Compare commits

...

16 Commits

Author SHA1 Message Date
Countess von Containerheim 6996a63c2c Merge pull request 'fix(ci): inline CI workflow (PRI-1630)' (#18) from fix/pri-1630-inline-ci into main
CI / ci (pull_request) Failing after 9s
CI / ci (push) Failing after 9s
Dual Approval (CTO + QA) / dual-approval (pull_request) Failing after 0s
fix(ci): inline CI workflow (PRI-1630)
2026-05-20 10:47:33 +00:00
Countess von Containerheim 3972589532 fix(ci): inline CI workflow, remove reusable .github dependency (PRI-1630)
CI / ci (push) Failing after 7s
Dual Approval (CTO + QA) / dual-approval (pull_request) Failing after 0s
CI / ci (pull_request) Failing after 8s
2026-05-20 10:47:25 +00:00
Countess von Containerheim 1d1cb6babe Merge pull request 'fix(ci): pass pr_number to dual-approval-check workflow' (#11) from fix/dual-approval-pr-number into main
CI / ci (push) Failing after 8s
merge
2026-05-20 03:04:24 +00:00
Countess von Containerheim e66ea0dcd2 Merge pull request 'fix: add missing GITHUB_TOKEN to Renovate workflow' (#16) from gandalf/fix-renovate-token into main
CI / ci (push) Failing after 3s
fix: add missing GITHUB_TOKEN to Renovate workflow
2026-05-20 03:03:47 +00:00
privilegedescalation-engineer[bot] 46e7733cf5 chore(ci): add audit-ci allowlist for inherited @kinvolk/headlamp-plugin CVEs (PRI-855)
QA reviewed and approved. Adds audit-ci.jsonc with 3 CVE allowlist entries for dev-only dependencies.
2026-05-12 22:22:41 +00:00
Chris Farhood 23db059a23 fix: add missing GITHUB_TOKEN to Renovate workflow
The Renovate workflow was failing because the token parameter
was removed in commit 0955832. This commit restores the
required GITHUB_TOKEN parameter so Renovate can authenticate
and create PRs for dependency updates.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-11 23:06:37 +00:00
privilegedescalation-ceo[bot] fc5796d2ca chore(renovate): add self-hosted Renovate GitHub Action workflow
chore(renovate): add self-hosted Renovate GitHub Action workflow
2026-05-10 19:43:36 +00:00
Chris Farhood 0955832d4a chore(renovate): pin action to v40.3.0, fix inputs per spec 2026-05-06 11:04:51 +00:00
privilegedescalation-engineer[bot] b704a381d4 chore(renovate): add self-hosted Renovate GitHub Action workflow 2026-05-06 10:51:38 +00:00
Chris Farhood 066db0b902 fix(ci): pass pr_number to dual-approval-check workflow
Passes github.event.pull_request.number to the reusable workflow so
dual-approval status checks work correctly on PRs instead of always
receiving pr_number=0.
2026-05-06 02:18:50 +00:00
privilegedescalation-engineer[bot] 59cfa0bd78 fix: override elliptic for GHSA-848j-6mx2-7j84
* fix: override elliptic to patched version for GHSA-848j-6mx2-7j84

* chore: regenerate pnpm-lock.yaml for elliptic override

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Chris Farhood <chris@farhood.org>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-06 02:14:16 +00:00
privilegedescalation-ceo[bot] d30d4894cf Merge pull request #8 from privilegedescalation/fix/add-eslint-direct-dependency
fix: add eslint as direct devDependency (unblocks PRI-556, PRI-568)
2026-05-05 10:30:59 +00:00
Chris Farhood 514d306eea fix: add prettier as direct devDependency
prettier is needed by the format:check script but was only available
as a transitive dependency of @kinvolk/headlamp-plugin.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-04 20:00:49 +00:00
Chris Farhood f07a4c7775 fix: add missing direct devDependencies to package.json
This is a prerequisite for CI to work with pnpm --frozen-lockfile.

Missing direct devDependencies that were only available transitively:
- eslint (lint script needs it)
- typescript (tsc script needs it)
- vite (provides vite/client.d.ts type definitions)
- vite-plugin-svgr (provides vite-plugin-svgr/client.d.ts type definitions)

Also fixed: tsconfig.json was missing skipLibCheck: true which caused
errors when type definitions referenced packages not in node_modules.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-04 19:58:07 +00:00
Chris Farhood b204491808 fix: add typescript as direct devDependency (fixes tsc not found)
PR #8 revealed that typescript is also missing as a direct dependency.
The tsc script calls 'tsc --noEmit' but typescript was only available
as a transitive dependency, causing CI to fail with 'tsc: not found'.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-04 19:53:42 +00:00
Chris Farhood 8600cedb64 fix: add eslint as direct devDependency
ESLint was only a transitive dependency of @kinvolk/headlamp-plugin.
Without it as a direct devDependency, CI fails at the lint step with
'eslint: not found' when using --frozen-lockfile.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-04 19:51:07 +00:00
7 changed files with 11885 additions and 4 deletions
+202 -4
View File
@@ -2,12 +2,210 @@ name: CI
on:
push:
branches: [main]
branches: ['**']
pull_request:
branches: [main]
branches: [main, dev, uat]
workflow_dispatch:
workflow_call:
permissions:
contents: read
jobs:
ci:
uses: privilegedescalation/.github/.github/workflows/plugin-ci.yaml@main
runs-on: ubuntu-latest
timeout-minutes: 10
container: node:22-slim
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Python
run: apt-get update && apt-get install -y --no-install-recommends python3 python3-yaml
- 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: '22'
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: Validate pnpm lockfile freshness
if: steps.pkg-manager.outputs.manager == 'pnpm'
run: |
if [ ! -f "pnpm-lock.yaml" ]; then
echo "No pnpm-lock.yaml found, skipping lockfile freshness check"
exit 0
fi
if ! grep -q 'overrides:' pnpm-lock.yaml 2>/dev/null; then
echo "No overrides section in pnpm-lock.yaml, skipping lockfile freshness check"
exit 0
fi
echo "Detected pnpm-lock.yaml with overrides section. Checking lockfile freshness..."
ERR_FILE=$(mktemp)
if pnpm install --frozen-lockfile 2>&1 | tee "$ERR_FILE"; then
echo "Lockfile is fresh."
else
if grep -q "CONFIG_MISMATCH\|EBADLOCKFILE\|ERR_PNPM_LOCKFILE" "$ERR_FILE"; then
echo ""
echo "::error::pnpm-lock.yaml is out of sync with package.json overrides."
echo "::error::Run 'pnpm install' to regenerate the lockfile and commit the updated pnpm-lock.yaml."
rm -f "$ERR_FILE"
exit 1
fi
rm -f "$ERR_FILE"
echo "::warning::Install failed with a different error. Will retry in the Install dependencies step."
fi
- name: Install dependencies
run: |
max_attempts=3
attempt=1
while [ $attempt -le $max_attempts ]; do
echo "Attempt $attempt of $max_attempts"
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
pnpm install --frozen-lockfile && break
else
npm ci && break
fi
if [ $attempt -lt $max_attempts ]; then
echo "::warning::Install step failed on attempt $attempt. Retrying in 5 seconds..."
sleep 5
fi
attempt=$((attempt + 1))
done
if [ $attempt -gt $max_attempts ]; then
echo "::error::Install step failed after $max_attempts attempts."
exit 1
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: |
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
npx audit-ci --pnpm --audit-level=high --config ./audit-ci.jsonc
else
npx audit-ci --npm --audit-level=high --config ./audit-ci.jsonc
fi
+2
View File
@@ -15,4 +15,6 @@ on:
jobs:
dual-approval:
uses: privilegedescalation/.github/.github/workflows/dual-approval-check.yaml@main
with:
pr_number: ${{ github.event.pull_request.number }}
secrets: inherit
+15
View File
@@ -0,0 +1,15 @@
name: Renovate
on:
schedule:
- cron: '0 3 * * *'
workflow_dispatch:
jobs:
renovate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: renovatebot/github-action@v40.3.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
configurationFile: renovate.json
renovate-json5: true
+20
View File
@@ -0,0 +1,20 @@
{
// Allowlist for inherited dev-dependency CVEs from @kinvolk/headlamp-plugin
// CTO decision (PRI-854): these high-severity vulns are dev/build-time only,
// trace to @kinvolk/headlamp-plugin transitive deps (Picomatch, Vite, lodash),
// and do NOT ship in production plugin artifacts.
"allowlist": [
{
"id": "GHSA-hhpm-516h-p3p6",
"reason": "Picomatch ReDoS: devDependency only, does not ship in production plugin bundle"
},
{
"id": "GHSA-36xf-7xpp-53w5",
"reason": "Vite arbitrary file read: devDependency only, does not ship in production plugin bundle"
},
{
"id": "GHSA-jf8v-p3pp-93qh",
"reason": "lodash code injection via _.template: devDependency only, does not ship in production plugin bundle"
}
]
}
+10
View File
@@ -29,10 +29,20 @@
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"eslint": "^8.57.0",
"jsdom": "^24.0.0",
"prettier": "^3.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^5.3.0",
"typescript": "^5.6.2",
"vite": "^6.4.1",
"vite-plugin-svgr": "^4.5.0",
"vitest": "^3.0.5"
},
"pnpm": {
"overrides": {
"elliptic": ">=6.6.1"
}
}
}
+11635
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -2,6 +2,7 @@
"extends": "@kinvolk/headlamp-plugin/config/plugins-tsconfig.json",
"compilerOptions": {
"jsx": "react",
"skipLibCheck": true,
"types": ["vite/client", "vite-plugin-svgr/client", "vitest/globals", "@testing-library/jest-dom"]
},
"include": ["src"]