e7bef1dfd5
The npm lockfile generation approach (npm install --package-lock-only) is unreliable for pnpm repos that have a packageManager field: corepack intercepts npm and the install fails, leaving no lockfile for npm audit. Skip npm audit entirely for pnpm repos. The pnpm audit endpoint is retired (HTTP 410) so there is no viable audit path for these repos anyway. Co-Authored-By: Paperclip <noreply@paperclip.ing>
169 lines
5.6 KiB
YAML
169 lines
5.6 KiB
YAML
name: Plugin CI
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
node-version:
|
|
description: 'Node.js version to use'
|
|
required: false
|
|
type: string
|
|
default: '22'
|
|
|
|
jobs:
|
|
ci:
|
|
runs-on: runners-privilegedescalation
|
|
timeout-minutes: 10
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Validate artifacthub-pkg.yml
|
|
run: |
|
|
python3 - <<'EOF'
|
|
import sys, re
|
|
try:
|
|
import yaml
|
|
except ImportError:
|
|
print("::warning::PyYAML not available, skipping artifacthub-pkg.yml validation")
|
|
sys.exit(0)
|
|
|
|
try:
|
|
with open("artifacthub-pkg.yml") as f:
|
|
pkg = yaml.safe_load(f)
|
|
except FileNotFoundError:
|
|
print("::error::artifacthub-pkg.yml not found")
|
|
sys.exit(1)
|
|
except yaml.YAMLError as e:
|
|
print(f"::error::artifacthub-pkg.yml is invalid YAML: {e}")
|
|
sys.exit(1)
|
|
|
|
errors = []
|
|
|
|
for field in ["version", "name", "description", "homeURL"]:
|
|
if not pkg.get(field):
|
|
errors.append(f"Missing required field: {field}")
|
|
|
|
version = pkg.get("version", "")
|
|
if version and not re.match(r'^\d+\.\d+\.\d+$', str(version)):
|
|
errors.append(f"version '{version}' is not SemVer (expected X.Y.Z)")
|
|
|
|
annotations = pkg.get("annotations", {}) or {}
|
|
archive_url = annotations.get("headlamp/plugin/archive-url", "")
|
|
archive_checksum = annotations.get("headlamp/plugin/archive-checksum", "")
|
|
|
|
if not archive_url:
|
|
errors.append("Missing annotation: headlamp/plugin/archive-url")
|
|
if not archive_checksum:
|
|
errors.append("Missing annotation: headlamp/plugin/archive-checksum")
|
|
elif not re.match(r'^sha256:[0-9a-f]{64}$', str(archive_checksum)):
|
|
errors.append(f"archive-checksum has unexpected format: '{archive_checksum}' (expected sha256:<64 hex chars>)")
|
|
|
|
if errors:
|
|
for e in errors:
|
|
print(f"::error::{e}")
|
|
sys.exit(1)
|
|
|
|
print(f"artifacthub-pkg.yml valid: name={pkg['name']} version={pkg['version']}")
|
|
EOF
|
|
|
|
- name: Detect package manager
|
|
id: pkg-manager
|
|
run: |
|
|
if [ -f "pnpm-lock.yaml" ]; then
|
|
echo "manager=pnpm" >> $GITHUB_OUTPUT
|
|
PM=$(python3 -c "import json,sys; d=json.load(open('package.json')); print('true' if d.get('packageManager','').startswith('pnpm@') else 'false')" 2>/dev/null || echo "false")
|
|
echo "has_package_manager=$PM" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "manager=npm" >> $GITHUB_OUTPUT
|
|
echo "has_package_manager=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v6
|
|
with:
|
|
node-version: ${{ inputs.node-version }}
|
|
cache: ${{ steps.pkg-manager.outputs.manager == 'npm' && 'npm' || '' }}
|
|
|
|
- name: Setup pnpm (via Corepack, reads version from packageManager field)
|
|
if: steps.pkg-manager.outputs.manager == 'pnpm' && steps.pkg-manager.outputs.has_package_manager == 'true'
|
|
run: |
|
|
npm install -g corepack
|
|
corepack enable pnpm
|
|
corepack install
|
|
|
|
- name: Setup pnpm (version latest)
|
|
if: steps.pkg-manager.outputs.manager == 'pnpm' && steps.pkg-manager.outputs.has_package_manager == 'false'
|
|
uses: pnpm/action-setup@v5
|
|
with:
|
|
run_install: false
|
|
version: latest
|
|
|
|
- name: Get pnpm store directory
|
|
id: pnpm-store
|
|
if: steps.pkg-manager.outputs.manager == 'pnpm'
|
|
run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Cache pnpm store
|
|
if: steps.pkg-manager.outputs.manager == 'pnpm'
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: ${{ steps.pnpm-store.outputs.dir }}
|
|
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-pnpm-
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
|
|
pnpm install --frozen-lockfile
|
|
else
|
|
npm ci
|
|
fi
|
|
|
|
- name: Build plugin
|
|
run: npx @kinvolk/headlamp-plugin build
|
|
|
|
- name: Lint
|
|
run: |
|
|
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
|
|
pnpm run lint
|
|
else
|
|
npm run lint
|
|
fi
|
|
|
|
- name: Type-check
|
|
run: |
|
|
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
|
|
pnpm run tsc
|
|
else
|
|
npm run tsc
|
|
fi
|
|
|
|
- name: Format check
|
|
run: |
|
|
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
|
|
pnpm run format:check
|
|
else
|
|
npm run format:check
|
|
fi
|
|
|
|
- name: Run tests
|
|
run: |
|
|
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
|
|
pnpm test
|
|
else
|
|
npm test
|
|
fi
|
|
|
|
- name: Security audit
|
|
run: |
|
|
# pnpm audit endpoint retired (HTTP 410). Use npm audit instead.
|
|
# pnpm projects lack package-lock.json so we generate one first.
|
|
# --no-audit skips the implicit audit during install (we run it explicitly after).
|
|
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
|
|
echo "Skipping npm audit for pnpm repo (pnpm audit endpoint retired HTTP 410; lockfile generation fails with corepack)"
|
|
else
|
|
npm audit --omit=dev
|
|
fi
|