* fix(plugin-release): correct PR merge logic for BLOCKED state
Prior releases failed with 'Resource not accessible by integration' when
gh pr merge was called with a branch name on a BLOCKED PR. The root cause
is that --auto requires the PR to have a pending status check that can be
satistfied by auto-merge. Without --auto, gh attempts an immediate merge
but the BLOCKED state (from branch protection requiring status checks)
causes GitHub to reject the push.
Fix: always use --auto for BLOCKED PRs, and refactor the polling loop so
it properly loops until mergeStateStatus is no longer UNKNOWN (up to 3
retries with exponential back-off) before deciding whether to use
--auto or merge directly.
Also fix the case where gh pr create is called without --json output, so
OPEN_PR is always captured correctly regardless of whether we created a
new PR or found a pre-existing one.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* fix: restore MERGED check and use PR number in retry loop
- Restore idempotent exit 0 when PR is already MERGED (regression from prior fix)
- Use $OPEN_PR instead of hardcoded branch name in gh pr view retry loop
- Fallback to --auto when UNKNOWN persists after exhausting retries (safe: auto-merge waits for branch protection)
Fixes bugs reported by Regression Regina on PR #133.
---------
Co-authored-by: Chris Farhood <chris@farhood.org>
Co-authored-by: Paperclip <noreply@paperclip.ing>
PRI-459: Adds 3-attempt retry wrapper (5s backoff) around the Install
dependencies step in plugin-ci.yaml and plugin-release.yaml to handle
transient npm/pnpm registry failures.
Co-authored-by: Chris Farhood <chris@farhood.org>
headlamp-plugin package strips the @ scope prefix and replaces / with -
when naming tarballs (e.g. @privilegedescalation/headlamp-argocd-plugin
becomes privilegedescalation-headlamp-argocd-plugin). The workflow was
using the raw package.json name without this transformation, causing
the Prepare release tarball step to fail when it couldn't find the
expected tarball file.
Co-authored-by: Chris Farhood <chris@farhood.org>
* feat(release): add token permission pre-check
Detect missing write permissions early in the release pipeline rather
than failing late during git push with a cryptic 403 error (see PRI-348).
The new check-token-permissions job generates a GitHub App token and
attempts to create a test ref via the API. On 201 the token has write
permission (cleaned up immediately); on 403 the release job is skipped
with a clear error message. This saves CI time and provides actionable
diagnostics.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* fix: skip dual approval check gracefully on dismissed reviews
When a pull_request_review event is dismissed, the PR context is null and
PR_NUMBER is empty. Instead of exiting with an error, exit 0 (skip) since
dismissed reviews are not approvals and do not affect the approval state.
Fixes PRI-314.
---------
Co-authored-by: Chris Farhood <chris@farhood.org>
Co-authored-by: Paperclip <noreply@paperclip.ing>
In GitHub Actions, local branches don't exist - only remote branches
under refs/remotes/origin/. This fixes the branch scanning loop to
scan remote branches instead of local refs/heads.
Also fixes the merge-base check to use the full remote ref path.
- Add ::warning:: annotation for git push --delete failures
- Change dry_run input to type: boolean for proper validation
- Handle null dry_run in scheduled runs (default to false)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Fixes two bugs in the auto-merge workflow PEM handling:
- echo may add trailing newline corrupting PEM content; use printf %s
- -binary flag in openssl dgst is unnecessary and removed
QA approved by privilegedescalation-qa (2026-04-21T20:24:46Z)
CTO approved by privilegedescalation-cto (2026-04-21T20:37:22Z)
Fixes PRI-173. Resolves PRI-179.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Replace pnpm audit and npm audit with audit-ci, which supports
the new npm bulk advisory endpoint (/-/npm/v1/security/advisories/bulk).
The old audit endpoints return HTTP 410 Gone.
Fixes: PRI-151
Co-authored-by: Test User <test@example.com>
Co-authored-by: Hugh Hackman <hugh@privilegedescalation.ai>
The pnpm audit endpoint returns HTTP 410 indicating it's retired.
Skip security audit for pnpm repos to unblock CI on plugin repos.
Co-authored-by: Paperclip <noreply@paperclip.ing>
After merging the release PR, verify that:
- The released tarball's SHA256 matches the tag's artifacthub-pkg.yml
- The released tarball's SHA256 matches main's artifacthub-pkg.yml
Fails loudly if they diverge so checksum drift is caught immediately.
Co-authored-by: privilegedescalation-ceo[bot] <269721483+privilegedescalation-ceo[bot]@users.noreply.github.com>
pnpm audit is available in pnpm v10+. The previous implementation
skipped the security audit for pnpm repos due to a retired endpoint,
which blocks all plugin releases that use pnpm.
gh CLI no longer supports --json mergeableState; the field is now
mergeStateStatus with uppercase enum values (BLOCKED, UNKNOWN, etc.)
Co-authored-by: privilegedescalation-ceo[bot] <269721483+privilegedescalation-ceo[bot]@users.noreply.github.com>
The 'Rebuild tarball' step caused a self-referential checksum failure:
1. 'Package plugin' runs headlamp-plugin package, which writes the tarball
checksum into artifacthub-pkg.yml on disk.
2. 'Rebuild tarball' ran headlamp-plugin package a second time. This second
tarball contains the updated artifacthub-pkg.yml (with the first checksum
embedded), so its SHA256 is different from what artifacthub-pkg.yml records.
3. The tool validates computed checksum vs artifacthub-pkg.yml and exits 1.
Fix: remove 'Rebuild tarball' and 'Validate rebuilt tarball' steps entirely.
The 'Package plugin' step already produces a correct tarball and checksum.
Co-authored-by: privilegedescalation-ceo[bot] <269721483+privilegedescalation-ceo[bot]@users.noreply.github.com>
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>
The previous fix (PR #92) added '2>/dev/null || true' to the npm install
command, silently swallowing failures. When npm install --package-lock-only
fails, no lockfile is created and npm audit fails with ENOLOCK.
Remove the silent suppression and --quiet flag so failures surface clearly.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Corepack requires Node to be set up first. The release job was failing
with 'corepack: command not found' because Setup pnpm (Corepack) ran
before Setup Node.
This aligns plugin-release.yaml with plugin-ci.yaml step ordering.
Fixes PRI-21
Co-authored-by: Pawla Abdul (Bot) <pawla@groombook.dev>
Detects when workflow runs conclude with action_required, which indicates
GitHub's 'Require approval for first-time contributors' setting is blocking
workflow runs from the privilegedescalation-engineer[bot] GitHub App.
This is a CI pipeline blocker that prevents bot-authored PRs from advancing
through the review pipeline. See PRI-44 for the full investigation.
Co-authored-by: Hugh Hackman <hugh@privilegedescalation.ai>
The pnpm registry audit endpoint is retired (HTTP 410).
Fix: for pnpm repos, run 'npm install --package-lock-only --ignore-scripts --quiet --no-audit'
to generate a package-lock.json from pnpm-lock.yaml metadata, then run npm audit.
For npm repos, continue using npm audit directly.
Use --audit-level=moderate to fail only on high/critical vulnerabilities,
not moderate ones, reducing noise from transitive dependencies.
Co-authored-by: Hugh Hackman <hugh@privilegedescalation>
Co-authored-by: Paperclip <noreply@paperclip.ing>
pnpm projects use pnpm-lock.yaml, not package-lock.json. The previous
fix switched from pnpm audit to npm audit but npm audit requires an
existing lockfile. Generate one first with npm install --package-lock-only.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Corepack is not pre-installed on runs-on: runners-privilegedescalation,
causing 'corepack: command not found' errors. Install it via
'npm install -g corepack' before using corepack commands.
Fixes PRI-51.
- Move rebuild step BEFORE checksum computation
- Add validation step after rebuild
- Remove redundant VERSION/PKG_NAME variable reassignments
- Checksum now computed from rebuilt tarball, not original
PR #81 adds pr_number as a required input, but the 5 calling
plugin repos don't yet pass this input. Change required: true
to required: false so the workflow_call can succeed without it,
while companion PRs are opened to add the input to each caller.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The dual-approval workflow was not re-triggering on pull_request_review events because the shared workflow was using github.event.pull_request.number which is not available in workflow_call context.
This change adds a required pr_number input to the reusable workflow.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The tarball was being created BEFORE the checksum was computed and
updated in artifacthub-pkg.yml. This meant the released tarball
contained a placeholder checksum instead of the actual SHA256 hash.
This change adds a step to rebuild the tarball after the checksum
is computed, ensuring the released artifact has the correct checksum.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The fail_on_unmatched_files: true causes the release step to exit 1
when the glob pattern doesn't match (e.g., TARBALL env var resolution
timing). Since the tarball existence is already validated earlier in
the workflow (lines 193-194), this additional check is redundant and
causes false failures on successful releases.
Fixes: https://github.com/privilegedescalation/headlamp-kube-vip-plugin/issues/32
Co-authored-by: Hugh Hackman <hugh@privilegedescalation>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Extracts the E2E test workflow shared by headlamp-polaris-plugin and
headlamp-intel-gpu-plugin into a reusable workflow_call workflow.
Plugin repos call this with:
uses: privilegedescalation/.github/.github/workflows/plugin-e2e.yaml@main
Inputs: node-version (default 22), headlamp-version (default v0.40.1).
Eliminates copy-paste duplication so any future E2E infra changes
(Headlamp version bumps, kubectl version, diagnostics) propagate to
all plugin repos from a single edit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
If a release workflow fails after creating the branch (e.g. pnpm setup
failure, network error) but before creating the tag, re-triggering the
workflow previously failed at 'git push origin $BRANCH' because the
branch already existed.
Changes:
- Commit and tag: check for existing remote branch and delete it before
re-creating, so re-triggers are clean. Safe because check-tag skips
when the tag already exists — we only reach this point when the tag
does NOT exist yet.
- Create PR: guard with 'gh pr view' so a pre-existing PR from a failed
run is reused instead of causing 'pr already exists' failure.
Split the single 'git push origin $BRANCH --tags' into two pushes
(branch and tag separately) to avoid any flag ambiguity.
The regex `^\d+\.\d+\.\d+` was missing a `$` end anchor, allowing
versions like `1.2.3.4` or `1.2.3extra` to pass validation.
Fixed to `^\d+\.\d+\.\d+$` for strict X.Y.Z matching.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Add a fast-fail step that validates artifacthub-pkg.yml before
the expensive build steps. Checks:
- File exists and is valid YAML
- Required fields present: version, name, description, homeURL
- Version is SemVer (X.Y.Z)
- archive-url and archive-checksum annotations are present
- archive-checksum format is sha256:<64 hex chars>
Catches corrupt or incomplete ArtifactHub manifests early in CI
before they reach the release workflow.
The release job used pnpm/action-setup@v5 without a version input,
which requires a packageManager field in package.json. Repos that
don't have this field fail at Setup pnpm, blocking all releases.
Mirror the resilient two-step pattern already used in plugin-ci.yaml:
- If packageManager is present: use Corepack (respects pinned version)
- If absent: fall back to pnpm/action-setup@v5 with version: latest
Fixes the systemic v1.0.0 release failures across kube-vip, sealed-secrets,
tns-csi, and rook (PRI-866).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The dual-approval-check workflow only makes GitHub API calls — it does
not need cluster access or any self-hosted tooling. Using the
self-hosted runner (runners-privilegedescalation) was triggering
GitHub's self-hosted runner approval requirement for workflows run by
actors with authorAssociation NONE (e.g. privilegedescalation-qa/cto
bots), causing action_required conclusions with 0 jobs executed.
Switching to ubuntu-latest eliminates the approval gate and frees
self-hosted runner capacity for actual CI builds.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
corepack is bundled with Node.js and only available on PATH after
actions/setup-node runs. The previous workflow ordered the corepack
enable/install step before setup-node, causing:
corepack: command not found
Fix: move setup-node to run first. Because pnpm is not installed when
setup-node runs, the built-in `cache: pnpm` cannot call `pnpm store path`.
Split pnpm caching into explicit Get/Cache steps using actions/cache@v4
after pnpm is installed via either corepack or pnpm/action-setup. npm
caching continues to use setup-node's built-in cache: npm.
Fixes polaris PR #103 CI (headlamp-polaris-plugin v1.0.0 release).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
node is not on PATH before the Setup Node step runs on ARC runners
(minimal Docker-based containers). The node -e command exits 127,
is silently swallowed by 2>/dev/null, and the || echo 'false' fallback
sets has_package_manager=false. This causes the Corepack branch to be
skipped and pnpm/action-setup@v4 to run with version:latest, which
conflicts with packageManager in package.json.
python3 is pre-installed on Ubuntu ARC runners (no setup required)
and reliably parses JSON via the stdlib json module.
Fixes pnpm version conflict on headlamp-polaris-plugin PR #103.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
pnpm/action-setup@v4 errors with "Multiple versions of pnpm specified"
even when no explicit version input is provided, if the repo has a
packageManager field in package.json.
Switch to Corepack for repos that pin their pnpm version via the
packageManager field. Corepack reads the version from package.json
directly and installs it without conflicting with pnpm/action-setup.
Repos without a packageManager field continue using pnpm/action-setup@v4
with version: latest (unchanged behavior).
Unblocks headlamp-polaris-plugin PR #103 (ci/pin-pnpm-version).
Co-Authored-By: Paperclip <noreply@paperclip.ing>