Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0619180
fix(cluster,update): audit remediation — scope cleanup to its cluster…
oleg-flamingocx Jul 10, 2026
d444c2a
ci(test): run root+testutil tests, add cross-compile/govulncheck/tidy…
oleg-flamingocx Jul 10, 2026
00e1616
chore: bump versions
oleg-flamingocx Jul 10, 2026
8a56b9d
ci(release): audit remediation — gate, guard, smoke and clean up the …
oleg-flamingocx Jul 10, 2026
4d20566
fix(ux): audit remediation — enforce the non-interactive contract
oleg-flamingocx Jul 10, 2026
6618988
fix(app): audit remediation — config correctness for ref resolution, …
oleg-flamingocx Jul 10, 2026
45cfa29
feat(app)!: remove --github-branch — --ref is the single way to pin a…
oleg-flamingocx Jul 10, 2026
4ab5c2a
fix(security): audit remediation — TLS scope, redaction, timeouts, st…
oleg-flamingocx Jul 10, 2026
96a32b4
test(ci): audit remediation — gate e2e tests, freeze the update contr…
oleg-flamingocx Jul 10, 2026
a161ad8
refactor: audit remediation — dead-code purge and structural cleanup
oleg-flamingocx Jul 10, 2026
90db0e5
fix: go mod tidy: prune 131 stale go.sum entries orphaned by the dele…
oleg-flamingocx Jul 10, 2026
f518f56
test(k3d): mock the Linux inotify pre-check (sysctl -n / sudo -n) in …
oleg-flamingocx Jul 10, 2026
2727478
fix(ux): dry-run summary, machine-readable status fields, truly silen…
oleg-flamingocx Jul 10, 2026
05df268
test(cli): exhaustive non-interactive invocation matrix at three levels
oleg-flamingocx Jul 10, 2026
95acdda
fix(helm): skip release verification and deployment waits in dry-run …
oleg-flamingocx Jul 10, 2026
baa3c0b
test: append .exe to test binaries on Windows
oleg-flamingocx Jul 10, 2026
85d51d9
ci: repurpose cross-compile into a release build matrix (compile-only)
oleg-flamingocx Jul 10, 2026
fe8c476
chore: go mod tidy — pflag is now a direct dependency (help-matrix te…
oleg-flamingocx Jul 10, 2026
be1c1f7
fix(cluster): drop --wait from cleanup's helm uninstalls
oleg-flamingocx Jul 10, 2026
ac1e722
fix(security): redact child-process stderr at the source, register th…
oleg-flamingocx Jul 10, 2026
d4b3d19
fix(cluster)!: validate the cluster name before it reaches a shell
oleg-flamingocx Jul 10, 2026
9a6d12f
test(update): cover self-update and rollback against the real latest …
oleg-flamingocx Jul 10, 2026
1dc0cbe
fix(helm): redact helm stdout everywhere it reaches the user, not jus…
oleg-flamingocx Jul 10, 2026
1cf091b
fix(cluster): strip ArgoCD finalizers during cleanup so the namespace…
oleg-flamingocx Jul 10, 2026
0b7ca19
refactor(windows): delete the dead native-Windows/WSL code paths
oleg-flamingocx Jul 10, 2026
3291ce7
feat(cli): make failures and diagnostics actually reachable
oleg-flamingocx Jul 10, 2026
7da7f7e
fix(cli): stop reporting things the CLI never measured
oleg-flamingocx Jul 10, 2026
bd7c90e
fix(argocd): run repo-server recovery regardless of --verbose; report…
oleg-flamingocx Jul 10, 2026
5bafa24
fix(errors): classify transient failures by type, not by wording
oleg-flamingocx Jul 10, 2026
a7a7377
fix(cluster): prune node images with crictl, not a docker binary that…
oleg-flamingocx Jul 10, 2026
b4b7df4
fix(ci): repair the three CI failures on the audit branch
oleg-flamingocx Jul 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
steps:
# The self-updater pins the cosign signing identity to
# release.yml@refs/heads/main (internal/shared/selfupdate/cosign.go). The
# Fulcio certificate carries the DISPATCHING ref, so a release run from any
# other branch would publish assets that every `openframe update` rejects
# ("release signature verification failed"). Fail loudly instead of
# skipping so the dispatcher sees why.
- name: 'Guard: releases only from main'
if: github.ref != 'refs/heads/main'
env:
DISPATCH_REF: ${{ github.ref }}
run: |
echo "==================================================================="
echo "=== GUARD: release dispatched from a non-main ref"
echo "==================================================================="
echo "::error::Releases must be dispatched from main (got $DISPATCH_REF). The cosign identity pinned by the self-updater only accepts release.yml@refs/heads/main, so assets signed from this ref would fail verification for every user."
exit 1

- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
Expand All @@ -48,6 +65,19 @@ jobs:
go-version-file: 'go.mod'
cache: true

# --- Gates: never tag or publish an unverified commit -------------------
- name: 'Gate: lint'
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
version: latest

- name: 'Gate: unit tests'
run: |
echo "==================================================================="
echo "=== GATE: unit tests (root, cmd, internal, tests/testutil)"
echo "==================================================================="
make test-unit

- name: Install GoReleaser
uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
with:
Expand All @@ -65,6 +95,7 @@ jobs:
uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0

- name: Create and push tag
id: tag
env:
VERSION: ${{ needs.version.outputs.version }}
# Explicit auth for the push, since the checkout no longer persists it.
Expand All @@ -81,3 +112,60 @@ jobs:
GORELEASER_CURRENT_TAG: ${{ needs.version.outputs.version }}
run: |
goreleaser release --clean

# --- Smoke: verify what was actually shipped ----------------------------
- name: 'Smoke: released binary reports the injected version'
env:
VERSION: ${{ needs.version.outputs.version }}
run: |
echo "==================================================================="
echo "=== SMOKE: dist binary runs and reports ${VERSION}"
echo "==================================================================="
# Guards the ldflags injection (-X cmd.version): a broken injection
# ships binaries reporting "dev", which disables self-update.
BIN="$(find dist -type f -name openframe -path '*linux*amd64*' | head -1)"
if [ -z "$BIN" ]; then echo "::error::no linux/amd64 binary found in dist/"; find dist -type f | head -20; exit 1; fi
got="$("$BIN" --version)"
echo "$got"
if ! echo "$got" | grep -qF "$VERSION"; then
echo "::error::released binary does not report ${VERSION} — ldflags version injection is broken"
exit 1
fi

- name: 'Smoke: published asset URLs resolve (WSL auto-install contract)'
env:
VERSION: ${{ needs.version.outputs.version }}
run: |
echo "==================================================================="
echo "=== SMOKE: bare-tag download URLs resolve for ${VERSION}"
echo "==================================================================="
# wsllauncher and `openframe update` download exactly these bare-tag
# URLs (releases are tagged "x.y.z", no "v" prefix). A 404 here means
# every released Windows binary breaks on first run (audit T0-3).
for asset in "openframe-cli_linux_amd64.tar.gz" "checksums.txt" "checksums.txt.bundle"; do
url="https://github.com/${GITHUB_REPOSITORY}/releases/download/${VERSION}/${asset}"
ok=""
for i in 1 2 3 4 5 6; do
if curl -fsSL -o /dev/null -I "$url"; then ok=1; break; fi
echo "retry $i: $url not yet resolvable"; sleep 5
done
if [ -z "$ok" ]; then echo "::error::released asset URL does not resolve: $url"; exit 1; fi
echo "OK: $url"
done

# --- Cleanup: never leave a half-published release behind ---------------
# A leftover tag wedges the next dispatch: version.yml resolves the next
# version from published releases, so a re-run picks the same version and
# the tag push fails until someone hand-deletes the tag. A half-published
# release failing smoke must not stay visible as `latest` either.
- name: 'Cleanup: delete tag & release on failure'
if: failure() && steps.tag.outcome == 'success'
env:
VERSION: ${{ needs.version.outputs.version }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "==================================================================="
echo "=== CLEANUP: rolling back tag/release ${VERSION} after failure"
echo "==================================================================="
gh release delete "${VERSION}" --repo "${GITHUB_REPOSITORY}" --yes && echo "deleted release ${VERSION}" || echo "no release ${VERSION} to delete"
git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" ":refs/tags/${VERSION}" && echo "deleted tag ${VERSION}"
Loading