Add persist-credentials gotcha and update release template
persist-credentials: false breaks git push. Document using
gh release create --target to create tags via the API instead.
Update the rust-binary release template to match: default-deny
permissions, GITHUB_SHA for short SHA, env var indirection, and
gh-based tagging.

Assisted-by: Claude Opus 4.6 via pi
change rvkpyrxkmtzrvnoumxxnzxrrzptovpvk
commit d5e51b3f96697c1b437ad024062d1059963ab460
author Alpha Chen <alpha@kejadlen.dev>
date
parent ysnqmsqv
diff --git a/ai/skills/github-actions/SKILL.md b/ai/skills/github-actions/SKILL.md
index 73ab73da..9ff8f8c0 100644
--- a/ai/skills/github-actions/SKILL.md
+++ b/ai/skills/github-actions/SKILL.md
@@ -39,6 +39,11 @@ leaking to later steps:
     persist-credentials: false
 ```
 
+This breaks `git push` — you can't push tags or commits from a step
+that checked out without credentials. Use `gh release create --target
+"${GITHUB_SHA}"` to create both the tag and release via the API
+instead of `git tag` + `git push`.
+
 **Indirect environment variable expansion.** Never interpolate
 expressions directly in `run:` scripts — an attacker-controlled value
 (branch name, PR title) can inject shell commands. Assign expressions to
diff --git a/ai/skills/rust-binary/release.md b/ai/skills/rust-binary/release.md
index ccb6a9db..5e928068 100644
--- a/ai/skills/rust-binary/release.md
+++ b/ai/skills/rust-binary/release.md
@@ -13,8 +13,7 @@ on:
     types: [completed]
     branches: [main]
 
-permissions:
-  contents: write
+permissions: {}
 
 jobs:
   build:
@@ -22,35 +21,38 @@ jobs:
       github.event_name == 'workflow_dispatch'
       || github.event.workflow_run.conclusion == 'success'
     runs-on: macos-latest
+    permissions:
+      contents: write # create GitHub release
     steps:
       - uses: actions/checkout@SHA # v4
         with:
           persist-credentials: false
-          fetch-depth: 0
 
       - name: Calculate version
         id: version
         run: |
           CALVER=$(date -u +"%Y-%m-%d")
-          SHORT_SHA=$(git rev-parse --short HEAD)
+          SHORT_SHA="${GITHUB_SHA::7}"
           echo "version=${CALVER}+${SHORT_SHA}" >> $GITHUB_OUTPUT
 
       - name: Build
         run: |
-          cargo build --release
+          RAMEKIN_VERSION="${STEPS_VERSION_OUTPUTS_VERSION}" cargo build --release
           tar -czf <name>-aarch64-apple-darwin.tar.gz -C target/release <name>
+        env:
+          STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
 
       - name: Publish
         run: |
-          VERSION="${{ steps.version.outputs.version }}"
-          git tag "v${VERSION}"
-          git push origin "v${VERSION}"
+          VERSION="${STEPS_VERSION_OUTPUTS_VERSION}"
           gh release create "v${VERSION}" \
             --title "v${VERSION}" \
             --generate-notes \
+            --target "${GITHUB_SHA}" \
             <name>-aarch64-apple-darwin.tar.gz
         env:
           GH_TOKEN: ${{ github.token }}
+          STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
 ```
 
 Adjust `runs-on` and archive name for target platform. Add matrix builds for cross-platform.
@@ -83,6 +85,8 @@ Add a `dotslash` job to `release.yml` after the build job:
   dotslash:
     needs: build
     runs-on: ubuntu-latest
+    permissions:
+      contents: write # upload release assets
     steps:
       - uses: actions/checkout@SHA # v4
         with: