Updates all workflow files and actionlint config to use ubuntu-latest
instead of the deprecated runners-privilegedescalation self-hosted runner.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The --json flag is not valid for gh pr create, only for read commands
like gh pr list and gh pr view. This was causing the release workflow
to fail with 'unknown flag: --json' in the Create PR step.
The PR number is correctly retrieved on the line after via gh pr list,
so no other change was needed.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds 'infra' to PLUGIN_REPOS after the discovery/fallback logic so the
private infra repo is always included in CI/CD health checks regardless
of which path populated PLUGIN_REPOS.
Fixes: PRI-906
Fixes: PRI-488
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Both the Update artifacthub-pkg.yml and Prepare release tarball steps now read PKG_NAME from artifacthub-pkg.yml when present, falling back to package.json with correct @org/ prefix stripping. This eliminates the archive-url/tarball name mismatch for 6 of 7 plugins.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When pnpm-lock.yaml has overrides section, validate that lockfile is fresh before install. If stale (detected via CONFIG_MISMATCH/EBADLOCKFILE/ERR_PNPM_LOCKFILE), fail with clear error message suggesting 'pnpm install' to regenerate.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When pnpm-lock.yaml has overrides section, validate that lockfile is fresh
before install. If stale (detected via CONFIG_MISMATCH), fail with clear
error message suggesting 'pnpm install' to regenerate.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The detection script was missing infra/, org/, Dockerfile,
docker-compose*, and Makefile patterns required by the SDLC spec.
Added 11 new test cases covering these patterns.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Fix subdirectory matching: use prefix match for .github/* paths
instead of exact dirname match (fixes .github/workflows/ not matching)
- Upgrade tj-actions/changed-files from v44 to v47 (Node 24 support)
- Extract detection logic into scripts/detect-pipeline.sh for testability
- Add 22 automated tests in scripts/test-detect-pipeline.sh covering
infra-only, plugin code, mixed, and edge cases
- Add test-detection-logic CI job to run tests on every PR
- Update README.md to reference v47
cc @cpfarhood
Co-Authored-By: Paperclip <noreply@paperclip.ing>
New model: no review for dev PRs, QA gates uat, UAT gates main.
Replaces the old CTO+QA dual-approval check.
Co-authored-by: Chris Farhood <chris@farhood.org>
Co-authored-by: Paperclip <noreply@paperclip.ing>
When MERGE_STATE is BLOCKED or UNKNOWN, the workflow attempts --auto
first. If that fails due to autoMergeAllowed: false on the repo, it
falls back to --admin which merges using the GitHub App token and
bypasses branch protection rules.
Resolves: PRI-497
Co-authored-by: Chris Farhood <chris@farhood.org>
Documents available tools on runners and common patterns for GitHub Actions.
Notably, clarifies that gh CLI is not available and recommends using curl
with GitHub API instead.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Adds workflow that detects Pipeline A vs Pipeline B based on changed files
- Pipeline B (infra-only): .github/, *.md, .eslintrc*, .prettierrc*, renovate.json*, .gitignore, .editorconfig, LICENSE
- Pipeline A (default): any other file changes
- Sets PR label (pipeline-a or pipeline-b) for downstream routing
- Reusable workflow can be called from any PR
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The shared plugin-e2e.yaml workflow lacks a Get kubeconfig step. The
ARC runner (runners-privilegedescalation) has no static kubeconfig at
any expected path (/runner/config, ~/.kube/config). It DOES have an
in-cluster service account at /var/run/secrets/kubernetes.io/serviceaccount/token.
This fix adds the same three-tier kubeconfig detection used in
headlamp-polaris-plugin#144:
1. /runner/config (not present on this runner)
2. ~/.kube/config (not present on this runner)
3. Generate from in-cluster service account credentials
This unbreaks E2E for all plugins using the shared workflow:
- headlamp-argocd-plugin
- headlamp-kube-vip-plugin
- headlamp-tns-csi-plugin
Co-authored-by: Chris Farhood <chris@farhood.org>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Add --config ./audit-ci.jsonc to audit-ci step so plugin repos can
provide their own allowlist for inherited @kinvolk/headlamp-plugin
dev-dependency CVEs (CTO decision PRI-854).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit updates ci-health-check.sh to categorize CI failures:
- Code failures: test/lint/build failures on main → FAIL
- Infra failures: startup_failure, timed_out → FAIL
- Pending (process): action_required (awaiting review) → INFO only
action_required is no longer treated as a failure since it's an expected
process state (PRs awaiting dual approval).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The workflow was failing on pull_request_review events when triggered by
non-PR actors (e.g. greptile-apps[bot] commenting). The dual-approval job
would attempt to call the reusable workflow with a null PR number,
causing the reusable workflow to fail since there was no valid PR to check.
Changes:
- Guard the PR number with explicit null check: [ -z "${PR_NUMBER}" ] || [ "${PR_NUMBER}" = "null" ]
- Add validation of the reviews response before processing
- Fix jq filter to handle null pipeline values explicitly
Fixes flapping Dual Approval (CTO + QA) checks across all plugin repos.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
PR #115's first commit landed dynamic discovery via gh api but missed
three of the five issue requirements. This commit completes them:
- Move headlamp- prefix filtering into jq via startswith() and add
explicit exclusion for headlamp-agent-skills (skills bundle, not a
plugin), instead of relying on grep -E '^headlamp-.+'.
- Add PLUGIN_REPOS_FALLBACK with the previously hardcoded list and
use it when discovery returns empty, instead of exiting with error.
- Add header comment documenting the discovery filter and the
headlamp-agent-skills exclusion.
Verified jq filter against live API: returns 8 plugin repos, all
prefixed headlamp-, headlamp-agent-skills correctly excluded.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Use gh api --paginate to dynamically fetch all non-archived public repos
matching ^headlamp-.+ from the privilegedescalation org. This eliminates
the need to manually update the repo list when new plugins are added.
NOTE: --paginate must come before the endpoint arg, not after --jq.
The previous commit had 'gh api paginate' which is incorrect syntax.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* 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>
Resolve conflict: keep stale-release-cleanup.yaml from feature branch.
Main had this file reverted (cleanup of direct push), feature branch has
the correct fixed version which this PR is introducing.
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>
- 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>
- Use git merge-base --is-ancestor instead of git log --merges
--ancestry-path for reliable merge detection (works with squash
merges and rebases)
- Narrow v* glob to v[0-9]* to avoid matching vendor/ or similar
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>
This script was previously unversioned at /paperclip/privilegedescalation/agents/.
Moving it here enables proper PR-based review of changes.
The script generates GitHub App installation access tokens by:
1. Building a JWT using the GitHub App ID and PEM key
2. Fetching the installation ID
3. Exchanging for an installation access token
Used by all agents for GitHub API access.
Co-authored-by: Hugh Hackman <hugh@privilegedescalation>
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>
Adds explicit packageRules for major version bumps on both github-actions
and npm managers. Previously only minor/patch updates were configured,
requiring manual audits when major versions shipped (e.g. PRI-802 where
actions/setup-node v4→v6 had to be found and fixed by hand).
With these rules, Renovate will surface major bumps as PRs automatically.
automerge is false for both — major updates go through the normal
dual-approval workflow.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds `pinDigests: true` to the org-wide Renovate config. Renovate will
now automatically pin all GitHub Actions references to full commit SHAs
and keep them updated via weekly PRs.
This implements the supply-chain hardening goal from PRI-731 without
requiring a one-time manual SHA substitution that would quickly become
stale. Renovate handles pin creation and ongoing updates, eliminating
the toil.
The github-actions packageRule is preserved — Renovate will still group
minor/patch action tag updates, and each group PR will include the
corresponding SHA pins.
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>
GitHub App reviews are submitted as `privilegedescalation-cto[bot]`
and `privilegedescalation-qa[bot]`, not the bare usernames used in the
workflow defaults. The jq filter now accepts both the plain username and
the `[bot]`-suffixed form, so the check passes regardless of whether the
review was submitted via the GitHub App or a regular account.
Fixes: https://github.com/privilegedescalation/.github/issues/51
Co-Authored-By: Paperclip <noreply@paperclip.ing>
pnpm/action-setup@v4 errors with ERR_PNPM_BAD_PM_VERSION when both
`version` (in the workflow) and `packageManager` (in package.json) are
specified. Remove the hardcoded `version: latest` from plugin-release
so that repos can pin their pnpm version via the packageManager field
in package.json.
When packageManager is absent the action falls back to latest (same
prior behavior). When packageManager is set it is used exclusively,
which prevents silent version drift.
The plugin-ci.yaml change is handled separately in PR #54.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
pnpm/action-setup@v4 errors when both the `version` input and a
`packageManager` field in package.json are specified. Detect the
packageManager field during the package-manager detection step and
conditionally omit `version: latest` when it is present.
Fixes CI failures on repos using Corepack-style pnpm version pinning
(e.g. headlamp-polaris-plugin PR #103).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The gh CLI is not installed on the self-hosted ARC runners
(runners-privilegedescalation). Replace the gh api call with
curl + GitHub token, which is available on all runners.
Fixes: https://github.com/privilegedescalation/.github/issues/50
Unblocks: headlamp-polaris-plugin PR #98 and v1.0.0 release pipeline
Mirrors the pnpm-detection logic from plugin-ci.yaml. When a repo has
pnpm-lock.yaml, the release job now: sets up pnpm, caches with pnpm,
runs pnpm install --frozen-lockfile, and commits pnpm-lock.yaml (not
package-lock.json) in the release branch.
Fixes the CI/release divergence where headlamp-polaris-plugin's CI used
pnpm strict hoisting but releases installed with npm, allowing dependency
resolution differences to reach production.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Previously the jq logic checked if *any* review from CTO/QA had
state == APPROVED. This allowed a PR to pass dual-approval even if
the reviewer subsequently requested changes — because the earlier
approval was still in the review history.
Fix: filter reviews by user, take the last one, and check its state.
This ensures a CHANGES_REQUESTED review after an approval correctly
blocks the check.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
pnpm/action-setup@v4 requires either a version input or a packageManager
field in package.json. Repos with pnpm-lock.yaml but no packageManager
field were failing with "No pnpm version is specified."
Adding version: latest as a fallback allows the action to install the
latest stable pnpm when packageManager is not set. Repos that do specify
packageManager in package.json continue to use their pinned version.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds a shared reusable workflow that plugin repos can call to enforce
the dual CTO+QA approval policy as a GitHub required status check.
The workflow queries the GitHub API for PR reviews and fails unless
both privilegedescalation-cto and privilegedescalation-qa have approved.
Triggered via pull_request and pull_request_review events in calling
repos, producing a clear "Dual Approval (CTO + QA)" status check.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The multi-line --body string had cc @cpfarhood at column 0, which
terminated the YAML literal block scalar prematurely and caused
actionlint to reject the workflow file. Use printf to construct
the body string without embedding a literal newline in the YAML.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When pnpm-lock.yaml is present, use pnpm for install, lint, type-check,
format check, tests, and security audit instead of npm. Repos using npm
are unaffected (falls back to existing npm behavior).
This fixes the npm/pnpm inconsistency in headlamp-polaris-plugin where
local development uses pnpm but CI used npm, causing:
- Different transitive dependency resolution (TypeScript not hoisted)
- Different audit results (pnpm audit vs npm audit)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All PRs must include cc @cpfarhood. The automated release PR
body generated by plugin-release.yaml was missing this.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Exclude E2E Tests from CI failure count (keeps CI/CD noise separate)
- Add dedicated E2E warning line for main branch failures (PRI-494)
- Move Release failure warning outside the else block — always report it
- Update Release warning comment: graceful skip is now in place, so
failures are real errors not just missing-secrets noise
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The CI/CD health check uses GITHUB_TOKEN which only has access to
the .github repo. Listing workflow runs across the 6 plugin repos
requires org-wide access, causing all repos to show "WARNING: No
workflow runs found".
Fix: generate a GitHub App token (using RELEASE_APP_ID/RELEASE_APP_PRIVATE_KEY,
same as the release workflow) scoped to the org before running the
health check script. Falls back to GITHUB_TOKEN gracefully via
continue-on-error if the secrets are not yet configured.
Once RELEASE_APP_ID is configured as an org secret (tracked separately),
the health check will produce accurate cross-repo CI data.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds a check-secrets job that runs before any expensive work. When
RELEASE_APP_ID is empty (org secret not yet set, tracked in PRI-380),
the workflow exits cleanly with a notice instead of running the full
build and failing at the GitHub App token step.
Previously this left dangling state: a pushed tag, a GitHub Release,
and a release branch — but no version-bump PR. Now the workflow skips
all of that and exits clean.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Replace node -e JSON parsing with jq (available on our runners)
- Exclude Release workflow failures from FAIL count — these fail at
the post-release PR-creation step due to missing RELEASE_APP org
secrets (tracked in PRI-380), not actual CI breakage
- Demote Release failures to WARN so the health check exits 0 when
only Release is broken, giving clean signal for real CI problems
- Increase run limit from 5 to 10 for better intermittent failure detection
- Remove unnecessary Node.js setup step from the workflow
Co-Authored-By: Paperclip <noreply@paperclip.ing>
PR .github#32 proposed adding a new renovate.json scoped to github-actions
with prConcurrentLimit: 5, but that would override the existing
renovate-config.json and silently drop npm dependency updates.
Instead, incorporate the limit change directly into the canonical
renovate-config.json which already covers both npm and github-actions.
Co-authored-by: Gandalf the Greybeard <gandalf@privilegedescalation.ai>
Co-authored-by: Paperclip <noreply@paperclip.ing>
* fix: skip duplicate release gracefully when tag already exists
Replace inline exit-1 tag check with a dedicated check-tag job that uses
the GitHub API. When the tag already exists, check-tag outputs skip=true
and the release job is conditionally skipped via if: condition. Workflow
now reports success (not failure) for duplicate release attempts.
Fixes#30 (partial) — resolves the tag-already-exists failure mode.
Co-Authored-By: Hugh Hackman <hugh@privilegedescalation.io>
* fix: use curl instead of gh CLI in check-tag job for portability
gh CLI may not be pre-installed on ARC runners. curl is always available
in container images. Avoids potential startup failure if gh binary is absent.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* fix: drop -f flag from curl in check-tag to avoid exit on 404
With -f, curl exits non-zero when the tag does not exist (404). In GitHub
Actions bash steps (set -e), this could cause the step to fail before the
if-block runs. Using -s alone: curl always exits 0 on network success,
HTTP_CODE is captured correctly for both 200 and 404 cases.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
---------
Co-authored-by: Hugh Hackman <hugh@privilegedescalation.io>
Co-authored-by: Paperclip <noreply@paperclip.ing>
The org blocks GITHUB_TOKEN from creating pull requests
("Write permissions for workflows are disabled by the organization").
Switch to a GitHub App installation token generated via
actions/create-github-app-token for the PR creation step.
Requires org-level secrets RELEASE_APP_ID and RELEASE_APP_PRIVATE_KEY
to be configured. Calling workflows must pass these secrets.
Closes#30
Co-authored-by: Hugh Hackman <hugh@privilegedescalation.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
ARC runner containers run as non-root, so `mv` to /usr/local/bin fails
with permission denied. Install to $HOME/.local/bin instead and add to
GITHUB_PATH.
Co-authored-by: Hugh Hackman [bot] <hugh-hackman[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
ARC runner scale set was recreated on 2026-03-19 with label
`runners-privilegedescalation` but all shared workflows still referenced
`local-ubuntu-latest`. This label mismatch caused startup_failure on
every Release workflow and queued CI jobs with no runner to pick them up.
Updates all 4 workflows and the actionlint config to match the current
ARC runner scale set label.
Closes#27
The kube-vip plugin has been on ArtifactHub but the org profile
still showed "—" for its badge. All 6 plugins now have badges.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The self-hosted runner doesn't have xz installed, so extracting the
shellcheck tar.xz release fails. Use apt-get install instead.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The shellcheck step fails with "command not found" because shellcheck
is not installed on the runner. Install it from GitHub releases, same
pattern as the actionlint install step.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The runner doesn't have write access to /usr/local/bin. Install to
$HOME/.local/bin instead and add it to GITHUB_PATH.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The .github repo had no CI running on pull requests — PRs merged without
any validation. This adds actionlint for workflow YAML and shellcheck for
scripts in .github/scripts/, triggered on PRs to main.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
actions/checkout v6 was already adopted in headlamp-agent-skills.
This brings the org-level reusable workflows (plugin-ci, plugin-release,
ci-health-check) up to the same version. Affects all plugin repos that
call these shared workflows.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The apt-based gh CLI install requires sudo which is not available on our
self-hosted container runners. Replace with a direct binary download from
GitHub releases that works without elevated permissions.
Fixes the "gh: command not found" error in the release workflow's
"Create PR for version bump" step.
Co-authored-by: Hugh Hackman <hugh@privilegedescalation.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
The self-hosted runner (local-ubuntu-latest) does not have gh CLI
pre-installed, causing the PR creation step to fail with
"gh: command not found" after the release is published.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The release PR is just a version bump + checksum update. Enable
auto-merge with squash and delete the release branch after merge
to prevent branch accumulation.
The release workflow pushed directly to main which fails on repos
with branch protection enabled. This broke the polaris plugin v0.7.0
release.
Changes:
- Create release/vX.Y.Z branch instead of committing to main
- Push to the release branch + tags
- Create a PR to merge the version bump back to main
- Add pull-requests: write permission
Fail fast when a release tag already exists instead of running the
full build+package cycle only to fail at git push. Saves CI time on
duplicate workflow_dispatch triggers.
Adds a security audit step (npm audit --omit=dev) to catch known
vulnerabilities in production dependencies. Runs after tests so build
failures are reported before audit findings. Uses --omit=dev to focus
on production-facing risk.
This covers all 6 plugin repos that use the shared workflow.
All 6 plugin repos use identical Renovate configs. This org-level
preset provides a single source of truth. Plugin repos can extend
it with: "extends": ["local>privilegedescalation/.github:renovate-config"]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
if [ "${{ steps.app-token.outcome }}" = "success" ]; then
echo "Using GitHub App token for cross-repo access"
else
echo "::warning::RELEASE_APP_ID not configured — using GITHUB_TOKEN. Cross-repo workflow run data will be unavailable. Configure RELEASE_APP_ID org secret to enable full health check."
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
**Industry Commentary Batch**: Establishes voice as operators who understand the gap between aspirational documentation and actual practices. Posts 1-3 are safe/immediately postable. Posts 4-5 are edgier but worth discussing. Posts 6-7 are evergreen.
**Why We Built These Batch**: Pain-point education that builds context before KubeCon. Each post has specific use case + why we built it. Strong candidate for pre-conference posting to establish credibility.
**KubeCon Campaign**: Rides #KubeCon conversation without forcing. Mix of self-deprecation ("1 star"), technical depth, and community positioning. Marquee post (March 26 ecosystem thread) should drive meaningful traffic.
---
## Git Branch Reference
```
d05b1f5 [social] batch: Industry commentary on Kubernetes ops culture
ba5a95e [content] technical changelog: March 9 releases and updates
f15f4c1 [social] batch: slow-burn curiosity post - K8s maturity gap awareness
b00be78 [social] batch: Why We Built These — problem-solution narrative for 6 plugins
f55dc48 [social] batch: March 9 releases + PureTensor community moment
0e07503 Draft KubeCon EU 2026 social posts — 6 posts for March 21-27
```
---
## Appendix: Full Content Titles
**Social Batches**
- Industry Commentary: observability theater, maintainer bottleneck, README as docs, consolidation trap, observability checkboxes, dependency hell, platform team reality
- Why We Built These: 6 posts (one per plugin, pain point + solution)
- March 9 + PureTensor: releases news + community moment
- Slow-Burn Curiosity: "The Dashboard You Don't Know You Need" (3 platform variants)
- March 9 Releases Technical Changelog: versioned feature list + upgrade guide
- (Already deployed) Intro Blog Post
---
**Status**: Ready to ship on authorization. All content is quality-checked and voice-consistent. Awaiting GitHub auth resolution and CMO schedule approval.
There's a particular kind of optimism that only exists in open source. It's the belief that if you build something genuinely useful, put it on GitHub, list it on Artifact Hub, write actual documentation, and then wait — someone will eventually find it.
We're currently in the "wait" phase.
## What We Actually Built
Privileged Escalation makes [Headlamp](https://headlamp.dev/) plugins. If you don't know what Headlamp is: it's a CNCF-listed Kubernetes dashboard that was designed to be extended. If you don't know what Kubernetes is, this blog post is going to be a rough ride.
We have six plugins. Each one takes something you'd normally do with `kubectl`, a terminal, and quiet desperation, and puts it in a web UI that your teammates might actually use.
**[headlamp-polaris-plugin](https://github.com/privilegedescalation/headlamp-polaris-plugin)** — Surfaces Fairwinds Polaris audit results directly in Headlamp. Cluster score in the app bar, per-namespace breakdowns, exemption management from the UI instead of annotation YAML editing. Recently hit v0.6.0 with dark mode support, because apparently that's what it takes to be taken seriously in 2026.
**[headlamp-tns-csi-plugin](https://github.com/privilegedescalation/headlamp-tns-csi-plugin)** — TrueNAS CSI driver visibility and storage benchmarking via kbench. If you've ever wondered whether your NFS share is actually performing the way iX Systems promised, this is the plugin that tells you the uncomfortable truth.
**[headlamp-rook-plugin](https://github.com/privilegedescalation/headlamp-rook-plugin)** — Rook-Ceph cluster health, pool status, and CSI driver monitoring. For people who chose distributed storage and now live with the consequences.
**[headlamp-sealed-secrets-plugin](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin)** — Bitnami Sealed Secrets management with client-side RSA-OAEP and AES-256-GCM encryption. Your plaintext never leaves the browser. We're fairly proud of this one, which is why it hurts that it has zero stars.
**[headlamp-intel-gpu-plugin](https://github.com/privilegedescalation/headlamp-intel-gpu-plugin)** — Intel GPU device visibility and resource monitoring. For the subset of people running Intel GPUs in Kubernetes, which is a smaller group than Intel's marketing department would like.
**[headlamp-kube-vip-plugin](https://github.com/privilegedescalation/headlamp-kube-vip-plugin)** — kube-vip virtual IP and load balancer visibility. Because sometimes you just need to know if the VIP is actually where it's supposed to be.
## Why Headlamp Plugins
The Kubernetes dashboard space is... let's call it "stratified." There are expensive commercial options that do everything. There are free options that do almost nothing. And then there's Headlamp, which does a reasonable amount and lets you extend it.
We chose the extension path. Every plugin installs through Headlamp's native plugin system — no separate deployments, no new URLs to bookmark, no "please also install this sidecar that needs its own RBAC." You add a plugin and it appears in the sidebar. That's it.
This matters because the alternative is what most teams actually do: they `kubectl` their way through everything, pipe JSON through `jq`, and call it observability. It works. It's also miserable if you're trying to onboard anyone who doesn't have muscle memory for `kubectl get pods -n rook-ceph -o jsonpath='{.items[*].status.phase}'`.
## The Honest Part
We launched all six plugins in the same week. Combined star count across all repos: zero. Combined fork count: one, and we're not entirely sure it was intentional.
Our CI is sometimes in a state that could charitably be described as "aspirational." We filed a bug against ourselves about E2E tests that have never passed because we haven't set up the test infrastructure yet. We committed LICENSE badges to READMEs before we committed the actual LICENSE files.
This is normal. This is what early open source looks like before the narrative gets cleaned up. We'd rather be honest about it than pretend we emerged fully formed with 200 stars and a contributor covenant.
## What's Next
We're working on getting every plugin listed on Artifact Hub with proper metadata, fixing the CI pipelines that are currently failing for reasons ranging from "missing secrets" to "format check disagreements," and writing the kind of documentation that makes people confident enough to actually install something.
If you run Headlamp and any of these plugins sound useful, try one. If something breaks, file an issue. If it works and you like it, a star would be nice. We're not above admitting that.
All plugins are Apache-2.0 licensed. All repos are at [github.com/privilegedescalation](https://github.com/privilegedescalation).
We build open source [Headlamp](https://headlamp.dev) plugins that bring deep visibility into Kubernetes storage, networking, GPU, and security subsystems — right inside your cluster dashboard.
## Our Plugins
| Plugin | What it does | Artifact Hub |
|--------|-------------|:---:|
| [headlamp-rook-plugin](https://github.com/privilegedescalation/headlamp-rook-plugin) | Rook-Ceph cluster health, pool status, and CSI driver monitoring | [](https://artifacthub.io/packages/headlamp/headlamp-rook-plugin/headlamp-rook-plugin) |
| [headlamp-kube-vip-plugin](https://github.com/privilegedescalation/headlamp-kube-vip-plugin) | kube-vip virtual IP and load balancer visibility | [](https://artifacthub.io/packages/headlamp/headlamp-kube-vip/headlamp-kube-vip) |
## Why Headlamp?
Headlamp is a CNCF-listed Kubernetes dashboard built for extensibility. Our plugins slot in natively — no separate UIs, no context switching. If you run Headlamp, you can add any of our plugins with a single command.
## Get Started
Every plugin is installable via the Headlamp plugin system. See individual repos for install instructions.
## Contributing
We welcome contributions, bug reports, and feature requests. Open an issue on any repo or start a discussion. All projects are licensed under Apache 2.0.
## Sponsor
If these plugins save your team time, consider [sponsoring our work](https://github.com/sponsors/privilegedescalation). Sponsorship funds go directly toward new plugin development and maintenance.
First-ever social batch for Privileged Escalation. The org has 6 Headlamp plugins across storage, security, and infrastructure -- all freshly released, all at zero stars. The play here is name recognition and curiosity: make people encounter "Privileged Escalation" in their feed and wonder what it is before they click. Leading with the sealed-secrets plugin (client-side crypto angle) and the absurdity of launching 6 plugins to zero fanfare.
---
## 1. Ready to Post
### Post 1
**Platform**: Twitter/X
**Post**:
We shipped 6 Kubernetes Headlamp plugins and nobody noticed.
Storage benchmarking, Rook-Ceph visibility, Polaris auditing, Sealed Secrets with actual client-side encryption, Intel GPU monitoring, and kube-vip dashboards.
Zero stars across the board. We are crushing it.
github.com/privilegedescalation
**CMO Note**: Self-deprecating launch acknowledgment. The honesty about zero stars is the hook -- it reads as human, not corporate. Links to the org for curious clicks.
---
### Post 2
**Platform**: Bluesky
**Post**:
the sealed secrets headlamp plugin does client-side RSA-OAEP + AES-256-GCM encryption so your plaintext never leaves the browser.
someone forked it last month. we have our first user. or our first person who accidentally clicked fork. either way, we are celebrating.
**CMO Note**: Technical specificity makes it credible. The fork joke (sm-moshi, Feb 22) is real and plays well on Bluesky's irony-friendly audience. Seeds curiosity about what Headlamp plugins are.
---
### Post 3
**Platform**: Mastodon
**Post**:
Genuine question for the fediverse: if you have 6 open source projects and zero stars on any of them, are you a software company or just a guy with a lot of repos?
Asking for a friend. The friend is github.com/privilegedescalation.
**CMO Note**: Mastodon audience appreciates self-aware humor. This is pure slow-burn -- raises the question of what Privileged Escalation is without explaining it. The link is there for anyone curious enough to click.
---
## 2. Risky but Worth Discussing
### Post 4
**Platform**: Twitter/X
**Post**:
Every Kubernetes UI either costs money or looks like it was designed during a mass layoff event.
We've been building Headlamp plugins that make the free one actually useful. Rook-Ceph dashboards, Polaris auditing, storage benchmarks -- the stuff you duct-tape together with kubectl and regret.
github.com/privilegedescalation
**CMO Note**: Mildly spicy take on the K8s UI landscape. Does not name competitors directly but the implication is clear. Could rub Lens/Rancher people the wrong way. Worth discussing tone.
---
## 3. Backlog (Evergreen)
### Post 5
**Platform**: LinkedIn
**Post**:
We just audited our own GitHub repos and found that 4 out of 6 were missing LICENSE files.
They all had Apache-2.0 badges in the README. The actual license text? Not present. Technically, anyone using our code was operating on vibes and good faith.
Fixed now. But if your open source project has a license badge and no LICENSE file, maybe go check. We'll wait.
**CMO Note**: Honest product personality at work. Admitting a real flaw (that we just fixed) builds trust and is genuinely useful advice. LinkedIn audience will share practical open source governance content.
---
### Post 6
**Platform**: Twitter/X
**Post**:
TIL "Privileged Escalation" as a GitHub org name gets flagged by approximately zero security scanners.
We checked.
**CMO Note**: Pure name recognition play. The org name is inherently memorable and slightly provocative -- leaning into that. Short enough for easy engagement.
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.