From 0c307cff74e965d0179b3e8975b6b06ff631e2d1 Mon Sep 17 00:00:00 2001 From: bordumb Date: Sat, 4 Apr 2026 23:15:16 -0700 Subject: [PATCH] refactor: replace old 3-secret ci-setup with single AUTHS_CI_TOKEN across workflows, docs, justfiles, and templates --- crates/auths-cli/src/commands/init/helpers.rs | 27 ++----- crates/auths-cli/tests/cases/init.rs | 8 +-- crates/xtask/src/ci_setup.rs | 7 ++ docs/contributing/release-process.md | 8 +-- docs/guides/platforms/ci-cd.md | 71 +++++++------------ justfile | 7 +- scripts/auths_workflows/artifact_signing.py | 5 +- 7 files changed, 52 insertions(+), 81 deletions(-) diff --git a/crates/auths-cli/src/commands/init/helpers.rs b/crates/auths-cli/src/commands/init/helpers.rs index 1044b7a9..d22706b7 100644 --- a/crates/auths-cli/src/commands/init/helpers.rs +++ b/crates/auths-cli/src/commands/init/helpers.rs @@ -128,13 +128,10 @@ fn set_git_config(key: &str, value: &str, scope: &str) -> Result<()> { // --- GitHub Action Scaffolding --- -const GITHUB_ACTION_WORKFLOW_TEMPLATE: &str = r#"# Auths release workflow — signs artifacts and commits attestations to the repo. +const GITHUB_ACTION_WORKFLOW_TEMPLATE: &str = r#"# Auths release workflow — signs artifacts and verifies them. # Generated by: auths init --github-action # -# Required secrets (generate with `just ci-setup`): -# AUTHS_CI_PASSPHRASE — passphrase for the CI keychain -# AUTHS_CI_KEYCHAIN — base64-encoded keychain file -# AUTHS_CI_IDENTITY_BUNDLE — base64-encoded identity bundle +# Required: run `auths ci setup` to set the AUTHS_CI_TOKEN secret. name: Auths Release @@ -157,22 +154,12 @@ jobs: # Replace this with your build step echo "Build your artifacts here" - - name: Sign artifacts and commit attestations - uses: auths-dev/attest-action@v1 - env: - # These secrets must be set in your repository settings - AUTHS_PASSPHRASE: ${{ secrets.AUTHS_CI_PASSPHRASE }} - AUTHS_CI_KEYCHAIN_B64: ${{ secrets.AUTHS_CI_KEYCHAIN }} - AUTHS_CI_IDENTITY_BUNDLE_B64: ${{ secrets.AUTHS_CI_IDENTITY_BUNDLE }} + - name: Sign and verify artifacts + uses: auths-dev/sign@v1 with: - # Glob pattern matching your release artifacts - artifacts: 'dist/*.tar.gz' - - # Directory in your repo where attestation files are committed - attestation-path: '.auths/releases' - - # "direct" pushes to the current branch; "pr" opens a pull request - commit-strategy: 'direct' + token: ${{ secrets.AUTHS_CI_TOKEN }} + files: 'dist/*.tar.gz' + verify: true "#; /// Scaffolds a GitHub Actions workflow for attestation signing. diff --git a/crates/auths-cli/tests/cases/init.rs b/crates/auths-cli/tests/cases/init.rs index aa6e4b12..16c209aa 100644 --- a/crates/auths-cli/tests/cases/init.rs +++ b/crates/auths-cli/tests/cases/init.rs @@ -36,12 +36,12 @@ fn test_init_github_action_scaffold() { let content = std::fs::read_to_string(&workflow).unwrap(); assert!( - content.contains("auths-dev/attest-action@v1"), - "workflow should reference attest-action" + content.contains("auths-dev/sign@v1"), + "workflow should reference sign action" ); assert!( - content.contains("AUTHS_CI_PASSPHRASE"), - "workflow should reference secrets" + content.contains("AUTHS_CI_TOKEN"), + "workflow should reference AUTHS_CI_TOKEN secret" ); // .auths/.gitkeep should exist diff --git a/crates/xtask/src/ci_setup.rs b/crates/xtask/src/ci_setup.rs index 783904d2..1ba6eadd 100644 --- a/crates/xtask/src/ci_setup.rs +++ b/crates/xtask/src/ci_setup.rs @@ -15,6 +15,13 @@ use walkdir::WalkDir; use crate::shell::{run_capture, run_capture_env, run_with_stdin}; pub fn run() -> Result<()> { + eprintln!( + "\x1b[1;33m⚠ `cargo xt ci-setup` is deprecated. Use `auths ci setup` instead.\x1b[0m" + ); + eprintln!(" The new command bundles all secrets into a single AUTHS_CI_TOKEN."); + eprintln!(" Run `auths ci setup --help` for details."); + eprintln!(); + println!(); println!("\x1b[0;36m╔════════════════════════════════════════════════════════════╗\x1b[0m"); println!("\x1b[0;36m║\x1b[0m\x1b[1m CI Release Signing Setup (One-Time) \x1b[0m\x1b[0;36m║\x1b[0m"); diff --git a/docs/contributing/release-process.md b/docs/contributing/release-process.md index 36326913..d7fdf32b 100644 --- a/docs/contributing/release-process.md +++ b/docs/contributing/release-process.md @@ -40,15 +40,15 @@ This makes similar checks as the github release. It also includes properly order ### One-time CI signing setup -Before the first release, GitHub Actions needs a device key and identity bundle for artifact signing: +Before the first release, GitHub Actions needs a device key and identity token for artifact signing: ```bash -just ci-setup +auths ci setup ``` -This creates a limited-capability CI device key, exports it as an encrypted keychain, and sets three GitHub secrets: `AUTHS_CI_PASSPHRASE`, `AUTHS_CI_KEYCHAIN`, and `AUTHS_CI_IDENTITY_BUNDLE`. Artifact signing is skipped gracefully if these secrets are missing. +This creates a limited-capability CI device key and sets a single `AUTHS_CI_TOKEN` secret on GitHub containing everything CI needs. Artifact signing is skipped gracefully if the secret is missing. -Re-run `ci-setup` only if the CI device key is revoked or the identity repo changes significantly. +To refresh the token without regenerating the device key, run `auths ci rotate`. ### Manual steps (if needed) diff --git a/docs/guides/platforms/ci-cd.md b/docs/guides/platforms/ci-cd.md index 9c7d0217..92620e74 100644 --- a/docs/guides/platforms/ci-cd.md +++ b/docs/guides/platforms/ci-cd.md @@ -12,38 +12,38 @@ CI signing in Auths works through device delegation: 4. In CI, the runner restores the identity bundle and signs artifacts using the CI device key. 5. You can **revoke** the CI device at any time without affecting your root identity. -## One-time setup with `cargo xt ci-setup` +## One-time setup with `auths ci setup` -The `ci-setup` xtask automates the entire provisioning flow. Run it from the project root: +Run this from any repo with a git remote: ```bash -cargo xt ci-setup +auths ci setup ``` This command will: -1. **Verify your identity exists** by running `auths status`. -2. **Read your identity DID** from `auths id show` and your key alias from `auths key list`. -3. **Generate a CI device key** (Ed25519, 32-byte seed) and import it into your platform keychain under the alias `ci-release-device`. -4. **Prompt for a passphrase** that will protect the CI device key. This passphrase will be stored as a GitHub Secret. -5. **Create an encrypted file keychain** by copying the key to a file-backed keychain using `auths key copy-backend --alias ci-release-device --dst-backend file`. -6. **Derive the device DID** using `auths key export --alias ci-release-device --format pub` and `auths debug util pubkey-to-did`. -7. **Link the CI device** to your identity with `auths device link --capabilities sign_release --note "GitHub Actions release signer"`. -8. **Package your `~/.auths` repository** as a base64-encoded tarball (excluding `.sock` files). -9. **Set three GitHub Secrets** via the `gh` CLI: - - `AUTHS_CI_PASSPHRASE` -- The passphrase for the CI device key. - - `AUTHS_CI_KEYCHAIN` -- The encrypted file keychain (base64). - - `AUTHS_CI_IDENTITY_BUNDLE` -- The `~/.auths` repository snapshot (base64 tarball). - -If the `gh` CLI is not authenticated, the command prints the secret values for you to add manually via **Repository > Settings > Secrets > Actions > New secret**. +1. **Verify your identity exists** and read your identity DID and key alias. +2. **Generate a CI device key** (Ed25519) and link it to your identity with `sign_release` capability. +3. **Package everything** into a single `AUTHS_CI_TOKEN` JSON secret containing the passphrase, encrypted keychain, identity repo snapshot, and verification bundle. +4. **Set the secret** on your forge automatically via the `gh` CLI (GitHub) or print the token for manual setup (other forges). + +If the `gh` CLI is not authenticated, the command prints the token value for you to add manually via **Repository > Settings > Secrets > Actions > New secret**. + +### Rotating the token + +To refresh the token (new TTL, updated identity repo) without regenerating the device key: + +```bash +auths ci rotate +``` ### Re-running setup -If you already have a `ci-release-device` key, `cargo xt ci-setup` detects it and reuses the existing key while regenerating the file keychain and secrets. +If you already have a `ci-release-device` key, `auths ci setup` detects it and reuses the existing key while regenerating the token. ## Signing artifacts in GitHub Actions -Once the secrets are set, add a signing step to your release workflow: +Once `AUTHS_CI_TOKEN` is set, add a signing step to your release workflow: ```yaml name: Release @@ -60,34 +60,15 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install Auths - run: cargo install auths-cli - - - name: Restore Auths identity - env: - AUTHS_CI_IDENTITY_BUNDLE: ${{ secrets.AUTHS_CI_IDENTITY_BUNDLE }} - AUTHS_CI_KEYCHAIN: ${{ secrets.AUTHS_CI_KEYCHAIN }} - AUTHS_CI_PASSPHRASE: ${{ secrets.AUTHS_CI_PASSPHRASE }} - run: | - # Restore the ~/.auths identity repository - mkdir -p ~/.auths - echo "$AUTHS_CI_IDENTITY_BUNDLE" | base64 -d | tar xz -C ~/.auths - - # Restore the file keychain - echo "$AUTHS_CI_KEYCHAIN" | base64 -d > /tmp/ci-keychain.enc - - # Set environment for file-backend keychain - echo "AUTHS_KEYCHAIN_BACKEND=file" >> $GITHUB_ENV - echo "AUTHS_KEYCHAIN_FILE=/tmp/ci-keychain.enc" >> $GITHUB_ENV - echo "AUTHS_PASSPHRASE=$AUTHS_CI_PASSPHRASE" >> $GITHUB_ENV - - name: Build release artifact run: cargo build --release && tar czf myproject.tar.gz -C target/release myproject - - name: Sign release artifact - run: | - auths sign myproject.tar.gz \ - --device-key ci-release-device + - name: Sign and verify artifact + uses: auths-dev/sign@v1 + with: + token: ${{ secrets.AUTHS_CI_TOKEN }} + files: 'myproject.tar.gz' + verify: true - name: Upload release uses: softprops/action-gh-release@v2 @@ -227,4 +208,4 @@ auths device revoke \ --key ``` -The device DID and identity key alias are printed by `cargo xt ci-setup` when the device is created. After revocation, the CI device key can no longer produce valid attestations, even if the secrets remain in GitHub. +The device DID and identity key alias are printed by `auths ci setup` when the device is created. After revocation, the CI device key can no longer produce valid attestations, even if the secrets remain in GitHub. diff --git a/justfile b/justfile index c508a881..d1f4a173 100644 --- a/justfile +++ b/justfile @@ -112,8 +112,7 @@ release-github: release-crates: python scripts/releases/2_crates.py --publish -# One-time setup: create a CI release-signing device and export secrets for GitHub -# Run this once locally, then add the printed values as GitHub secrets -# Delegates to the xtask crate for cross-platform correctness. +# One-time setup: create a CI release-signing device and set AUTHS_CI_TOKEN secret. +# Run this once locally — detects forge from git remote and sets the secret automatically. ci-setup: - cargo xt ci-setup + auths ci setup diff --git a/scripts/auths_workflows/artifact_signing.py b/scripts/auths_workflows/artifact_signing.py index dde2d977..87a6da38 100644 --- a/scripts/auths_workflows/artifact_signing.py +++ b/scripts/auths_workflows/artifact_signing.py @@ -270,10 +270,7 @@ def main() -> None: print(f"{BOLD}{GREEN} Artifact signing workflow completed successfully!{RESET}") print(f"{BOLD}{GREEN}{'='*60}{RESET}") print(f"\n This confirms the release.yml signing step will work in CI.") - print(f" Make sure these GitHub secrets are set (via 'just ci-setup'):") - print(f" • AUTHS_CI_PASSPHRASE") - print(f" • AUTHS_CI_KEYCHAIN") - print(f" • AUTHS_CI_IDENTITY_BUNDLE\n") + print(f" Make sure AUTHS_CI_TOKEN is set (via 'auths ci setup').\n") if __name__ == "__main__":