{"id":50998774,"url":"https://github.com/thedavidweng/cli-workflow-template","last_synced_at":"2026-06-20T12:03:08.081Z","repository":{"id":364683529,"uuid":"1268837237","full_name":"thedavidweng/cli-workflow-template","owner":"thedavidweng","description":"Reusable GitHub Actions workflows for Go CLI projects. CI, release, CodeQL.","archived":false,"fork":false,"pushed_at":"2026-06-14T02:19:22.000Z","size":7,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-14T04:12:12.748Z","etag":null,"topics":["ci-cd","cli","devops","github-actions","go","goreleaser","reusable-workflows","template"],"latest_commit_sha":null,"homepage":"https://thedavidweng.github.io/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thedavidweng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-14T01:57:41.000Z","updated_at":"2026-06-14T02:19:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thedavidweng/cli-workflow-template","commit_stats":null,"previous_names":["thedavidweng/cli-workflow-template"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/thedavidweng/cli-workflow-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedavidweng%2Fcli-workflow-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedavidweng%2Fcli-workflow-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedavidweng%2Fcli-workflow-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedavidweng%2Fcli-workflow-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thedavidweng","download_url":"https://codeload.github.com/thedavidweng/cli-workflow-template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thedavidweng%2Fcli-workflow-template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34568743,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ci-cd","cli","devops","github-actions","go","goreleaser","reusable-workflows","template"],"created_at":"2026-06-20T12:03:07.309Z","updated_at":"2026-06-20T12:03:08.076Z","avatar_url":"https://github.com/thedavidweng.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# cli-workflow-template\n\nReusable GitHub Actions workflows for app and CLI projects. One place to define common CI, release, and security scanning policy while each downstream project keeps its product-specific commands and metadata.\n\n## Architecture\n\n```\ncli-workflow-template/              \u003c- you are here\n├── .github/workflows/\n│   ├── go-ci.yml                   Go test + lint + snapshot\n│   ├── go-release.yml              GoReleaser + cosign + SBOM\n│   ├── go-codeql.yml               Go CodeQL security scanning\n│   ├── tauri-ci.yml                Tauri frontend/Rust/build checks\n│   ├── tauri-codeql.yml            Tauri Rust + JS/TS CodeQL scanning\n│   └── template-check.yml          validates this template repo\n│\ncanvas-cli/\n├── .github/workflows/\n│   ├── ci.yml                      uses: .../go-ci.yml@main\n│   ├── release.yml                 uses: .../go-release.yml@main\n│   └── codeql.yml                  uses: .../go-codeql.yml@main\n│\nOpenKara / OpenLoop/\n├── .github/workflows/\n│   ├── ci.yml                      uses: .../tauri-ci.yml@main\n│   └── codeql.yml                  uses: .../tauri-codeql.yml@main\n```\n\nDownstream projects own triggers, release timing, secrets, and project metadata. This repo owns shared execution policy: consistent setup, security checks, lint/test/build ordering, and reusable release primitives where the project family is standardized enough.\n\n## Workflows\n\n### go-ci.yml\n\nTest, lint, and build Go projects on every push and PR. Builds a GoReleaser snapshot on `main` after tests pass.\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `os-matrix` | `[\"ubuntu-latest\", \"macos-latest\", \"windows-latest\"]` | OS to test on |\n| `enable-golangci-lint` | `true` | Run golangci-lint |\n| `golangci-lint-version` | `latest` | golangci-lint version |\n| `enable-gofmt` | `true` | Explicit gofmt check |\n| `enable-race` | `true` | Race detector |\n| `enable-snapshot` | `true` | GoReleaser snapshot build |\n\n**Concurrency:** cancels in-progress runs on the same ref.\n\n```yaml\njobs:\n  ci:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/go-ci.yml@main\n```\n\n### go-release.yml\n\nRelease Go projects via GoReleaser on `v*` tag push. Includes cosign keyless signing, SBOM generation, pre-release tests, and Homebrew tap token verification.\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `enable-syft` | `true` | Generate SBOM with syft |\n| `enable-pre-release-test` | `true` | Run tests before GoReleaser |\n| `enable-homebrew-verify` | `true` | Verify HOMEBREW_TAP_GITHUB_TOKEN |\n\n**Permissions:** caller workflows must grant `contents: write` and `id-token: write`. GitHub does not let a called reusable workflow elevate the caller's token.\n\n**Secrets:** `HOMEBREW_TAP_GITHUB_TOKEN`, `SCOOP_BUCKET_GITHUB_TOKEN` (both optional, inherited via `secrets: inherit`).\n\n**Release policy lives here:** pre-release tests, cosign installation, syft installation, Homebrew token verification, and the GoReleaser invocation are centralized in this workflow. Downstream repos own when a release is triggered; this template owns how the release runs.\n\n**GoReleaser config boundary:** downstream repos currently keep `.goreleaser.yaml` only for project metadata that has not been standardized yet, such as binary name, ldflags package, package names, and Homebrew formula or cask details. The intended end state is a template-owned GoReleaser config generated from a small metadata contract, so release behavior can change in one place.\n\n```yaml\npermissions:\n  contents: write\n  id-token: write\n\njobs:\n  release:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/go-release.yml@main\n    secrets: inherit\n```\n\n### go-codeql.yml\n\nCodeQL security scanning for Go projects with `security-extended` queries.\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `languages` | `go` | Language to scan |\n\n```yaml\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: \"0 0 * * 1\"\n\npermissions:\n  security-events: write\n  actions: read\n  contents: read\n\njobs:\n  analyze:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/go-codeql.yml@main\n```\n\n### tauri-ci.yml\n\nShared CI skeleton for Tauri 2 desktop apps. It centralizes the repeatable parts: workflow linting, pnpm/Node setup, Rust setup, dependency audit hooks, Cargo dependency policy, Linux Tauri packages, Rust cache wiring, and optional Tauri build validation.\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `node-version` | `24` | Node.js version |\n| `pnpm-version` | `10.33.2` | pnpm version |\n| `rust-toolchain` | `stable` | Rust toolchain passed to `dtolnay/rust-toolchain` |\n| `rust-os-matrix` | `[\"ubuntu-22.04\", \"macos-14\"]` | OSes for Rust checks |\n| `tauri-build-os-matrix` | `[\"ubuntu-22.04\", \"macos-14\", \"windows-latest\"]` | OSes for optional Tauri build checks |\n| `cargo-manifest-path` | `src-tauri/Cargo.toml` | Cargo manifest path |\n| `cargo-workspace` | `./src-tauri -\u003e target` | Rust cache workspace mapping |\n| `linux-apt-packages` | Tauri WebKit/GTK build packages | Packages installed on Linux jobs |\n| `project-prepare-command` | empty | Project-owned setup for models, sidecars, generated native assets, or runtime prep |\n| `frontend-command` | `pnpm ci:frontend` | Project-owned frontend CI command |\n| `rust-command` | `pnpm ci:rust` | Project-owned Rust CI command |\n| `tauri-build-command` | `pnpm ci:tauri-build` | Project-owned Tauri build validation command |\n| `enable-workflow-lint` | `true` | Run actionlint and zizmor |\n| `enable-frontend` | `true` | Run the frontend job |\n| `enable-cargo-deny` | `true` | Run cargo-deny |\n| `enable-rust` | `true` | Run Rust checks |\n| `enable-tauri-build` | `false` | Run cross-platform Tauri build validation |\n\n**Tauri contract boundary:** this workflow owns the shared environment and check ordering. Each app owns its scripts. If a project needs ONNX Runtime, model downloads, sidecars, generated bindings, app-specific secrets, or platform-specific release packaging, put that logic behind the project commands rather than adding broad fallback behavior here.\n\n**Permissions:** caller workflows must grant `contents: read`. If `enable-workflow-lint` stays enabled, also grant `security-events: write` so zizmor can upload SARIF results.\n\n**Build dependency:** `enable-tauri-build: true` expects `enable-frontend`, `enable-cargo-deny`, and `enable-rust` to remain enabled. The final `validate` job fails when an enabled check is skipped or unsuccessful, so misconfigured callers fail visibly.\n\n```yaml\njobs:\n  ci:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/tauri-ci.yml@main\n    with:\n      project-prepare-command: pnpm prepare:sidecars\n      frontend-command: pnpm ci:frontend\n      rust-command: pnpm ci:rust\n      tauri-build-command: pnpm ci:tauri-build\n      enable-tauri-build: true\n```\n\n### tauri-codeql.yml\n\nCodeQL security scanning for Tauri projects. The default matrix scans Rust with autobuild and JavaScript/TypeScript without autobuild.\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `matrix` | Rust + JS/TS | JSON array of CodeQL `{ \"language\", \"build-mode\" }` objects |\n\n```yaml\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: \"0 0 * * 1\"\n\npermissions:\n  security-events: write\n  actions: read\n  contents: read\n\njobs:\n  analyze:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/tauri-codeql.yml@main\n```\n\n## Projects\n\n| Project | Family | Shared workflows | Notes |\n|---------|--------|------------------|-------|\n| [canvas-cli](https://github.com/thedavidweng/canvas-cli) | Go CLI | `go-ci`, `go-release`, `go-codeql` | Binary: `canvas` |\n| [zenodo-cli](https://github.com/thedavidweng/zenodo-cli) | Go CLI | `go-ci`, `go-release`, `go-codeql` | Binary: `zenodo` |\n| [monarchmoney-cli](https://github.com/thedavidweng/monarchmoney-cli) | Go CLI | `go-ci`, `go-release`, `go-codeql` | Binary: `monarch` |\n| [flickr-cli](https://github.com/thedavidweng/flickr-cli) | Go CLI | `go-ci`, `go-release`, `go-codeql` | Binary: `flickr` |\n| [money](https://github.com/thedavidweng/money) | Go app | `go-codeql` | Website and app CI stay separate |\n| [OpenKara](https://github.com/thedavidweng/OpenKara) | Tauri 2 app | planned: `tauri-ci`, `tauri-codeql` | Release, model/runtime, WinGet, and Flatpak stay project-owned |\n| [OpenLoop](https://github.com/thedavidweng/OpenLoop) | Tauri 2 app | planned: `tauri-ci`, `tauri-codeql` | Release and sidecar packaging stay project-owned |\n\n## Adding a Go Project\n\n1. Add caller workflows for CI, release, and CodeQL.\n2. Keep project metadata in the downstream repo until the GoReleaser metadata contract is standardized.\n3. Add the project to the table above.\n\n## Adding a Tauri Project\n\n1. Add project scripts that match the Tauri contract:\n\n```json\n{\n  \"scripts\": {\n    \"ci:frontend\": \"pnpm audit --audit-level=high \u0026\u0026 pnpm format:check \u0026\u0026 pnpm lint \u0026\u0026 pnpm test:coverage \u0026\u0026 pnpm build\",\n    \"ci:rust\": \"cargo fmt --manifest-path src-tauri/Cargo.toml --check \u0026\u0026 cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings \u0026\u0026 cargo test -q --manifest-path src-tauri/Cargo.toml\",\n    \"ci:tauri-build\": \"pnpm tauri build --debug --no-bundle --ci\"\n  }\n}\n```\n\n2. Add a caller workflow:\n\n```yaml\nname: CI\non:\n  push:\n    branches: [main]\n  pull_request:\n\npermissions:\n  contents: read\n  security-events: write\n\njobs:\n  ci:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/tauri-ci.yml@main\n    with:\n      enable-tauri-build: true\n```\n\n3. Add CodeQL:\n\n```yaml\nname: CodeQL\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: \"0 0 * * 1\"\n\npermissions:\n  security-events: write\n  actions: read\n  contents: read\n\njobs:\n  analyze:\n    uses: thedavidweng/cli-workflow-template/.github/workflows/tauri-codeql.yml@main\n```\n\n4. Keep release workflows project-owned until a real shared Tauri release contract emerges.\n\n## Shared Conventions\n\nAll projects using this template follow:\n\n- **Caller ownership:** downstream repos own triggers, branch filters, secrets, and project metadata.\n- **Template ownership:** this repo owns reusable setup, check ordering, security scanner choices, and standardized release primitives.\n- **Go version:** from `go.mod` for Go workflows.\n- **Tauri JavaScript runtime:** Node 24 and pnpm by default.\n- **Tauri Rust manifest:** `src-tauri/Cargo.toml` by default.\n- **Security scanning:** CodeQL uses `security-extended`; workflow linting uses actionlint and zizmor where enabled.\n- **No hidden fallback behavior:** if a project needs generated assets, sidecars, runtimes, or release-specific secrets, expose that as a project command or caller workflow setting.\n\n## Updating\n\nTo update shared CI behavior for all projects, edit the workflow file here. Changes take effect on the next push/PR in each consuming project.\n\n```bash\n# Example: upgrade pnpm across Tauri apps\n# Change the default in tauri-ci.yml, then let callers pick it up on their next run.\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthedavidweng%2Fcli-workflow-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthedavidweng%2Fcli-workflow-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthedavidweng%2Fcli-workflow-template/lists"}