Skip to content

Migrate release tooling from cargo-dist to GoReleaser before v0.1 #65

Closed as not planned

Description

@unclesp1d3r

Context

Our current release process uses cargo-dist to build and publish releases. While cargo-dist has served us well, we've encountered some friction points that would be resolved by migrating to GoReleaser.

Current State

The cargo-dist configuration includes:

  • Multi-platform builds (Linux x86_64, Linux ARM, macOS, Windows)
  • GitHub Release creation with auto-generated release notes
  • Homebrew formula publishing to EvilBit-Labs/homebrew-tap
  • SBOM generation using cargo-cyclonedx
  • Build attestations for supply chain security
  • Artifact signing and checksums

Problems with Current Approach

  1. Workflow Complexity: The generated .github/workflows/release.yml is over 300 lines and difficult to customize
  2. Actionlint Warnings: The auto-generated workflow consistently triggers actionlint warnings, cluttering our CI output
  3. Limited Flexibility: cargo-dist's opinionated approach makes it challenging to customize the release process
  4. Maintenance Burden: Need to keep cargo-dist installation scripts in sync across multiple workflow files (security.yml, copilot-setup-steps.yml)

Why GoReleaser?

  1. Better Rust Support: GoReleaser now has official Rust/Cargo support with good cross-compilation capabilities
  2. More Mature Ecosystem: Extensive plugin system and well-documented customization options
  3. Cleaner Configuration: YAML-based config is easier to understand and maintain than generated workflows
  4. Flexible: Easier to customize release behavior, artifacts, and publishing strategies
  5. No Generated Workflows: Uses a single reusable action, avoiding actionlint issues
  6. Rich Feature Set: Built-in support for Docker, Snapcraft, AUR, and many other distribution channels

Proposed Solution

Phase 1: Setup GoReleaser Configuration

  1. Create .goreleaser.yml configuration file with:
    • Rust build configuration for all target platforms
    • Archive generation matching current artifact structure
    • Checksum generation
    • GitHub Release publishing

Phase 2: Migrate Publishing Targets

  1. Homebrew: Configure GoReleaser's Homebrew tap publisher
    • Target: EvilBit-Labs/homebrew-tap
    • Ensure formula matches current structure
  2. SBOM Generation: Integrate SBOM generation (cargo-cyclonedx or built-in)
  3. Attestations: Configure artifact signing and attestations

Phase 3: Update CI/CD

  1. Replace .github/workflows/release.yml with minimal GoReleaser workflow
  2. Remove cargo-dist installation from:
    • security.yml
    • copilot-setup-steps.yml
  3. Update any documentation referencing cargo-dist

Phase 4: Testing & Validation

  1. Test release process with pre-release tag
  2. Verify all artifacts are generated correctly
  3. Confirm Homebrew formula updates work
  4. Validate checksums and signatures
  5. Test installation on all supported platforms

Success Criteria

  • GoReleaser configuration successfully builds all current platforms
  • GitHub Releases match current format and content
  • Homebrew tap updates automatically
  • SBOMs are generated for all artifacts
  • Attestations/signatures work correctly
  • Release workflow is under 100 lines
  • No actionlint warnings
  • Successfully complete a test release

References

Timeline

This migration should be completed before releasing v0.1, as changing release tooling after the first major release would be more disruptive to users who may have automated installations.

Activity

  1. added theissue type on Nov 10, 2025
  2. traycerai commented on Nov 10, 2025

    @traycerai

    Plan

    Observations

    The project uses cargo-dist for multi-platform releases across 5 targets, with shell/PowerShell/Homebrew installers, SBOM via cargo-cyclonedx, attestations, and a Homebrew tap. The auto-generated release workflow is complex (300+ lines) and triggers actionlint warnings. justfile includes cargo-dist recipes and partial GoReleaser setup with macOS SDK handling. Cargo.toml defines a dist profile with thin LTO. Security and Copilot workflows install cargo-dist. Documentation references cargo-dist processes.

    Approach

    Migrate to GoReleaser by creating .goreleaser.yml to replicate all features: Rust builds with cargo-zigbuild and auditable, archives/checksums, SBOM, Homebrew cask publishing, and release assets including custom installers. Replace the release workflow with a simple GoReleaser action plus attestations. Remove cargo-dist from justfile, workflows, and config files. Update documentation for new process. Test via snapshot releases.

    Reasoning

    I listed repository files to identify cargo-dist configs and workflows. I read the release.yml to confirm its complexity and generation. I examined dist-workspace.toml for current settings like targets and installers. I reviewed Cargo.toml for build profiles. I checked justfile for existing recipes. I inspected security.yml and copilot-setup-steps.yml for cargo-dist installations. I browsed docs for release references.

    Proposed File Changes

    📄 .goreleaser.yml (NEW) 🔗

    References

    Create comprehensive GoReleaser configuration replicating cargo-dist features.

    Builds

    • Use builder: rust with goosarch for all 5 targets.
    • Set binary: stringy and main: ./src/main.rs.
    • Enable hooks to install cargo-zigbuild, cargo-auditable, cargo-cyclonedx.
    • Use command: auditable with extra_args: ['zigbuild', '--release'] for cross-compilation and auditing.
    • Set ldflags to include thin LTO via -C lto=thin matching profile.dist.
    • For macOS targets, reference env vars from justfile (SDKROOT, etc.) in env section.

    Archives

    • Unix: format: tarxz, Windows: format: zip.
    • Template: {{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}.

    Checksum

    • name_template: 'checksums.txt'.

    Sbom

    • Use generator: cyclonedx with command: cargo cyclonedx args ['-o', '{{ .ArtifactName }}.cdx.json'].

    Brew

    • tap: github.com/EvilBit-Labs/homebrew-tap on main branch.
    • token: HOMEBREW_TAP_TOKEN.
    • folder: Casks, name: stringy.
    • Set homepage, description, license from Cargo.toml.
    • commit_author.name: 'Stringy Bot', commit_author.email: 'bot@evilbitlabs.io'.
    • install: |- bin.install "stringy".
    • caveats: 'Successfully installed Stringy! Ready to start looking at your binaries!'.

    Release

    • disable: false, include extra_files: [scripts/install.sh, scripts/install.ps1].
    • github_token: {{ .Env.GITHUB_TOKEN }}.

    UniversalBinaries (macOS)

    • Enable for aarch64-apple-darwin if needed, but use separate builds for simplicity.

    Reference Cargo.toml for metadata, dist-workspace.toml for targets/installers.

    📄 .github/workflows/release.yml (MODIFY) 🔗

    References

    Replace entire cargo-dist generated workflow with simple GoReleaser setup.

    • Name: 'Release'.
    • Permissions: contents: write, id-token: write, attestations: write.
    • On: push: tags: ['v[0-9]+.[0-9]+.[0-9]+*'], pull_request for testing.
    • Job 'release': runs-on ubuntu-latest.
      • Checkout with fetch-depth: 0.
      • Setup Rust: dtolnay/rust-toolchain@v1 with 1.90.
      • Install Zig: kennethreitz/setup-zig@v1 version 0.12.1.
      • Cargo install: cargo-zigbuild, cargo-auditable, cargo-cyclonedx with --locked.
      • Rustup target add for all 5 triples.
      • GoReleaser: goreleaser/goreleaser-action@v5 with distribution: goreleaser args release --clean.
      • Env: GITHUB_TOKEN, HOMEBREW_TAP_TOKEN.
    • If tag push: After GoReleaser, run actions/attest-build-provenance@v1 with subject-paths: dist/checksums.txt.

    This simplifies to ~50 lines, eliminates actionlint issues, and handles all builds/publishing in one job.

    Reference new .goreleaser.yml for config integration.

    📁 scripts (NEW) 🔗

    Create scripts directory for installer files to be included in releases.

    📄 scripts/install.sh (NEW) 🔗

    References

    Create Unix shell installer script.

    • Shebang: #!/usr/bin/env bash.
    • Set -euo pipefail.
    • Vars: OWNER='EvilBit-Labs', REPO='StringyMcStringFace', BINARY='stringy', INSTALL_DIR='/usr/local/bin'.
    • Version: Use $VERSION or fetch latest tag via GitHub API (curl -s https://api.github.com/repos/$OWNER/$REPO/releases/latest | jq -r .tag_name).
    • Detect OS/Arch: OS=$(uname -s | tr '[:upper:]' '[:lower:]'), ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/' ).
    • Temp dir: mktemp -d with trap cleanup.
    • Download: Asset name ${BINARY}_${VERSION}_${OS}_${ARCH}.tar.xz, URL from GitHub releases, curl -L -o.
    • Download checksums.txt, verify sha256sum -c --ignore-missing.
    • Extract: tar -xJf, sudo install -m 755 stringy $INSTALL_DIR/.
    • Success msg: 'Successfully installed Stringy! Ready to start looking at your binaries!'.

    Matches cargo-dist shell installer behavior, uses GoReleaser naming.

    📄 scripts/install.ps1 (NEW) 🔗

    References

    Create Windows PowerShell installer script.

    • Param: [CmdletBinding()] param( [string]$Version = '' ).
    • $ErrorActionPreference = 'Stop'.
    • Vars: $Owner = 'EvilBit-Labs', $Repo = 'StringyMcStringFace', $Binary = 'stringy', $InstallDir = "$env:ProgramFiles\Stringy".
    • Version: If empty, $latest = Invoke-RestMethod "https://api.github.com/repos/$Owner/$Repo/releases/latest"; $Version = $latest.tag_name.
    • Arch: $Arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { 'amd64' } else { 'arm64' }; OS='windows'.
    • Temp: $tempDir = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid().
    • Asset: ${Binary}_${Version}_windows_${Arch}.zip.
    • Download: Invoke-WebRequest -Uri "https://github.com/$Owner/$Repo/releases/download/$Version/$asset" -OutFile "$tempDir\$asset".
    • Download checksums.txt, compute hash Get-FileHash, verify against file.
    • Extract: Expand-Archive -Path "$tempDir\$asset" -DestinationPath $InstallDir.
    • Add to PATH: [Environment]::SetEnvironmentVariable('Path', "$env:Path;$InstallDir", 'User').
    • Msg: Success message, note to restart shell.

    Replicates cargo-dist PowerShell installer with GoReleaser compatibility.

    📄 dist-workspace.toml (DELETE) 🔗

    Remove cargo-dist workspace configuration as it's replaced by .goreleaser.yml.

    📄 justfile (MODIFY) 🔗

    References

    Update justfile to remove cargo-dist and enhance GoReleaser.

    • In install-tools: Remove cargo-dist from binstall list (lines ~73,77).
    • Remove dist recipes: dist, dist-check, dist-plan, dist-generate-ci (lines 291-304).
    • Update ci-check: Remove dist-plan dependency (line 278), now pre-commit-run fmt-check lint-rust lint-rust-min test-ci build-release audit coverage-check.
    • Keep all goreleaser-* recipes (lines 355-425) as they align with new config; add comment: '# GoReleaser handles releases via .goreleaser.yml and GitHub Actions'.
    • Optional: Add release: goreleaser-snapshot alias for local testing.

    Ensures clean transition, retains macOS SDK handling in GoReleaser recipes.

    Reference .goreleaser.yml for integration.

    📄 Cargo.toml (MODIFY) 🔗

    References

    Minor update to Cargo.toml for profile clarity.

    • Rename [profile.dist] to [profile.release] or add comment: '# Previously for cargo-dist; GoReleaser uses --release profile with optional thin LTO via ldflags'.
    • Keep inherits = 'release', lto = 'thin'.
    • No other changes needed as GoReleaser can reference this via build flags.

    Reference .goreleaser.yml where ldflags incorporate thin LTO.

    📄 .github/workflows/security.yml (MODIFY) 🔗

    Remove cargo-dist from security workflow.

    • In 'Install cargo tools' step (line ~34): Remove cargo-dist from taiki-e/install-action tool list.
    • Remove 'Run cargo dist check' step (lines 41-43).
    • Keep cargo-outdated, cargo-deny.

    Aligns with migration; security checks now focus on other tools.

    📄 .github/workflows/copilot-setup-steps.yml (MODIFY) 🔗

    References

    Remove cargo-dist from Copilot setup.

    • In 'Install cargo tools' step (line ~49): Remove cargo-dist from tool list.
    • In 'just install-tools' run (line 58): This will now skip cargo-dist due to justfile update.
    • Update summary echo (line 72): Remove cargo-dist version check.

    Ensures setup doesn't install obsolete tool.

    📄 docs/src/installation.md (MODIFY) 🔗

    References

    Update installation docs for GoReleaser releases.

    • Add section 'Binary Releases' after 'Prerequisites':
      • 'Quick Install (Unix/macOS)': curl -sSfL https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.sh | sh.
      • 'Quick Install (Windows)': irm https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.ps1 | iex.
      • 'Homebrew': brew tap EvilBit-Labs/homebrew-tap && brew install stringy.
      • 'Manual': Download archives from GitHub Releases.
    • Update intro note: 'Binary releases available from v0.1 via GoReleaser; source install for development'.
    • Retain 'From Source', 'Development Build', etc. sections.

    Reference installer scripts for commands.

    📄 docs/src/contributing.md (MODIFY) 🔗

    References

    Update contributing docs for release process.

    • In 'Release Checklist':
      1. Update Cargo.toml version.
      2. Update CHANGELOG.md.
      3. Run just ci-check.
      4. Update docs.
      5. Test: just goreleaser-snapshot.
      6. Tag/push: git tag vX.Y.Z && git push --tags.
      7. GitHub Actions auto-publishes via GoReleaser.
      8. Verify releases, Homebrew, artifacts.
    • Add 'Testing Releases': Use just goreleaser-snapshot for local dry-run; just goreleaser-check validates config.
    • Add 'Automation': Tags trigger workflow building 5 platforms, installers, SBOM, attestations, Homebrew push.

    Reference .goreleaser.yml and release.yml.

    📄 README.md (MODIFY) 🔗

    References

    Update README installation section.

    • After 'Installation' header: Add 'Pre-built binaries available from v0.1 via GitHub Releases, Homebrew, and one-liners. See docs/installation.md for details.'
    • Retain 'From Source' and 'Development Build' as primary methods.
    • No major changes; keep concise.

    Import In IDE

    VSCode Icon Cursor Icon Windsurf Icon

    🤖 Prompt for AI Agents
    I have created the following plan after thorough exploration and analysis of the codebase. Follow the below plan verbatim. Trust the files and references. Do not re-verify what's written in the plan. Explore only when absolutely necessary. First implement all the proposed file changes and then I'll review all the changes together at the end.
    
    ### Observations
    
    The project uses cargo-dist for multi-platform releases across 5 targets, with shell/PowerShell/Homebrew installers, SBOM via cargo-cyclonedx, attestations, and a Homebrew tap. The auto-generated release workflow is complex (300+ lines) and triggers actionlint warnings. justfile includes cargo-dist recipes and partial GoReleaser setup with macOS SDK handling. Cargo.toml defines a dist profile with thin LTO. Security and Copilot workflows install cargo-dist. Documentation references cargo-dist processes.
    
    ### Approach
    
    Migrate to GoReleaser by creating `.goreleaser.yml` to replicate all features: Rust builds with cargo-zigbuild and auditable, archives/checksums, SBOM, Homebrew cask publishing, and release assets including custom installers. Replace the release workflow with a simple GoReleaser action plus attestations. Remove cargo-dist from justfile, workflows, and config files. Update documentation for new process. Test via snapshot releases.
    
    ### Reasoning
    
    I listed repository files to identify cargo-dist configs and workflows. I read the release.yml to confirm its complexity and generation. I examined dist-workspace.toml for current settings like targets and installers. I reviewed Cargo.toml for build profiles. I checked justfile for existing recipes. I inspected security.yml and copilot-setup-steps.yml for cargo-dist installations. I browsed docs for release references.
    
    ## Proposed File Changes
    
    ### .goreleaser.yml(NEW)
    
    References: 
    
    - Cargo.toml(MODIFY)
    - dist-workspace.toml(DELETE)
    - justfile(MODIFY)
    
    # Create comprehensive GoReleaser configuration replicating cargo-dist features.
    
    ## Builds
    - Use `builder: rust` with `goosarch` for all 5 targets.
    - Set `binary: stringy` and `main: ./src/main.rs`.
    - Enable `hooks` to install cargo-zigbuild, cargo-auditable, cargo-cyclonedx.
    - Use `command: auditable` with `extra_args: ['zigbuild', '--release']` for cross-compilation and auditing.
    - Set `ldflags` to include thin LTO via `-C lto=thin` matching `profile.dist`.
    - For macOS targets, reference env vars from justfile (SDKROOT, etc.) in `env` section.
    
    ## Archives
    - Unix: `format: tarxz`, Windows: `format: zip`.
    - Template: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`.
    
    ## Checksum
    - `name_template: 'checksums.txt'`.
    
    ## Sbom
    - Use `generator: cyclonedx` with `command: cargo cyclonedx` args `['-o', '{{ .ArtifactName }}.cdx.json']`.
    
    ## Brew
    - `tap: github.com/EvilBit-Labs/homebrew-tap` on `main` branch.
    - `token: HOMEBREW_TAP_TOKEN`.
    - `folder: Casks`, `name: stringy`.
    - Set `homepage`, `description`, `license` from Cargo.toml.
    - `commit_author.name: 'Stringy Bot'`, `commit_author.email: 'bot@evilbitlabs.io'`.
    - `install: |-
      bin.install "stringy"`.
    - `caveats: 'Successfully installed Stringy! Ready to start looking at your binaries!'`.
    
    ## Release
    - `disable: false`, include `extra_files: [scripts/install.sh, scripts/install.ps1]`.
    - `github_token: {{ .Env.GITHUB_TOKEN }}`.
    
    ## UniversalBinaries (macOS)
    - Enable for aarch64-apple-darwin if needed, but use separate builds for simplicity.
    
    Reference Cargo.toml for metadata, dist-workspace.toml for targets/installers.
    
    ### .github/workflows/release.yml(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Replace entire cargo-dist generated workflow with simple GoReleaser setup.
    
    - Name: 'Release'.
    - Permissions: `contents: write`, `id-token: write`, `attestations: write`.
    - On: `push: tags: ['v[0-9]+.[0-9]+.[0-9]+*']`, `pull_request` for testing.
    - Job 'release': runs-on `ubuntu-latest`.
      - Checkout with `fetch-depth: 0`.
      - Setup Rust: `dtolnay/rust-toolchain@v1` with `1.90`.
      - Install Zig: `kennethreitz/setup-zig@v1` version `0.12.1`.
      - Cargo install: `cargo-zigbuild`, `cargo-auditable`, `cargo-cyclonedx` with `--locked`.
      - Rustup target add for all 5 triples.
      - GoReleaser: `goreleaser/goreleaser-action@v5` with `distribution: goreleaser` args `release --clean`.
      - Env: `GITHUB_TOKEN`, `HOMEBREW_TAP_TOKEN`.
    - If tag push: After GoReleaser, run `actions/attest-build-provenance@v1` with `subject-paths: dist/checksums.txt`.
    
    This simplifies to ~50 lines, eliminates actionlint issues, and handles all builds/publishing in one job.
    
    Reference new .goreleaser.yml for config integration.
    
    ### scripts(NEW)
    
    # Create scripts directory for installer files to be included in releases.
    
    ### scripts/install.sh(NEW)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Create Unix shell installer script.
    
    - Shebang: `#!/usr/bin/env bash`.
    - Set `-euo pipefail`.
    - Vars: `OWNER='EvilBit-Labs'`, `REPO='StringyMcStringFace'`, `BINARY='stringy'`, `INSTALL_DIR='/usr/local/bin'`.
    - Version: Use `$VERSION` or fetch latest tag via GitHub API (`curl -s https://api.github.com/repos/$OWNER/$REPO/releases/latest | jq -r .tag_name`).
    - Detect OS/Arch: `OS=$(uname -s | tr '[:upper:]' '[:lower:]')`, `ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/' )`.
    - Temp dir: `mktemp -d` with trap cleanup.
    - Download: Asset name `${BINARY}_${VERSION}_${OS}_${ARCH}.tar.xz`, URL from GitHub releases, `curl -L -o`.
    - Download checksums.txt, verify `sha256sum -c --ignore-missing`.
    - Extract: `tar -xJf`, `sudo install -m 755 stringy $INSTALL_DIR/`.
    - Success msg: 'Successfully installed Stringy! Ready to start looking at your binaries!'.
    
    Matches cargo-dist shell installer behavior, uses GoReleaser naming.
    
    ### scripts/install.ps1(NEW)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Create Windows PowerShell installer script.
    
    - Param: `[CmdletBinding()] param( [string]$Version = '' )`.
    - `$ErrorActionPreference = 'Stop'`.
    - Vars: `$Owner = 'EvilBit-Labs'`, `$Repo = 'StringyMcStringFace'`, `$Binary = 'stringy'`, `$InstallDir = "$env:ProgramFiles\Stringy"`.
    - Version: If empty, `$latest = Invoke-RestMethod "https://api.github.com/repos/$Owner/$Repo/releases/latest"; $Version = $latest.tag_name`.
    - Arch: `$Arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { 'amd64' } else { 'arm64' }`; OS='windows'.
    - Temp: `$tempDir = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid()`.
    - Asset: `${Binary}_${Version}_windows_${Arch}.zip`.
    - Download: `Invoke-WebRequest -Uri "https://github.com/$Owner/$Repo/releases/download/$Version/$asset" -OutFile "$tempDir\$asset"`.
    - Download checksums.txt, compute hash `Get-FileHash`, verify against file.
    - Extract: `Expand-Archive -Path "$tempDir\$asset" -DestinationPath $InstallDir`.
    - Add to PATH: `[Environment]::SetEnvironmentVariable('Path', "$env:Path;$InstallDir", 'User')`.
    - Msg: Success message, note to restart shell.
    
    Replicates cargo-dist PowerShell installer with GoReleaser compatibility.
    
    ### dist-workspace.toml(DELETE)
    
    # Remove cargo-dist workspace configuration as it's replaced by .goreleaser.yml.
    
    ### justfile(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Update justfile to remove cargo-dist and enhance GoReleaser.
    
    - In `install-tools`: Remove `cargo-dist` from binstall list (lines ~73,77).
    - Remove dist recipes: `dist`, `dist-check`, `dist-plan`, `dist-generate-ci` (lines 291-304).
    - Update `ci-check`: Remove `dist-plan` dependency (line 278), now `pre-commit-run fmt-check lint-rust lint-rust-min test-ci build-release audit coverage-check`.
    - Keep all `goreleaser-*` recipes (lines 355-425) as they align with new config; add comment: '# GoReleaser handles releases via .goreleaser.yml and GitHub Actions'.
    - Optional: Add `release: goreleaser-snapshot` alias for local testing.
    
    Ensures clean transition, retains macOS SDK handling in GoReleaser recipes.
    
    Reference .goreleaser.yml for integration.
    
    ### Cargo.toml(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Minor update to Cargo.toml for profile clarity.
    
    - Rename `[profile.dist]` to `[profile.release]` or add comment: '# Previously for cargo-dist; GoReleaser uses --release profile with optional thin LTO via ldflags'.
    - Keep `inherits = 'release'`, `lto = 'thin'`.
    - No other changes needed as GoReleaser can reference this via build flags.
    
    Reference .goreleaser.yml where ldflags incorporate thin LTO.
    
    ### .github/workflows/security.yml(MODIFY)
    
    # Remove cargo-dist from security workflow.
    
    - In 'Install cargo tools' step (line ~34): Remove `cargo-dist` from `taiki-e/install-action` tool list.
    - Remove 'Run cargo dist check' step (lines 41-43).
    - Keep cargo-outdated, cargo-deny.
    
    Aligns with migration; security checks now focus on other tools.
    
    ### .github/workflows/copilot-setup-steps.yml(MODIFY)
    
    References: 
    
    - justfile(MODIFY)
    
    # Remove cargo-dist from Copilot setup.
    
    - In 'Install cargo tools' step (line ~49): Remove `cargo-dist` from tool list.
    - In 'just install-tools' run (line 58): This will now skip cargo-dist due to justfile update.
    - Update summary echo (line 72): Remove cargo-dist version check.
    
    Ensures setup doesn't install obsolete tool.
    
    ### docs/src/installation.md(MODIFY)
    
    References: 
    
    - scripts/install.sh(NEW)
    - scripts/install.ps1(NEW)
    
    # Update installation docs for GoReleaser releases.
    
    - Add section 'Binary Releases' after 'Prerequisites':
      - 'Quick Install (Unix/macOS)': `curl -sSfL https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.sh | sh`.
      - 'Quick Install (Windows)': `irm https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.ps1 | iex`.
      - 'Homebrew': `brew tap EvilBit-Labs/homebrew-tap && brew install stringy`.
      - 'Manual': Download archives from GitHub Releases.
    - Update intro note: 'Binary releases available from v0.1 via GoReleaser; source install for development'.
    - Retain 'From Source', 'Development Build', etc. sections.
    
    Reference installer scripts for commands.
    
    ### docs/src/contributing.md(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    - .github/workflows/release.yml(MODIFY)
    - justfile(MODIFY)
    
    # Update contributing docs for release process.
    
    - In 'Release Checklist':
      1. Update Cargo.toml version.
      2. Update CHANGELOG.md.
      3. Run `just ci-check`.
      4. Update docs.
      5. Test: `just goreleaser-snapshot`.
      6. Tag/push: `git tag vX.Y.Z && git push --tags`.
      7. GitHub Actions auto-publishes via GoReleaser.
      8. Verify releases, Homebrew, artifacts.
    - Add 'Testing Releases': Use `just goreleaser-snapshot` for local dry-run; `just goreleaser-check` validates config.
    - Add 'Automation': Tags trigger workflow building 5 platforms, installers, SBOM, attestations, Homebrew push.
    
    Reference .goreleaser.yml and release.yml.
    
    ### README.md(MODIFY)
    
    References: 
    
    - docs/src/installation.md(MODIFY)
    
    # Update README installation section.
    
    - After 'Installation' header: Add 'Pre-built binaries available from v0.1 via GitHub Releases, Homebrew, and one-liners. See docs/installation.md for details.'
    - Retain 'From Source' and 'Development Build' as primary methods.
    - No major changes; keep concise.

    Developer Humor

    🎉 Swapping cargo-dist for GoReleaser's grace,\n> No more lint warnings in our CI space!\n> Builds fly fast with Zig's embrace,\n> Installers ready, Homebrew in place.\n> Stringy releases, now with style and pace! 🚀


    Execution Information

    Branch: main
    Commit: 37cfc7c


    💡 Tips

    Supported Commands (Inside Comments)

    • Use @traycerai generate to iterate on the previous version of the implementation plan.

    Supported Commands (Inside Description)

    • Add @traycerai ignore anywhere in the ticket description to prevent this ticket from being processed.
    • Add @traycerai branch:<branch-name> anywhere in the ticket description to specify the target branch for the implementation plan.

    Community

    • Join our Discord Community to get help, request features, and share feedback.
    • Follow us on X/Twitter for updates and announcements.
  3. added this to the v0.1 milestone on Nov 10, 2025
  4. unclesp1d3r commented on Nov 10, 2025

    @unclesp1d3r
    MemberAuthor

    @coderabbitai Enhance this issue body with additional context and a proposed solution. Improve the issue title and assign the proper labels and other metadata.

  5. changed the title [-]Move from cargo-dist to GoReleaser[/-] [+]Migrate release tooling from cargo-dist to GoReleaser before v0.1[/+] on Nov 10, 2025
  6. added
    enhancementNew feature or request
    github_actionsPull requests that update GitHub Actions code
    MVPMinimum viable product features
    on Nov 10, 2025
  7. coderabbitai commented on Nov 10, 2025

    @coderabbitai
    Contributor

    Tip

    For best results, initiate chat on the files or code changes.

    🧩 Analysis chain

    🏁 Script executed:

    #!/bin/bash
    
    # Fetch the current issue details
    gh issue view 65 --json title,body,labels,assignees,state
    
    # Check for cargo-dist configuration
    fd -t f "dist.toml|Cargo.toml" -x cat {}
    
    # Check for existing GitHub Actions related to cargo-dist
    fd -t f ".yml|.yaml" .github/workflows -x cat {}
    

    Length of output: 27646


    🏁 Script executed:

    #!/bin/bash
    
    # Update the issue with enhanced content
    gh issue edit 65 \
      --title "Migrate release tooling from cargo-dist to GoReleaser before v0.1" \
      --body "## Context
    
    Our current release process uses [cargo-dist](https://github.com/axodotdev/cargo-dist) to build and publish releases. While cargo-dist has served us well, we've encountered some friction points that would be resolved by migrating to [GoReleaser](https://goreleaser.com/).
    
    ## Current State
    
    The cargo-dist configuration includes:
    - Multi-platform builds (Linux x86_64, Linux ARM, macOS, Windows)
    - GitHub Release creation with auto-generated release notes
    - Homebrew formula publishing to \`EvilBit-Labs/homebrew-tap\`
    - SBOM generation using cargo-cyclonedx
    - Build attestations for supply chain security
    - Artifact signing and checksums
    
    ## Problems with Current Approach
    
    1. **Workflow Complexity**: The generated \`.github/workflows/release.yml\` is over 300 lines and difficult to customize
    2. **Actionlint Warnings**: The auto-generated workflow consistently triggers actionlint warnings, cluttering our CI output
    3. **Limited Flexibility**: cargo-dist's opinionated approach makes it challenging to customize the release process
    4. **Maintenance Burden**: Need to keep cargo-dist installation scripts in sync across multiple workflow files (\`security.yml\`, \`copilot-setup-steps.yml\`)
    
    ## Why GoReleaser?
    
    1. **Better Rust Support**: GoReleaser now has official Rust/Cargo support with good cross-compilation capabilities
    2. **More Mature Ecosystem**: Extensive plugin system and well-documented customization options
    3. **Cleaner Configuration**: YAML-based config is easier to understand and maintain than generated workflows
    4. **Flexible**: Easier to customize release behavior, artifacts, and publishing strategies
    5. **No Generated Workflows**: Uses a single reusable action, avoiding actionlint issues
    6. **Rich Feature Set**: Built-in support for Docker, Snapcraft, AUR, and many other distribution channels
    
    ## Proposed Solution
    
    ### Phase 1: Setup GoReleaser Configuration
    
    1. Create \`.goreleaser.yml\` configuration file with:
       - Rust build configuration for all target platforms
       - Archive generation matching current artifact structure
       - Checksum generation
       - GitHub Release publishing
    
    ### Phase 2: Migrate Publishing Targets
    
    1. **Homebrew**: Configure GoReleaser's Homebrew tap publisher
       - Target: \`EvilBit-Labs/homebrew-tap\`
       - Ensure formula matches current structure
    2. **SBOM Generation**: Integrate SBOM generation (cargo-cyclonedx or built-in)
    3. **Attestations**: Configure artifact signing and attestations
    
    ### Phase 3: Update CI/CD
    
    1. Replace \`.github/workflows/release.yml\` with minimal GoReleaser workflow
    2. Remove cargo-dist installation from:
       - \`security.yml\`
       - \`copilot-setup-steps.yml\`
    3. Update any documentation referencing cargo-dist
    
    ### Phase 4: Testing & Validation
    
    1. Test release process with pre-release tag
    2. Verify all artifacts are generated correctly
    3. Confirm Homebrew formula updates work
    4. Validate checksums and signatures
    5. Test installation on all supported platforms
    
    ## Success Criteria
    
    - [ ] GoReleaser configuration successfully builds all current platforms
    - [ ] GitHub Releases match current format and content
    - [ ] Homebrew tap updates automatically
    - [ ] SBOMs are generated for all artifacts
    - [ ] Attestations/signatures work correctly
    - [ ] Release workflow is under 100 lines
    - [ ] No actionlint warnings
    - [ ] Successfully complete a test release
    
    ## References
    
    - [GoReleaser Rust/Cargo Documentation](https://goreleaser.com/customization/builds/#rust)
    - [GoReleaser Homebrew Documentation](https://goreleaser.com/customization/homebrew/)
    - Current cargo-dist config: \`Cargo.toml\` (profile.dist section)
    - Current release workflow: \`.github/workflows/release.yml\`
    
    ## Timeline
    
    This migration should be completed before releasing v0.1, as changing release tooling after the first major release would be more disruptive to users who may have automated installations." \
      --add-label "enhancement" \
      --add-label "ci/cd" \
      --add-label "tooling" \
      --add-assignee "unclesp1d3r"
    

    Length of output: 122


    🏁 Script executed:

    #!/bin/bash
    
    # List available labels in the repository
    echo "Available labels:"
    gh label list --limit 100
    
    # Let's try updating the issue without the problematic label first
    # We'll add labels that are more likely to exist
    gh issue edit 65 \
      --title "Migrate release tooling from cargo-dist to GoReleaser before v0.1" \
      --body "## Context
    
    Our current release process uses [cargo-dist](https://github.com/axodotdev/cargo-dist) to build and publish releases. While cargo-dist has served us well, we've encountered some friction points that would be resolved by migrating to [GoReleaser](https://goreleaser.com/).
    
    ## Current State
    
    The cargo-dist configuration includes:
    - Multi-platform builds (Linux x86_64, Linux ARM, macOS, Windows)
    - GitHub Release creation with auto-generated release notes
    - Homebrew formula publishing to \`EvilBit-Labs/homebrew-tap\`
    - SBOM generation using cargo-cyclonedx
    - Build attestations for supply chain security
    - Artifact signing and checksums
    
    ## Problems with Current Approach
    
    1. **Workflow Complexity**: The generated \`.github/workflows/release.yml\` is over 300 lines and difficult to customize
    2. **Actionlint Warnings**: The auto-generated workflow consistently triggers actionlint warnings, cluttering our CI output
    3. **Limited Flexibility**: cargo-dist's opinionated approach makes it challenging to customize the release process
    4. **Maintenance Burden**: Need to keep cargo-dist installation scripts in sync across multiple workflow files (\`security.yml\`, \`copilot-setup-steps.yml\`)
    
    ## Why GoReleaser?
    
    1. **Better Rust Support**: GoReleaser now has official Rust/Cargo support with good cross-compilation capabilities
    2. **More Mature Ecosystem**: Extensive plugin system and well-documented customization options
    3. **Cleaner Configuration**: YAML-based config is easier to understand and maintain than generated workflows
    4. **Flexible**: Easier to customize release behavior, artifacts, and publishing strategies
    5. **No Generated Workflows**: Uses a single reusable action, avoiding actionlint issues
    6. **Rich Feature Set**: Built-in support for Docker, Snapcraft, AUR, and many other distribution channels
    
    ## Proposed Solution
    
    ### Phase 1: Setup GoReleaser Configuration
    
    1. Create \`.goreleaser.yml\` configuration file with:
       - Rust build configuration for all target platforms
       - Archive generation matching current artifact structure
       - Checksum generation
       - GitHub Release publishing
    
    ### Phase 2: Migrate Publishing Targets
    
    1. **Homebrew**: Configure GoReleaser's Homebrew tap publisher
       - Target: \`EvilBit-Labs/homebrew-tap\`
       - Ensure formula matches current structure
    2. **SBOM Generation**: Integrate SBOM generation (cargo-cyclonedx or built-in)
    3. **Attestations**: Configure artifact signing and attestations
    
    ### Phase 3: Update CI/CD
    
    1. Replace \`.github/workflows/release.yml\` with minimal GoReleaser workflow
    2. Remove cargo-dist installation from:
       - \`security.yml\`
       - \`copilot-setup-steps.yml\`
    3. Update any documentation referencing cargo-dist
    
    ### Phase 4: Testing & Validation
    
    1. Test release process with pre-release tag
    2. Verify all artifacts are generated correctly
    3. Confirm Homebrew formula updates work
    4. Validate checksums and signatures
    5. Test installation on all supported platforms
    
    ## Success Criteria
    
    - [ ] GoReleaser configuration successfully builds all current platforms
    - [ ] GitHub Releases match current format and content
    - [ ] Homebrew tap updates automatically
    - [ ] SBOMs are generated for all artifacts
    - [ ] Attestations/signatures work correctly
    - [ ] Release workflow is under 100 lines
    - [ ] No actionlint warnings
    - [ ] Successfully complete a test release
    
    ## References
    
    - [GoReleaser Rust/Cargo Documentation](https://goreleaser.com/customization/builds/#rust)
    - [GoReleaser Homebrew Documentation](https://goreleaser.com/customization/homebrew/)
    - Current cargo-dist config: \`Cargo.toml\` (profile.dist section)
    - Current release workflow: \`.github/workflows/release.yml\`
    
    ## Timeline
    
    This migration should be completed before releasing v0.1, as changing release tooling after the first major release would be more disruptive to users who may have automated installations." \
      --add-assignee "unclesp1d3r"
    
    echo ""
    echo "Issue title and body updated successfully"
    

    Length of output: 1642


    🏁 Script executed:

    #!/bin/bash
    
    # Add appropriate labels to the issue
    gh issue edit 65 \
      --add-label "enhancement" \
      --add-label "github_actions" \
      --add-label "priority:high" \
      --add-label "MVP"
    
    echo "Labels added successfully"
    
    # Verify the final state of the issue
    echo ""
    echo "Final issue state:"
    gh issue view 65 --json title,labels,assignees,url | jq '.'
    

    Length of output: 1074


    @unclesp1d3r I've successfully enhanced issue #65 with the following improvements:

    ✅ Updated Title

    "Migrate release tooling from cargo-dist to GoReleaser before v0.1"

    • More descriptive and includes the timeline constraint

    ✅ Enhanced Issue Body

    Added comprehensive context including:

    • Context: Explains current cargo-dist usage and rationale for migration
    • Current State: Documents all existing features (multi-platform builds, Homebrew publishing, SBOMs, attestations)
    • Problems: Lists specific issues with cargo-dist (300+ line workflow, actionlint warnings, limited flexibility, maintenance burden)
    • Why GoReleaser: 6 key benefits including better Rust support and no generated workflows
    • Proposed Solution: 4-phase migration plan:
      1. Setup GoReleaser configuration
      2. Migrate publishing targets (Homebrew, SBOMs, attestations)
      3. Update CI/CD workflows
      4. Testing & validation
    • Success Criteria: 8 specific checkboxes to track completion
    • References: Links to GoReleaser documentation and current configurations
    • Timeline: Emphasizes completion before v0.1 release

    ✅ Added Metadata

    • Labels: enhancement, github_actions, priority:high, MVP
    • Assignee: unclesp1d3r

    The issue now provides a clear, actionable roadmap for the migration with all the context needed for implementation! 🚀

  8. traycerai commented on Nov 10, 2025

    @traycerai

    I have updated the Implementation Plan to reflect the recent changes in the ticket.

    Previous Plan

    Observations

    The project currently uses cargo-dist v0.30.2 for release automation, which generates a complex GitHub Actions workflow. The migration to GoReleaser is partially prepared—the justfile already contains GoReleaser commands with sophisticated macOS SDK handling. The current setup includes:

    • Targets: 5 platforms (aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, x86_64-pc-windows-msvc)
    • Installers: shell, powershell, and Homebrew tap (EvilBit-Labs/homebrew-tap)
    • Security features: GitHub attestations, cargo-auditable, cargo-cyclonedx (SBOM)
    • Secret: HOMEBREW_TAP_TOKEN for tap publishing
    • Build profile: Custom profile.dist with thin LTO

    GoReleaser's 2025 Rust support (alpha since v2.5) provides feature parity with cargo-zigbuild as the default builder, native Homebrew Casks publisher, SBOM generation, and GitHub attestations integration.

    Approach

    Replace cargo-dist with GoReleaser by creating a comprehensive .goreleaser.yml configuration that maintains all current features, replacing the auto-generated release workflow with a GoReleaser-based GitHub Actions workflow, removing cargo-dist configuration files, updating the justfile to remove cargo-dist commands, and updating documentation to reflect the new release process. Use cargo-zigbuild for cross-compilation, cargo-auditable for embedded dependency metadata, and cargo-cyclonedx for SBOM generation.

    Reasoning

    I explored the repository structure and identified the current cargo-dist configuration in dist-workspace.toml and the auto-generated .github/workflows/release.yml. I examined the Cargo.toml to understand the project metadata and the custom profile.dist build profile. I reviewed the justfile and discovered existing GoReleaser commands with macOS SDK handling, indicating partial preparation. I searched for references to cargo-dist throughout the codebase and found them in the justfile's install-tools and ci-check recipes. I researched GoReleaser's 2025 Rust support capabilities, including cargo-zigbuild vs cross comparison, Homebrew Casks publishing, SBOM generation options, and GitHub attestations integration. I verified the secret requirements by examining the current Homebrew publishing workflow.

    Proposed File Changes

    📄 .goreleaser.yml (NEW) 🔗

    References

    Create a comprehensive GoReleaser configuration file that replicates all cargo-dist features:

    Project metadata section: Set project_name to "stringy" and configure before.hooks to install required tools (rustup components, cargo-zigbuild, cargo-auditable, cargo-cyclonedx).

    Builds section: Configure a single Rust build with builder: rust, using cargo-zigbuild as the default tool. Set command: auditable with flags: [zigbuild, --release] to enable cargo-auditable. Specify binary: stringy and define all five targets matching the current cargo-dist configuration (aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, x86_64-pc-windows-msvc). Configure environment variables for macOS SDK paths (SDKROOT, MACOSX_DEPLOYMENT_TARGET, CARGO_ZIGBUILD_SYSROOT, RUSTFLAGS) to match the sophisticated handling in the existing justfile GoReleaser commands. Set ldflags to enable thin LTO matching the profile.dist configuration in Cargo.toml.

    Archives section: Configure separate archive formats for Unix (.tar.xz) and Windows (.zip) matching current cargo-dist settings. Use name template: {{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}.

    Checksum section: Set name_template: checksums.txt for predictable naming required by installer scripts and attestations.

    SBOM section: Configure cargo-cyclonedx to generate CycloneDX JSON SBOMs. Use artifacts: any since cargo-cyclonedx operates at the workspace level. Set command to cargo with args [cyclonedx, -f, json, --spec-version, "1.4", --output, $document]. Configure document output as {{ .ProjectName }}_{{ .Version }}.cyclonedx.json.

    Homebrew Casks section: Configure the Homebrew tap publisher with repository owner "EvilBit-Labs", name "homebrew-tap", branch "main", and token from environment variable HOMEBREW_TAP_TOKEN. Set directory to "Casks" (note: GoReleaser v2.10+ uses Casks, not Formula). Configure commit author name and email (use project-specific bot identity). Set formula name to "stringy", homepage to the repository URL from Cargo.toml, description from Cargo.toml, and license "Apache-2.0". Specify binary as "stringy". Add install success message matching the current cargo-dist configuration.

    Release section: Configure extra_files to include shell and PowerShell installer scripts (install.sh, install.ps1) that will be created. Set draft: false and configure release notes generation.

    Docker digest section: Set name_template: digests.txt for GitHub attestations integration (even if not using Docker initially, this enables future expansion).

    📄 .github/workflows/release.yml (MODIFY) 🔗

    References

    Replace the entire auto-generated cargo-dist workflow with a new GoReleaser-based workflow:

    Workflow metadata: Keep the name "Release" and configure permissions for contents: write, id-token: write, and attestations: write (required for GitHub attestations).

    Trigger: Maintain the existing tag-based trigger pattern tags: ['**[0-9]+.[0-9]+.[0-9]+*'] and keep the pull_request trigger for testing.

    Job: release: Configure to run on ubuntu-latest. Add checkout step with fetch-depth: 0 for full git history (required by GoReleaser). Add Rust toolchain setup using actions-rust-lang/setup-rust-toolchain@v1 with stable toolchain. Install Zig using goto-bus-stop/setup-zig@v2 with version 0.13.0 or latest. Install cargo-zigbuild, cargo-auditable, and cargo-cyclonedx using cargo install commands with --locked flag. Add rustup target add commands for all five target platforms. Use goreleaser/goreleaser-action@v6 with version: latest and args: release --clean. Configure environment variables: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} for release creation and HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} for tap publishing.

    Attestation steps: After GoReleaser completes, add actions/attest-build-provenance@v3 step with subject-checksums: ./dist/checksums.txt to attest all built artifacts. Add conditional check to only run on tag pushes, not pull requests.

    Workflow optimization: Unlike the complex multi-job cargo-dist workflow with separate plan/build-local/build-global/host/publish jobs, GoReleaser handles everything in a single job, significantly simplifying the workflow and addressing the actionlint issues mentioned in the GitHub issue.

    📁 scripts (NEW) 🔗

    Create a scripts directory to hold installer scripts that will be uploaded as release assets.

    📄 scripts/install.sh (NEW) 🔗

    References

    Create a shell installer script for Unix-like systems (Linux, macOS) that provides one-line installation:

    Configuration variables: Set OWNER="EvilBit-Labs", REPO="StringyMcStringFace", BINARY="stringy", INSTALL_DIR="/usr/local/bin".

    Version resolution: Support VERSION environment variable override, otherwise fetch latest release tag from GitHub API using curl and grep/jq.

    Platform detection: Detect OS using uname -s (convert to lowercase) and architecture using uname -m (map x86_64→amd64, aarch64→arm64, armv7l→armv7) to match GoReleaser naming conventions.

    Download and verify: Create temporary directory with cleanup trap. Construct asset filename matching GoReleaser's archive naming template. Download the archive and checksums.txt from GitHub releases. Verify SHA256 checksum using sha256sum -c against the checksums.txt file.

    Installation: Extract the archive using tar, install the binary to INSTALL_DIR using sudo install -m 0755, and display version information.

    Error handling: Use set -euo pipefail for strict error handling and provide clear error messages.

    This replaces the shell installer that cargo-dist would have generated.

    📄 scripts/install.ps1 (NEW) 🔗

    References

    Create a PowerShell installer script for Windows that provides one-line installation:

    Parameters: Define CmdletBinding parameters for Owner (default "EvilBit-Labs"), Repo (default "StringyMcStringFace"), Binary (default "stringy"), and optional Version.

    Configuration: Set $ErrorActionPreference = "Stop" for strict error handling.

    Platform detection: Set os="windows" and map $env:PROCESSOR_ARCHITECTURE to GoReleaser naming (amd64, arm64).

    Version resolution: If Version not provided, fetch latest release from GitHub API using Invoke-RestMethod and extract tag_name.

    Download and verify: Create temporary directory using [System.IO.Path]::GetTempPath() with GUID. Construct asset filename matching GoReleaser's archive naming template (.zip for Windows). Download archive and checksums.txt using Invoke-WebRequest. Verify SHA256 using Get-FileHash and compare against expected checksum from checksums.txt.

    Installation: Extract zip to $env:ProgramFiles\StringyMcStringFace using [System.IO.Compression.ZipFile]::ExtractToDirectory. Add installation directory to user PATH environment variable if not already present. Display version information.

    User guidance: Inform user to open new terminal for PATH changes to take effect.

    This replaces the PowerShell installer that cargo-dist would have generated.

    📄 dist-workspace.toml (DELETE) 🔗

    Remove the cargo-dist configuration file as it is no longer needed. All release configuration is now handled by .goreleaser.yml.

    📄 justfile (MODIFY) 🔗

    References

    Update the justfile to remove cargo-dist references and clean up GoReleaser integration:

    install-tools recipe (lines 72-77): Remove cargo-dist from the cargo binstall command list in both Windows and Unix variants. Keep cargo-release, cargo-cyclonedx, cargo-auditable, and other tools.

    Remove dist recipes (lines 291-304): Delete the dist, dist-check, dist-plan, and dist-generate-ci recipes as they are cargo-dist specific and no longer needed.

    Update ci-check recipe (line 278): Remove dist-plan from the dependency list. The recipe should become: ci-check: pre-commit-run fmt-check lint-rust lint-rust-min test-ci build-release audit coverage-check.

    Keep GoReleaser recipes (lines 352-425): Retain all existing goreleaser-* recipes (goreleaser-check, goreleaser-build, goreleaser-snapshot, goreleaser-build-target, goreleaser-clean) as they are already well-configured with proper macOS SDK handling and will work with the new .goreleaser.yml.

    Add release recipe comment: Update or add a comment above the GoReleaser section explaining that GoReleaser is used for releases and referencing the .goreleaser.yml configuration file.

    📄 Cargo.toml (MODIFY) 🔗

    References

    Update the Cargo.toml to reflect the tooling change:

    profile.dist section (lines 33-36): Rename the [profile.dist] section to [profile.release-optimized] or similar, since the "dist" name is cargo-dist specific. Alternatively, keep it as-is since GoReleaser will use the --release flag which uses the [profile.release] profile, and the dist profile can remain for local testing. The thin LTO configuration should be documented as optional for GoReleaser builds.

    Comment update: Add a comment above the profile section explaining that this profile was previously used by cargo-dist and is now optional for GoReleaser, which uses the standard release profile. Alternatively, if keeping the profile, note that it can be used with GoReleaser by adding --profile dist to the build flags in .goreleaser.yml.

    Note: This change is optional and low-priority. The profile can remain as-is without affecting GoReleaser functionality.

    📄 docs/src/installation.md (MODIFY) 🔗

    References

    Update the installation documentation to reflect the new GoReleaser-based release process:

    Add new section after "Prerequisites" (around line 19): Add a "Binary Releases" section that explains users can download pre-built binaries from GitHub Releases once v0.1 is released. Include subsections for:

    • Quick Install (Unix/Linux/macOS): Show the one-line curl installer: curl -fsSL https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.sh | bash
    • Quick Install (Windows): Show the one-line PowerShell installer: iwr -useb https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.ps1 | iex
    • Homebrew: Show the Homebrew tap installation: brew tap EvilBit-Labs/tap followed by brew install stringy
    • Manual Download: Explain users can download archives directly from the GitHub Releases page and extract them manually

    Update note at top (line 3): Modify the note to mention that binary releases will be available starting with v0.1, and until then, installation from source is required.

    Keep existing sections: Retain all existing "From Source", "Development Build", "Platform-Specific Notes", "Docker", and "Troubleshooting" sections as they remain valid.

    This provides users with multiple installation options once releases are published via GoReleaser.

    📄 docs/src/contributing.md (MODIFY) 🔗

    References

    Update the release process documentation to reflect GoReleaser:

    Release Checklist section (lines 415-422): Update the checklist to reflect the new GoReleaser-based process:

    1. Update version in Cargo.toml
    2. Update CHANGELOG.md
    3. Run full test suite (just ci-check)
    4. Update documentation
    5. Test release locally (just goreleaser-snapshot)
    6. Create and push release tag (git tag v0.x.x && git push origin v0.x.x)
    7. GitHub Actions will automatically build and publish the release via GoReleaser
    8. Verify release artifacts on GitHub Releases page
    9. Verify Homebrew tap was updated
    10. Publish to crates.io (when ready)

    Add new subsection: Add a "Testing Releases Locally" subsection that explains developers can test the release process using just goreleaser-snapshot which creates a snapshot release without publishing. Mention that just goreleaser-check validates the GoReleaser configuration.

    Add new subsection: Add a "Release Automation" subsection explaining that releases are automated via GoReleaser and GitHub Actions, triggered by pushing version tags. Mention that the workflow builds for all supported platforms, generates installers, creates SBOMs, adds attestations, and publishes to the Homebrew tap automatically.

    📄 README.md (MODIFY) 🔗

    References

    Update the README installation section to mention the upcoming binary releases:

    Installation section (lines 70-88): Add a brief note at the beginning of the section (after line 72) mentioning that pre-built binaries will be available via Homebrew, shell/PowerShell installers, and direct downloads from GitHub Releases starting with v0.1. Add a sentence directing users to the full installation documentation at docs/src/installation.md for all installation methods.

    Keep existing content: Retain the "From Source" and "Development Build" subsections as they remain the primary installation methods during development.

    This provides a preview of upcoming installation options without cluttering the README with detailed instructions that are better suited for the documentation.

    Diagram

    sequenceDiagram
        participant Dev as Developer
        participant Git as Git Repository
        participant GHA as GitHub Actions
        participant GR as GoReleaser
        participant GH as GitHub Releases
        participant HB as Homebrew Tap
        participant User as End User
    
        Dev->>Git: Push version tag (v0.1.0)
        Git->>GHA: Trigger release workflow
        
        GHA->>GHA: Setup Rust toolchain
        GHA->>GHA: Install Zig + cargo-zigbuild
        GHA->>GHA: Install cargo-auditable
        GHA->>GHA: Install cargo-cyclonedx
        
        GHA->>GR: Run goreleaser release
        
        GR->>GR: Build for 5 platforms<br/>(with cargo-auditable)
        GR->>GR: Create archives (.tar.xz, .zip)
        GR->>GR: Generate checksums.txt
        GR->>GR: Generate SBOM (CycloneDX)
        GR->>GR: Create installer scripts
        
        GR->>GH: Upload release artifacts
        GR->>HB: Push Homebrew Cask
        
        GHA->>GHA: Attest build provenance
        GHA->>GH: Upload attestations
        
        User->>GH: Download via install.sh/ps1
        User->>HB: brew install stringy
        User->>GH: Manual download
    
    Loading

    Import In IDE

    VSCode Icon Cursor Icon Windsurf Icon

    🤖 Prompt for AI Agents
    I have created the following plan after thorough exploration and analysis of the codebase. Follow the below plan verbatim. Trust the files and references. Do not re-verify what's written in the plan. Explore only when absolutely necessary. First implement all the proposed file changes and then I'll review all the changes together at the end.
    
    ### Observations
    
    The project currently uses cargo-dist v0.30.2 for release automation, which generates a complex GitHub Actions workflow. The migration to GoReleaser is partially prepared—the justfile already contains GoReleaser commands with sophisticated macOS SDK handling. The current setup includes:
    
    - **Targets**: 5 platforms (aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, x86_64-pc-windows-msvc)
    - **Installers**: shell, powershell, and Homebrew tap (EvilBit-Labs/homebrew-tap)
    - **Security features**: GitHub attestations, cargo-auditable, cargo-cyclonedx (SBOM)
    - **Secret**: HOMEBREW_TAP_TOKEN for tap publishing
    - **Build profile**: Custom `profile.dist` with thin LTO
    
    GoReleaser's 2025 Rust support (alpha since v2.5) provides feature parity with cargo-zigbuild as the default builder, native Homebrew Casks publisher, SBOM generation, and GitHub attestations integration.
    
    ### Approach
    
    Replace cargo-dist with GoReleaser by creating a comprehensive `.goreleaser.yml` configuration that maintains all current features, replacing the auto-generated release workflow with a GoReleaser-based GitHub Actions workflow, removing cargo-dist configuration files, updating the justfile to remove cargo-dist commands, and updating documentation to reflect the new release process. Use cargo-zigbuild for cross-compilation, cargo-auditable for embedded dependency metadata, and cargo-cyclonedx for SBOM generation.
    
    ### Reasoning
    
    I explored the repository structure and identified the current cargo-dist configuration in `dist-workspace.toml` and the auto-generated `.github/workflows/release.yml`. I examined the `Cargo.toml` to understand the project metadata and the custom `profile.dist` build profile. I reviewed the `justfile` and discovered existing GoReleaser commands with macOS SDK handling, indicating partial preparation. I searched for references to cargo-dist throughout the codebase and found them in the justfile's `install-tools` and `ci-check` recipes. I researched GoReleaser's 2025 Rust support capabilities, including cargo-zigbuild vs cross comparison, Homebrew Casks publishing, SBOM generation options, and GitHub attestations integration. I verified the secret requirements by examining the current Homebrew publishing workflow.
    
    ## Mermaid Diagram
    
    sequenceDiagram
        participant Dev as Developer
        participant Git as Git Repository
        participant GHA as GitHub Actions
        participant GR as GoReleaser
        participant GH as GitHub Releases
        participant HB as Homebrew Tap
        participant User as End User
    
        Dev->>Git: Push version tag (v0.1.0)
        Git->>GHA: Trigger release workflow
        
        GHA->>GHA: Setup Rust toolchain
        GHA->>GHA: Install Zig + cargo-zigbuild
        GHA->>GHA: Install cargo-auditable
        GHA->>GHA: Install cargo-cyclonedx
        
        GHA->>GR: Run goreleaser release
        
        GR->>GR: Build for 5 platforms<br/>(with cargo-auditable)
        GR->>GR: Create archives (.tar.xz, .zip)
        GR->>GR: Generate checksums.txt
        GR->>GR: Generate SBOM (CycloneDX)
        GR->>GR: Create installer scripts
        
        GR->>GH: Upload release artifacts
        GR->>HB: Push Homebrew Cask
        
        GHA->>GHA: Attest build provenance
        GHA->>GH: Upload attestations
        
        User->>GH: Download via install.sh/ps1
        User->>HB: brew install stringy
        User->>GH: Manual download
    
    ## Proposed File Changes
    
    ### .goreleaser.yml(NEW)
    
    References: 
    
    - dist-workspace.toml(DELETE)
    - Cargo.toml(MODIFY)
    - justfile(MODIFY)
    
    Create a comprehensive GoReleaser configuration file that replicates all cargo-dist features:
    
    **Project metadata section**: Set `project_name` to "stringy" and configure `before.hooks` to install required tools (rustup components, cargo-zigbuild, cargo-auditable, cargo-cyclonedx).
    
    **Builds section**: Configure a single Rust build with `builder: rust`, using cargo-zigbuild as the default tool. Set `command: auditable` with `flags: [zigbuild, --release]` to enable cargo-auditable. Specify `binary: stringy` and define all five targets matching the current cargo-dist configuration (aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl, x86_64-pc-windows-msvc). Configure environment variables for macOS SDK paths (SDKROOT, MACOSX_DEPLOYMENT_TARGET, CARGO_ZIGBUILD_SYSROOT, RUSTFLAGS) to match the sophisticated handling in the existing justfile GoReleaser commands. Set `ldflags` to enable thin LTO matching the `profile.dist` configuration in `Cargo.toml`.
    
    **Archives section**: Configure separate archive formats for Unix (.tar.xz) and Windows (.zip) matching current cargo-dist settings. Use name template: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`.
    
    **Checksum section**: Set `name_template: checksums.txt` for predictable naming required by installer scripts and attestations.
    
    **SBOM section**: Configure cargo-cyclonedx to generate CycloneDX JSON SBOMs. Use `artifacts: any` since cargo-cyclonedx operates at the workspace level. Set command to `cargo` with args `[cyclonedx, -f, json, --spec-version, "1.4", --output, $document]`. Configure document output as `{{ .ProjectName }}_{{ .Version }}.cyclonedx.json`.
    
    **Homebrew Casks section**: Configure the Homebrew tap publisher with repository owner "EvilBit-Labs", name "homebrew-tap", branch "main", and token from environment variable `HOMEBREW_TAP_TOKEN`. Set directory to "Casks" (note: GoReleaser v2.10+ uses Casks, not Formula). Configure commit author name and email (use project-specific bot identity). Set formula name to "stringy", homepage to the repository URL from `Cargo.toml`, description from `Cargo.toml`, and license "Apache-2.0". Specify binary as "stringy". Add install success message matching the current cargo-dist configuration.
    
    **Release section**: Configure `extra_files` to include shell and PowerShell installer scripts (install.sh, install.ps1) that will be created. Set `draft: false` and configure release notes generation.
    
    **Docker digest section**: Set `name_template: digests.txt` for GitHub attestations integration (even if not using Docker initially, this enables future expansion).
    
    ### .github/workflows/release.yml(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    Replace the entire auto-generated cargo-dist workflow with a new GoReleaser-based workflow:
    
    **Workflow metadata**: Keep the name "Release" and configure permissions for `contents: write`, `id-token: write`, and `attestations: write` (required for GitHub attestations).
    
    **Trigger**: Maintain the existing tag-based trigger pattern `tags: ['**[0-9]+.[0-9]+.[0-9]+*']` and keep the pull_request trigger for testing.
    
    **Job: release**: Configure to run on ubuntu-latest. Add checkout step with `fetch-depth: 0` for full git history (required by GoReleaser). Add Rust toolchain setup using `actions-rust-lang/setup-rust-toolchain@v1` with stable toolchain. Install Zig using `goto-bus-stop/setup-zig@v2` with version 0.13.0 or latest. Install cargo-zigbuild, cargo-auditable, and cargo-cyclonedx using cargo install commands with `--locked` flag. Add rustup target add commands for all five target platforms. Use `goreleaser/goreleaser-action@v6` with `version: latest` and `args: release --clean`. Configure environment variables: `GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}` for release creation and `HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}` for tap publishing.
    
    **Attestation steps**: After GoReleaser completes, add `actions/attest-build-provenance@v3` step with `subject-checksums: ./dist/checksums.txt` to attest all built artifacts. Add conditional check to only run on tag pushes, not pull requests.
    
    **Workflow optimization**: Unlike the complex multi-job cargo-dist workflow with separate plan/build-local/build-global/host/publish jobs, GoReleaser handles everything in a single job, significantly simplifying the workflow and addressing the actionlint issues mentioned in the GitHub issue.
    
    ### scripts(NEW)
    
    Create a scripts directory to hold installer scripts that will be uploaded as release assets.
    
    ### scripts/install.sh(NEW)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    Create a shell installer script for Unix-like systems (Linux, macOS) that provides one-line installation:
    
    **Configuration variables**: Set OWNER="EvilBit-Labs", REPO="StringyMcStringFace", BINARY="stringy", INSTALL_DIR="/usr/local/bin".
    
    **Version resolution**: Support VERSION environment variable override, otherwise fetch latest release tag from GitHub API using curl and grep/jq.
    
    **Platform detection**: Detect OS using `uname -s` (convert to lowercase) and architecture using `uname -m` (map x86_64→amd64, aarch64→arm64, armv7l→armv7) to match GoReleaser naming conventions.
    
    **Download and verify**: Create temporary directory with cleanup trap. Construct asset filename matching GoReleaser's archive naming template. Download the archive and checksums.txt from GitHub releases. Verify SHA256 checksum using `sha256sum -c` against the checksums.txt file.
    
    **Installation**: Extract the archive using tar, install the binary to INSTALL_DIR using `sudo install -m 0755`, and display version information.
    
    **Error handling**: Use `set -euo pipefail` for strict error handling and provide clear error messages.
    
    This replaces the shell installer that cargo-dist would have generated.
    
    ### scripts/install.ps1(NEW)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    Create a PowerShell installer script for Windows that provides one-line installation:
    
    **Parameters**: Define CmdletBinding parameters for Owner (default "EvilBit-Labs"), Repo (default "StringyMcStringFace"), Binary (default "stringy"), and optional Version.
    
    **Configuration**: Set `$ErrorActionPreference = "Stop"` for strict error handling.
    
    **Platform detection**: Set os="windows" and map `$env:PROCESSOR_ARCHITECTURE` to GoReleaser naming (amd64, arm64).
    
    **Version resolution**: If Version not provided, fetch latest release from GitHub API using `Invoke-RestMethod` and extract tag_name.
    
    **Download and verify**: Create temporary directory using `[System.IO.Path]::GetTempPath()` with GUID. Construct asset filename matching GoReleaser's archive naming template (.zip for Windows). Download archive and checksums.txt using `Invoke-WebRequest`. Verify SHA256 using `Get-FileHash` and compare against expected checksum from checksums.txt.
    
    **Installation**: Extract zip to `$env:ProgramFiles\StringyMcStringFace` using `[System.IO.Compression.ZipFile]::ExtractToDirectory`. Add installation directory to user PATH environment variable if not already present. Display version information.
    
    **User guidance**: Inform user to open new terminal for PATH changes to take effect.
    
    This replaces the PowerShell installer that cargo-dist would have generated.
    
    ### dist-workspace.toml(DELETE)
    
    Remove the cargo-dist configuration file as it is no longer needed. All release configuration is now handled by `.goreleaser.yml`.
    
    ### justfile(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    Update the justfile to remove cargo-dist references and clean up GoReleaser integration:
    
    **install-tools recipe** (lines 72-77): Remove `cargo-dist` from the cargo binstall command list in both Windows and Unix variants. Keep cargo-release, cargo-cyclonedx, cargo-auditable, and other tools.
    
    **Remove dist recipes** (lines 291-304): Delete the `dist`, `dist-check`, `dist-plan`, and `dist-generate-ci` recipes as they are cargo-dist specific and no longer needed.
    
    **Update ci-check recipe** (line 278): Remove `dist-plan` from the dependency list. The recipe should become: `ci-check: pre-commit-run fmt-check lint-rust lint-rust-min test-ci build-release audit coverage-check`.
    
    **Keep GoReleaser recipes** (lines 352-425): Retain all existing `goreleaser-*` recipes (goreleaser-check, goreleaser-build, goreleaser-snapshot, goreleaser-build-target, goreleaser-clean) as they are already well-configured with proper macOS SDK handling and will work with the new `.goreleaser.yml`.
    
    **Add release recipe comment**: Update or add a comment above the GoReleaser section explaining that GoReleaser is used for releases and referencing the `.goreleaser.yml` configuration file.
    
    ### Cargo.toml(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    Update the Cargo.toml to reflect the tooling change:
    
    **profile.dist section** (lines 33-36): Rename the `[profile.dist]` section to `[profile.release-optimized]` or similar, since the "dist" name is cargo-dist specific. Alternatively, keep it as-is since GoReleaser will use the `--release` flag which uses the `[profile.release]` profile, and the dist profile can remain for local testing. The thin LTO configuration should be documented as optional for GoReleaser builds.
    
    **Comment update**: Add a comment above the profile section explaining that this profile was previously used by cargo-dist and is now optional for GoReleaser, which uses the standard release profile. Alternatively, if keeping the profile, note that it can be used with GoReleaser by adding `--profile dist` to the build flags in `.goreleaser.yml`.
    
    Note: This change is optional and low-priority. The profile can remain as-is without affecting GoReleaser functionality.
    
    ### docs/src/installation.md(MODIFY)
    
    References: 
    
    - scripts/install.sh(NEW)
    - scripts/install.ps1(NEW)
    
    Update the installation documentation to reflect the new GoReleaser-based release process:
    
    **Add new section** after "Prerequisites" (around line 19): Add a "Binary Releases" section that explains users can download pre-built binaries from GitHub Releases once v0.1 is released. Include subsections for:
    
    - **Quick Install (Unix/Linux/macOS)**: Show the one-line curl installer: `curl -fsSL https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.sh | bash`
    - **Quick Install (Windows)**: Show the one-line PowerShell installer: `iwr -useb https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.ps1 | iex`
    - **Homebrew**: Show the Homebrew tap installation: `brew tap EvilBit-Labs/tap` followed by `brew install stringy`
    - **Manual Download**: Explain users can download archives directly from the GitHub Releases page and extract them manually
    
    **Update note at top** (line 3): Modify the note to mention that binary releases will be available starting with v0.1, and until then, installation from source is required.
    
    **Keep existing sections**: Retain all existing "From Source", "Development Build", "Platform-Specific Notes", "Docker", and "Troubleshooting" sections as they remain valid.
    
    This provides users with multiple installation options once releases are published via GoReleaser.
    
    ### docs/src/contributing.md(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    - .github/workflows/release.yml(MODIFY)
    
    Update the release process documentation to reflect GoReleaser:
    
    **Release Checklist section** (lines 415-422): Update the checklist to reflect the new GoReleaser-based process:
    
    1. Update version in `Cargo.toml`
    2. Update `CHANGELOG.md`
    3. Run full test suite (`just ci-check`)
    4. Update documentation
    5. Test release locally (`just goreleaser-snapshot`)
    6. Create and push release tag (`git tag v0.x.x && git push origin v0.x.x`)
    7. GitHub Actions will automatically build and publish the release via GoReleaser
    8. Verify release artifacts on GitHub Releases page
    9. Verify Homebrew tap was updated
    10. Publish to crates.io (when ready)
    
    **Add new subsection**: Add a "Testing Releases Locally" subsection that explains developers can test the release process using `just goreleaser-snapshot` which creates a snapshot release without publishing. Mention that `just goreleaser-check` validates the GoReleaser configuration.
    
    **Add new subsection**: Add a "Release Automation" subsection explaining that releases are automated via GoReleaser and GitHub Actions, triggered by pushing version tags. Mention that the workflow builds for all supported platforms, generates installers, creates SBOMs, adds attestations, and publishes to the Homebrew tap automatically.
    
    ### README.md(MODIFY)
    
    References: 
    
    - docs/src/installation.md(MODIFY)
    
    Update the README installation section to mention the upcoming binary releases:
    
    **Installation section** (lines 70-88): Add a brief note at the beginning of the section (after line 72) mentioning that pre-built binaries will be available via Homebrew, shell/PowerShell installers, and direct downloads from GitHub Releases starting with v0.1. Add a sentence directing users to the full installation documentation at `docs/src/installation.md` for all installation methods.
    
    **Keep existing content**: Retain the "From Source" and "Development Build" subsections as they remain the primary installation methods during development.
    
    This provides a preview of upcoming installation options without cluttering the README with detailed instructions that are better suited for the documentation.

    Developer Humor

    🚀 From cargo-dist to GoReleaser we go,\n> No more actionlint errors to show!\n> With Zig and attestations in tow,\n> Five platforms built in one flow,\n> Homebrew taps and SBOMs aglow,\n> StringyMcStringFace ready to grow! 🎉


    Execution Information

    Branch: main
    Commit: 92ca8db

    New Plan

    Observations

    The project uses cargo-dist for multi-platform releases across 5 targets, with shell/PowerShell/Homebrew installers, SBOM via cargo-cyclonedx, attestations, and a Homebrew tap. The auto-generated release workflow is complex (300+ lines) and triggers actionlint warnings. justfile includes cargo-dist recipes and partial GoReleaser setup with macOS SDK handling. Cargo.toml defines a dist profile with thin LTO. Security and Copilot workflows install cargo-dist. Documentation references cargo-dist processes.

    Approach

    Migrate to GoReleaser by creating .goreleaser.yml to replicate all features: Rust builds with cargo-zigbuild and auditable, archives/checksums, SBOM, Homebrew cask publishing, and release assets including custom installers. Replace the release workflow with a simple GoReleaser action plus attestations. Remove cargo-dist from justfile, workflows, and config files. Update documentation for new process. Test via snapshot releases.

    Reasoning

    I listed repository files to identify cargo-dist configs and workflows. I read the release.yml to confirm its complexity and generation. I examined dist-workspace.toml for current settings like targets and installers. I reviewed Cargo.toml for build profiles. I checked justfile for existing recipes. I inspected security.yml and copilot-setup-steps.yml for cargo-dist installations. I browsed docs for release references.

    Proposed File Changes

    📄 .goreleaser.yml (NEW) 🔗

    References

    Create comprehensive GoReleaser configuration replicating cargo-dist features.

    Builds

    • Use builder: rust with goosarch for all 5 targets.
    • Set binary: stringy and main: ./src/main.rs.
    • Enable hooks to install cargo-zigbuild, cargo-auditable, cargo-cyclonedx.
    • Use command: auditable with extra_args: ['zigbuild', '--release'] for cross-compilation and auditing.
    • Set ldflags to include thin LTO via -C lto=thin matching profile.dist.
    • For macOS targets, reference env vars from justfile (SDKROOT, etc.) in env section.

    Archives

    • Unix: format: tarxz, Windows: format: zip.
    • Template: {{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}.

    Checksum

    • name_template: 'checksums.txt'.

    Sbom

    • Use generator: cyclonedx with command: cargo cyclonedx args ['-o', '{{ .ArtifactName }}.cdx.json'].

    Brew

    • tap: github.com/EvilBit-Labs/homebrew-tap on main branch.
    • token: HOMEBREW_TAP_TOKEN.
    • folder: Casks, name: stringy.
    • Set homepage, description, license from Cargo.toml.
    • commit_author.name: 'Stringy Bot', commit_author.email: 'bot@evilbitlabs.io'.
    • install: |- bin.install "stringy".
    • caveats: 'Successfully installed Stringy! Ready to start looking at your binaries!'.

    Release

    • disable: false, include extra_files: [scripts/install.sh, scripts/install.ps1].
    • github_token: {{ .Env.GITHUB_TOKEN }}.

    UniversalBinaries (macOS)

    • Enable for aarch64-apple-darwin if needed, but use separate builds for simplicity.

    Reference Cargo.toml for metadata, dist-workspace.toml for targets/installers.

    📄 .github/workflows/release.yml (MODIFY) 🔗

    References

    Replace entire cargo-dist generated workflow with simple GoReleaser setup.

    • Name: 'Release'.
    • Permissions: contents: write, id-token: write, attestations: write.
    • On: push: tags: ['v[0-9]+.[0-9]+.[0-9]+*'], pull_request for testing.
    • Job 'release': runs-on ubuntu-latest.
      • Checkout with fetch-depth: 0.
      • Setup Rust: dtolnay/rust-toolchain@v1 with 1.90.
      • Install Zig: kennethreitz/setup-zig@v1 version 0.12.1.
      • Cargo install: cargo-zigbuild, cargo-auditable, cargo-cyclonedx with --locked.
      • Rustup target add for all 5 triples.
      • GoReleaser: goreleaser/goreleaser-action@v5 with distribution: goreleaser args release --clean.
      • Env: GITHUB_TOKEN, HOMEBREW_TAP_TOKEN.
    • If tag push: After GoReleaser, run actions/attest-build-provenance@v1 with subject-paths: dist/checksums.txt.

    This simplifies to ~50 lines, eliminates actionlint issues, and handles all builds/publishing in one job.

    Reference new .goreleaser.yml for config integration.

    📁 scripts (NEW) 🔗

    Create scripts directory for installer files to be included in releases.

    📄 scripts/install.sh (NEW) 🔗

    References

    Create Unix shell installer script.

    • Shebang: #!/usr/bin/env bash.
    • Set -euo pipefail.
    • Vars: OWNER='EvilBit-Labs', REPO='StringyMcStringFace', BINARY='stringy', INSTALL_DIR='/usr/local/bin'.
    • Version: Use $VERSION or fetch latest tag via GitHub API (curl -s https://api.github.com/repos/$OWNER/$REPO/releases/latest | jq -r .tag_name).
    • Detect OS/Arch: OS=$(uname -s | tr '[:upper:]' '[:lower:]'), ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/' ).
    • Temp dir: mktemp -d with trap cleanup.
    • Download: Asset name ${BINARY}_${VERSION}_${OS}_${ARCH}.tar.xz, URL from GitHub releases, curl -L -o.
    • Download checksums.txt, verify sha256sum -c --ignore-missing.
    • Extract: tar -xJf, sudo install -m 755 stringy $INSTALL_DIR/.
    • Success msg: 'Successfully installed Stringy! Ready to start looking at your binaries!'.

    Matches cargo-dist shell installer behavior, uses GoReleaser naming.

    📄 scripts/install.ps1 (NEW) 🔗

    References

    Create Windows PowerShell installer script.

    • Param: [CmdletBinding()] param( [string]$Version = '' ).
    • $ErrorActionPreference = 'Stop'.
    • Vars: $Owner = 'EvilBit-Labs', $Repo = 'StringyMcStringFace', $Binary = 'stringy', $InstallDir = "$env:ProgramFiles\Stringy".
    • Version: If empty, $latest = Invoke-RestMethod "https://api.github.com/repos/$Owner/$Repo/releases/latest"; $Version = $latest.tag_name.
    • Arch: $Arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { 'amd64' } else { 'arm64' }; OS='windows'.
    • Temp: $tempDir = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid().
    • Asset: ${Binary}_${Version}_windows_${Arch}.zip.
    • Download: Invoke-WebRequest -Uri "https://github.com/$Owner/$Repo/releases/download/$Version/$asset" -OutFile "$tempDir\$asset".
    • Download checksums.txt, compute hash Get-FileHash, verify against file.
    • Extract: Expand-Archive -Path "$tempDir\$asset" -DestinationPath $InstallDir.
    • Add to PATH: [Environment]::SetEnvironmentVariable('Path', "$env:Path;$InstallDir", 'User').
    • Msg: Success message, note to restart shell.

    Replicates cargo-dist PowerShell installer with GoReleaser compatibility.

    📄 dist-workspace.toml (DELETE) 🔗

    Remove cargo-dist workspace configuration as it's replaced by .goreleaser.yml.

    📄 justfile (MODIFY) 🔗

    References

    Update justfile to remove cargo-dist and enhance GoReleaser.

    • In install-tools: Remove cargo-dist from binstall list (lines ~73,77).
    • Remove dist recipes: dist, dist-check, dist-plan, dist-generate-ci (lines 291-304).
    • Update ci-check: Remove dist-plan dependency (line 278), now pre-commit-run fmt-check lint-rust lint-rust-min test-ci build-release audit coverage-check.
    • Keep all goreleaser-* recipes (lines 355-425) as they align with new config; add comment: '# GoReleaser handles releases via .goreleaser.yml and GitHub Actions'.
    • Optional: Add release: goreleaser-snapshot alias for local testing.

    Ensures clean transition, retains macOS SDK handling in GoReleaser recipes.

    Reference .goreleaser.yml for integration.

    📄 Cargo.toml (MODIFY) 🔗

    References

    Minor update to Cargo.toml for profile clarity.

    • Rename [profile.dist] to [profile.release] or add comment: '# Previously for cargo-dist; GoReleaser uses --release profile with optional thin LTO via ldflags'.
    • Keep inherits = 'release', lto = 'thin'.
    • No other changes needed as GoReleaser can reference this via build flags.

    Reference .goreleaser.yml where ldflags incorporate thin LTO.

    📄 .github/workflows/security.yml (MODIFY) 🔗

    Remove cargo-dist from security workflow.

    • In 'Install cargo tools' step (line ~34): Remove cargo-dist from taiki-e/install-action tool list.
    • Remove 'Run cargo dist check' step (lines 41-43).
    • Keep cargo-outdated, cargo-deny.

    Aligns with migration; security checks now focus on other tools.

    📄 .github/workflows/copilot-setup-steps.yml (MODIFY) 🔗

    References

    Remove cargo-dist from Copilot setup.

    • In 'Install cargo tools' step (line ~49): Remove cargo-dist from tool list.
    • In 'just install-tools' run (line 58): This will now skip cargo-dist due to justfile update.
    • Update summary echo (line 72): Remove cargo-dist version check.

    Ensures setup doesn't install obsolete tool.

    📄 docs/src/installation.md (MODIFY) 🔗

    References

    Update installation docs for GoReleaser releases.

    • Add section 'Binary Releases' after 'Prerequisites':
      • 'Quick Install (Unix/macOS)': curl -sSfL https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.sh | sh.
      • 'Quick Install (Windows)': irm https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.ps1 | iex.
      • 'Homebrew': brew tap EvilBit-Labs/homebrew-tap && brew install stringy.
      • 'Manual': Download archives from GitHub Releases.
    • Update intro note: 'Binary releases available from v0.1 via GoReleaser; source install for development'.
    • Retain 'From Source', 'Development Build', etc. sections.

    Reference installer scripts for commands.

    📄 docs/src/contributing.md (MODIFY) 🔗

    References

    Update contributing docs for release process.

    • In 'Release Checklist':
      1. Update Cargo.toml version.
      2. Update CHANGELOG.md.
      3. Run just ci-check.
      4. Update docs.
      5. Test: just goreleaser-snapshot.
      6. Tag/push: git tag vX.Y.Z && git push --tags.
      7. GitHub Actions auto-publishes via GoReleaser.
      8. Verify releases, Homebrew, artifacts.
    • Add 'Testing Releases': Use just goreleaser-snapshot for local dry-run; just goreleaser-check validates config.
    • Add 'Automation': Tags trigger workflow building 5 platforms, installers, SBOM, attestations, Homebrew push.

    Reference .goreleaser.yml and release.yml.

    📄 README.md (MODIFY) 🔗

    References

    Update README installation section.

    • After 'Installation' header: Add 'Pre-built binaries available from v0.1 via GitHub Releases, Homebrew, and one-liners. See docs/installation.md for details.'
    • Retain 'From Source' and 'Development Build' as primary methods.
    • No major changes; keep concise.

    Import In IDE

    VSCode Icon Cursor Icon Windsurf Icon

    🤖 Prompt for AI Agents
    I have created the following plan after thorough exploration and analysis of the codebase. Follow the below plan verbatim. Trust the files and references. Do not re-verify what's written in the plan. Explore only when absolutely necessary. First implement all the proposed file changes and then I'll review all the changes together at the end.
    
    ### Observations
    
    The project uses cargo-dist for multi-platform releases across 5 targets, with shell/PowerShell/Homebrew installers, SBOM via cargo-cyclonedx, attestations, and a Homebrew tap. The auto-generated release workflow is complex (300+ lines) and triggers actionlint warnings. justfile includes cargo-dist recipes and partial GoReleaser setup with macOS SDK handling. Cargo.toml defines a dist profile with thin LTO. Security and Copilot workflows install cargo-dist. Documentation references cargo-dist processes.
    
    ### Approach
    
    Migrate to GoReleaser by creating `.goreleaser.yml` to replicate all features: Rust builds with cargo-zigbuild and auditable, archives/checksums, SBOM, Homebrew cask publishing, and release assets including custom installers. Replace the release workflow with a simple GoReleaser action plus attestations. Remove cargo-dist from justfile, workflows, and config files. Update documentation for new process. Test via snapshot releases.
    
    ### Reasoning
    
    I listed repository files to identify cargo-dist configs and workflows. I read the release.yml to confirm its complexity and generation. I examined dist-workspace.toml for current settings like targets and installers. I reviewed Cargo.toml for build profiles. I checked justfile for existing recipes. I inspected security.yml and copilot-setup-steps.yml for cargo-dist installations. I browsed docs for release references.
    
    ## Proposed File Changes
    
    ### .goreleaser.yml(NEW)
    
    References: 
    
    - Cargo.toml(MODIFY)
    - dist-workspace.toml(DELETE)
    - justfile(MODIFY)
    
    # Create comprehensive GoReleaser configuration replicating cargo-dist features.
    
    ## Builds
    - Use `builder: rust` with `goosarch` for all 5 targets.
    - Set `binary: stringy` and `main: ./src/main.rs`.
    - Enable `hooks` to install cargo-zigbuild, cargo-auditable, cargo-cyclonedx.
    - Use `command: auditable` with `extra_args: ['zigbuild', '--release']` for cross-compilation and auditing.
    - Set `ldflags` to include thin LTO via `-C lto=thin` matching `profile.dist`.
    - For macOS targets, reference env vars from justfile (SDKROOT, etc.) in `env` section.
    
    ## Archives
    - Unix: `format: tarxz`, Windows: `format: zip`.
    - Template: `{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}`.
    
    ## Checksum
    - `name_template: 'checksums.txt'`.
    
    ## Sbom
    - Use `generator: cyclonedx` with `command: cargo cyclonedx` args `['-o', '{{ .ArtifactName }}.cdx.json']`.
    
    ## Brew
    - `tap: github.com/EvilBit-Labs/homebrew-tap` on `main` branch.
    - `token: HOMEBREW_TAP_TOKEN`.
    - `folder: Casks`, `name: stringy`.
    - Set `homepage`, `description`, `license` from Cargo.toml.
    - `commit_author.name: 'Stringy Bot'`, `commit_author.email: 'bot@evilbitlabs.io'`.
    - `install: |-
      bin.install "stringy"`.
    - `caveats: 'Successfully installed Stringy! Ready to start looking at your binaries!'`.
    
    ## Release
    - `disable: false`, include `extra_files: [scripts/install.sh, scripts/install.ps1]`.
    - `github_token: {{ .Env.GITHUB_TOKEN }}`.
    
    ## UniversalBinaries (macOS)
    - Enable for aarch64-apple-darwin if needed, but use separate builds for simplicity.
    
    Reference Cargo.toml for metadata, dist-workspace.toml for targets/installers.
    
    ### .github/workflows/release.yml(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Replace entire cargo-dist generated workflow with simple GoReleaser setup.
    
    - Name: 'Release'.
    - Permissions: `contents: write`, `id-token: write`, `attestations: write`.
    - On: `push: tags: ['v[0-9]+.[0-9]+.[0-9]+*']`, `pull_request` for testing.
    - Job 'release': runs-on `ubuntu-latest`.
      - Checkout with `fetch-depth: 0`.
      - Setup Rust: `dtolnay/rust-toolchain@v1` with `1.90`.
      - Install Zig: `kennethreitz/setup-zig@v1` version `0.12.1`.
      - Cargo install: `cargo-zigbuild`, `cargo-auditable`, `cargo-cyclonedx` with `--locked`.
      - Rustup target add for all 5 triples.
      - GoReleaser: `goreleaser/goreleaser-action@v5` with `distribution: goreleaser` args `release --clean`.
      - Env: `GITHUB_TOKEN`, `HOMEBREW_TAP_TOKEN`.
    - If tag push: After GoReleaser, run `actions/attest-build-provenance@v1` with `subject-paths: dist/checksums.txt`.
    
    This simplifies to ~50 lines, eliminates actionlint issues, and handles all builds/publishing in one job.
    
    Reference new .goreleaser.yml for config integration.
    
    ### scripts(NEW)
    
    # Create scripts directory for installer files to be included in releases.
    
    ### scripts/install.sh(NEW)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Create Unix shell installer script.
    
    - Shebang: `#!/usr/bin/env bash`.
    - Set `-euo pipefail`.
    - Vars: `OWNER='EvilBit-Labs'`, `REPO='StringyMcStringFace'`, `BINARY='stringy'`, `INSTALL_DIR='/usr/local/bin'`.
    - Version: Use `$VERSION` or fetch latest tag via GitHub API (`curl -s https://api.github.com/repos/$OWNER/$REPO/releases/latest | jq -r .tag_name`).
    - Detect OS/Arch: `OS=$(uname -s | tr '[:upper:]' '[:lower:]')`, `ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/' )`.
    - Temp dir: `mktemp -d` with trap cleanup.
    - Download: Asset name `${BINARY}_${VERSION}_${OS}_${ARCH}.tar.xz`, URL from GitHub releases, `curl -L -o`.
    - Download checksums.txt, verify `sha256sum -c --ignore-missing`.
    - Extract: `tar -xJf`, `sudo install -m 755 stringy $INSTALL_DIR/`.
    - Success msg: 'Successfully installed Stringy! Ready to start looking at your binaries!'.
    
    Matches cargo-dist shell installer behavior, uses GoReleaser naming.
    
    ### scripts/install.ps1(NEW)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Create Windows PowerShell installer script.
    
    - Param: `[CmdletBinding()] param( [string]$Version = '' )`.
    - `$ErrorActionPreference = 'Stop'`.
    - Vars: `$Owner = 'EvilBit-Labs'`, `$Repo = 'StringyMcStringFace'`, `$Binary = 'stringy'`, `$InstallDir = "$env:ProgramFiles\Stringy"`.
    - Version: If empty, `$latest = Invoke-RestMethod "https://api.github.com/repos/$Owner/$Repo/releases/latest"; $Version = $latest.tag_name`.
    - Arch: `$Arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { 'amd64' } else { 'arm64' }`; OS='windows'.
    - Temp: `$tempDir = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid()`.
    - Asset: `${Binary}_${Version}_windows_${Arch}.zip`.
    - Download: `Invoke-WebRequest -Uri "https://github.com/$Owner/$Repo/releases/download/$Version/$asset" -OutFile "$tempDir\$asset"`.
    - Download checksums.txt, compute hash `Get-FileHash`, verify against file.
    - Extract: `Expand-Archive -Path "$tempDir\$asset" -DestinationPath $InstallDir`.
    - Add to PATH: `[Environment]::SetEnvironmentVariable('Path', "$env:Path;$InstallDir", 'User')`.
    - Msg: Success message, note to restart shell.
    
    Replicates cargo-dist PowerShell installer with GoReleaser compatibility.
    
    ### dist-workspace.toml(DELETE)
    
    # Remove cargo-dist workspace configuration as it's replaced by .goreleaser.yml.
    
    ### justfile(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Update justfile to remove cargo-dist and enhance GoReleaser.
    
    - In `install-tools`: Remove `cargo-dist` from binstall list (lines ~73,77).
    - Remove dist recipes: `dist`, `dist-check`, `dist-plan`, `dist-generate-ci` (lines 291-304).
    - Update `ci-check`: Remove `dist-plan` dependency (line 278), now `pre-commit-run fmt-check lint-rust lint-rust-min test-ci build-release audit coverage-check`.
    - Keep all `goreleaser-*` recipes (lines 355-425) as they align with new config; add comment: '# GoReleaser handles releases via .goreleaser.yml and GitHub Actions'.
    - Optional: Add `release: goreleaser-snapshot` alias for local testing.
    
    Ensures clean transition, retains macOS SDK handling in GoReleaser recipes.
    
    Reference .goreleaser.yml for integration.
    
    ### Cargo.toml(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    
    # Minor update to Cargo.toml for profile clarity.
    
    - Rename `[profile.dist]` to `[profile.release]` or add comment: '# Previously for cargo-dist; GoReleaser uses --release profile with optional thin LTO via ldflags'.
    - Keep `inherits = 'release'`, `lto = 'thin'`.
    - No other changes needed as GoReleaser can reference this via build flags.
    
    Reference .goreleaser.yml where ldflags incorporate thin LTO.
    
    ### .github/workflows/security.yml(MODIFY)
    
    # Remove cargo-dist from security workflow.
    
    - In 'Install cargo tools' step (line ~34): Remove `cargo-dist` from `taiki-e/install-action` tool list.
    - Remove 'Run cargo dist check' step (lines 41-43).
    - Keep cargo-outdated, cargo-deny.
    
    Aligns with migration; security checks now focus on other tools.
    
    ### .github/workflows/copilot-setup-steps.yml(MODIFY)
    
    References: 
    
    - justfile(MODIFY)
    
    # Remove cargo-dist from Copilot setup.
    
    - In 'Install cargo tools' step (line ~49): Remove `cargo-dist` from tool list.
    - In 'just install-tools' run (line 58): This will now skip cargo-dist due to justfile update.
    - Update summary echo (line 72): Remove cargo-dist version check.
    
    Ensures setup doesn't install obsolete tool.
    
    ### docs/src/installation.md(MODIFY)
    
    References: 
    
    - scripts/install.sh(NEW)
    - scripts/install.ps1(NEW)
    
    # Update installation docs for GoReleaser releases.
    
    - Add section 'Binary Releases' after 'Prerequisites':
      - 'Quick Install (Unix/macOS)': `curl -sSfL https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.sh | sh`.
      - 'Quick Install (Windows)': `irm https://github.com/EvilBit-Labs/StringyMcStringFace/releases/latest/download/install.ps1 | iex`.
      - 'Homebrew': `brew tap EvilBit-Labs/homebrew-tap && brew install stringy`.
      - 'Manual': Download archives from GitHub Releases.
    - Update intro note: 'Binary releases available from v0.1 via GoReleaser; source install for development'.
    - Retain 'From Source', 'Development Build', etc. sections.
    
    Reference installer scripts for commands.
    
    ### docs/src/contributing.md(MODIFY)
    
    References: 
    
    - .goreleaser.yml(NEW)
    - .github/workflows/release.yml(MODIFY)
    - justfile(MODIFY)
    
    # Update contributing docs for release process.
    
    - In 'Release Checklist':
      1. Update Cargo.toml version.
      2. Update CHANGELOG.md.
      3. Run `just ci-check`.
      4. Update docs.
      5. Test: `just goreleaser-snapshot`.
      6. Tag/push: `git tag vX.Y.Z && git push --tags`.
      7. GitHub Actions auto-publishes via GoReleaser.
      8. Verify releases, Homebrew, artifacts.
    - Add 'Testing Releases': Use `just goreleaser-snapshot` for local dry-run; `just goreleaser-check` validates config.
    - Add 'Automation': Tags trigger workflow building 5 platforms, installers, SBOM, attestations, Homebrew push.
    
    Reference .goreleaser.yml and release.yml.
    
    ### README.md(MODIFY)
    
    References: 
    
    - docs/src/installation.md(MODIFY)
    
    # Update README installation section.
    
    - After 'Installation' header: Add 'Pre-built binaries available from v0.1 via GitHub Releases, Homebrew, and one-liners. See docs/installation.md for details.'
    - Retain 'From Source' and 'Development Build' as primary methods.
    - No major changes; keep concise.

    Developer Humor

    🎉 Swapping cargo-dist for GoReleaser's grace,\n> No more lint warnings in our CI space!\n> Builds fly fast with Zig's embrace,\n> Installers ready, Homebrew in place.\n> Stringy releases, now with style and pace! 🚀


    Execution Information

    Branch: main
    Commit: 37cfc7c

  9. unclesp1d3r commented on Jul 5, 2026

    @unclesp1d3r
    MemberAuthor

    Decision: not migrating to GoReleaser — keeping cargo-dist

    After grounding this against the actual repo and verifying GoReleaser's Rust support, this is a won't-do. Summary below.

    The migration doesn't survive our target matrix

    Our dist-workspace.toml builds 6 targets, including two MSVC targets — x86_64-pc-windows-msvc and aarch64-pc-windows-msvc (Windows ARM64) — plus x86_64-unknown-linux-musl, with msvc-crt-static = true.

    GoReleaser's Rust builder cross-compiles via cargo-zigbuild, which supports only Linux and macOS targets — not Windows MSVC (per cargo-zigbuild's own README). GoReleaser's Rust docs never mention MSVC, Windows-ARM64, or cargo-xwin. The natural workaround (build MSVC natively, then merge) is GoReleaser Pro (paid).

    The half-finished .goreleaser.yaml already in the repo confirms this: it silently dropped Windows-ARM64 + musl, switched Windows to the GNU ABI, and notes zigbuild can't do macOS (so macOS needs a mac runner anyway). It reaches ~40% parity only by reducing what we ship. Going to GoReleaser at true parity has no open-source path today.

    The strongest reason to leave cargo-dist turned out false

    cargo-dist / dist is actively maintained — v0.32.0 shipped 2026-05-22 with real changelog work; axo.dev is live. No abandonment signal.

    The actionlint pain is already fixed

    The main concrete complaint here was actionlint noise from the generated release.yml. That's already resolved:

    • actionlint .github/workflows/*.yml → exit 0, zero warnings.
    • .github/actionlint.yml suppresses release.yml via paths: ignore (added 2026-06-20, 6aa4147).
    • .pre-commit-config.yaml also excludes release.yml from the actionlint hook.

    The other cited pains (300+ line generated workflow, cross-workflow tool sync) are inherent to any generated-workflow release tool and don't justify moving to a less-mature one.

    Reversal trigger

    Revisit if any of these change:

    • GoReleaser's Rust builder gains documented cargo-xwin/MSVC cross-compile in OSS, or
    • cargo-dist shows real abandonment (no releases ~12+ months, security backlog), or
    • we decide, as a product call, to drop the MSVC/Windows-ARM64 targets and ship GNU-ABI Windows.

    Closing as not planned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

MVPMinimum viable product featuresenhancementNew feature or requestgithub_actionsPull requests that update GitHub Actions codepriority:highHigh priority taskstatus:backlogTask in backlog

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions