mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-07-02 20:51:37 +00:00
76e130b313
## Summary Fixes the missing `actions: write` permission on `.github/workflows/release-fast-path.yml` so the fallback `gh workflow run deploy.yml` dispatch no longer returns HTTP 403. ## Triage verdict From issue #1702 root-cause section: > Fast-path workflow YAML likely lacks: > ```yaml > permissions: > contents: read > packages: write > actions: write # MISSING — required to dispatch other workflows > ``` > ## Fix > One-line addition to `.github/workflows/release-fast-path.yml` permissions block. ## Root cause `.github/workflows/release-fast-path.yml` lines 16-18 (before this change) only granted `contents: read` and `packages: write`. The fallback step (`gh workflow run deploy.yml` when `:edge`'s `org.opencontainers.image.revision` label doesn't match the tag SHA) calls the GitHub Actions REST API, which requires `actions: write` on `GITHUB_TOKEN`. Without it, the dispatch fails with `Resource not accessible by integration` and the release stalls until an operator manually re-runs the fast-path job after `:edge` rebuilds. ## Change - `.github/workflows/release-fast-path.yml`: add `actions: write` to the workflow-level `permissions:` block. - `cmd/server/release_fast_path_workflow_test.go`: extend the existing config-gate test (issue #1677) to require `actions: write` alongside the previously asserted `contents: read` and `packages: write`. Two commits, red→green: 1. `test(#1702): assert release-fast-path.yml requires actions: write` — extends the assertion. Verified to fail on this commit (`release-fast-path.yml: missing required permission "actions: write"`). 2. `fix(#1702): grant actions: write to release-fast-path workflow` — adds the permission. Test green. ## TDD posture The repo already had a YAML-config gate at `cmd/server/release_fast_path_workflow_test.go` (parses the workflow as text and asserts required permission strings). Strict TDD applied: red commit extends the test, green commit fixes the workflow. No exemption needed. ## Acceptance criteria (from #1702) - [x] `permissions.actions: write` added to the fast-path workflow - [ ] Manual test: tag a scratch SHA where `:edge` is stale; confirm fallback dispatches deploy.yml without 403 — by-design out of CI scope (would require a throwaway tag + race condition); covered by next real release. - [ ] Operator-felt: next release where notes-commit lands AFTER `:edge` build completes works in one pass without manual rerun — verifiable only on next release; in-scope of `Closes #1702` because bullet 1 (the structural defect) is the cause of bullets 2 and 3. ## Preflight `bash ~/.openclaw/skills/pr-preflight/scripts/run-all.sh origin/master` → **clean** (all hard gates pass, no warnings). Closes #1702 --------- Co-authored-by: Kpa-clawbot <kpa-clawbot@users.noreply.github.com>
113 lines
4.5 KiB
YAML
113 lines
4.5 KiB
YAML
name: Release Fast-Path
|
|
|
|
# Issue #1677: re-tag :edge as :vX.Y.Z when the tag SHA matches :edge's
|
|
# org.opencontainers.image.revision label. Skips ~30 min of Go test +
|
|
# Playwright + Docker rebuild because the bytes are identical — only the
|
|
# manifest name changes. Falls back to deploy.yml when SHAs differ so
|
|
# tags on older commits still go through full validation.
|
|
#
|
|
# This workflow is the SOLE consumer of push.tags. deploy.yml's tag
|
|
# trigger has been removed to prevent double-fire.
|
|
|
|
on:
|
|
push:
|
|
tags: ['v[0-9]+.[0-9]+.[0-9]+']
|
|
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
actions: write # issue #1702: required so the fallback `gh workflow run deploy.yml` dispatch is allowed
|
|
|
|
concurrency:
|
|
group: release-fast-path-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
retag-or-fallback:
|
|
name: "🏷️ Re-tag :edge → :vX.Y.Z (fast) or dispatch deploy.yml (fallback)"
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Log in to GHCR
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Install crane
|
|
uses: imjasonh/setup-crane@v0.4
|
|
|
|
- name: Parse semver from tag
|
|
id: semver
|
|
run: |
|
|
set -euo pipefail
|
|
TAG="${GITHUB_REF#refs/tags/}"
|
|
# Expect vMAJOR.MINOR.PATCH (workflow trigger already enforces this).
|
|
if [[ ! "$TAG" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
|
|
echo "Tag $TAG does not match vMAJOR.MINOR.PATCH" >&2
|
|
exit 1
|
|
fi
|
|
MAJOR="${BASH_REMATCH[1]}"
|
|
MINOR="${BASH_REMATCH[2]}"
|
|
{
|
|
echo "tag=$TAG"
|
|
echo "vMajor=v$MAJOR"
|
|
echo "vMajorMinor=v$MAJOR.$MINOR"
|
|
} >> "$GITHUB_OUTPUT"
|
|
echo "Parsed: $TAG → v$MAJOR / v$MAJOR.$MINOR / $TAG"
|
|
|
|
- name: Inspect :edge revision label
|
|
id: edge
|
|
run: |
|
|
set -euo pipefail
|
|
IMAGE="ghcr.io/kpa-clawbot/corescope"
|
|
EDGE_REF="${IMAGE}:edge"
|
|
# crane config returns the OCI image config JSON; the revision label
|
|
# is set by docker/metadata-action on the master-edge build.
|
|
# If :edge doesn't exist yet (first run on a fresh registry), fall
|
|
# through to the slow path.
|
|
if ! CONFIG="$(crane config "$EDGE_REF" 2>/dev/null)"; then
|
|
echo "edge_revision=" >> "$GITHUB_OUTPUT"
|
|
echo "no_edge=true" >> "$GITHUB_OUTPUT"
|
|
echo ":edge not found in registry — will use fallback path"
|
|
exit 0
|
|
fi
|
|
REV="$(echo "$CONFIG" | jq -r '.config.Labels["org.opencontainers.image.revision"] // ""')"
|
|
echo "edge_revision=$REV" >> "$GITHUB_OUTPUT"
|
|
echo "no_edge=false" >> "$GITHUB_OUTPUT"
|
|
echo ":edge org.opencontainers.image.revision = $REV"
|
|
echo "tag SHA (github.sha) = ${{ github.sha }}"
|
|
|
|
# ─────────── FAST PATH: SHAs match, metadata-only retag ───────────
|
|
- name: Re-tag :edge → :vX.Y.Z + :vX.Y + :vX + :latest (fast path)
|
|
if: steps.edge.outputs.no_edge == 'false' && steps.edge.outputs.edge_revision == github.sha
|
|
run: |
|
|
set -euo pipefail
|
|
IMAGE="ghcr.io/kpa-clawbot/corescope"
|
|
SRC="${IMAGE}:edge"
|
|
echo "SHA match — fast-path re-tag from $SRC"
|
|
for NEW_TAG in \
|
|
"${{ steps.semver.outputs.tag }}" \
|
|
"${{ steps.semver.outputs.vMajorMinor }}" \
|
|
"${{ steps.semver.outputs.vMajor }}" \
|
|
"latest"; do
|
|
echo " crane tag $SRC $NEW_TAG"
|
|
crane tag "$SRC" "$NEW_TAG"
|
|
done
|
|
echo "Fast-path complete — all tags point at the :edge manifest digest."
|
|
|
|
# ─────────── FALLBACK: SHAs differ, run the full pipeline ───────────
|
|
- name: Dispatch full deploy.yml pipeline (fallback)
|
|
if: steps.edge.outputs.no_edge == 'true' || steps.edge.outputs.edge_revision != github.sha
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
echo "SHA mismatch (or no :edge) — falling back to full pipeline"
|
|
echo " :edge revision = '${{ steps.edge.outputs.edge_revision }}'"
|
|
echo " tag SHA = '${{ github.sha }}'"
|
|
gh workflow run deploy.yml \
|
|
--repo "${{ github.repository }}" \
|
|
--ref "${{ github.ref }}"
|
|
echo "Dispatched deploy.yml against ${{ github.ref }}"
|