feat(ci): auto-dispatch publish workflows; fast-winget --submit#361
Conversation
…bmit Adds a trigger-publish job at the end of release-cfl.yml and release-jtk.yml that uses gh workflow run to dispatch each CLI's chocolatey and winget publish workflows once GoReleaser and the tag-rename step finish. Uses the built-in GITHUB_TOKEN with permissions actions write, and each dispatch step is independent (step-level continue-on-error) so a chocolatey failure does not skip the winget dispatch. Job-level continue-on-error preserves the existing decoupling: publish failures do not fail the release run. Migrates both winget publish workflows from the manual fork-clone PR dance to a single wingetcreate update --submit invocation, matching the gro pattern in open-cli-collective/google-readonly#118. Cuts the winget publish wall-clock from ~6 minutes to ~2. Also refreshes the workflow guidance docs to reflect that publish workflows are no longer manual in the common path. Closes #360
|
No findings. The PR matches the revised architecture: GoReleaser config and tag rename stay untouched, publish fanout happens after the release job via Residual risk is limited to the planned post-merge e2e path, which is inherent to this change because the publish dispatch is only observable after the real release workflows run. |
TDD assessmentVerdict: no unit tests warranted. This is correctly an infra-only change. What the diff actually contains
Unit-testable surfaceNone. The Go diff is E2E acceptance criteriaThe PR's verification model is the only one that meaningfully exercises this change:
This is verifiable post-merge via RecommendationShip as-is. No tests to add. |
monit-reviewer
left a comment
There was a problem hiding this comment.
Automated PR Review
Reviewed commit: 6cda87f
Summary
| Reviewer | Findings |
|---|---|
| harness-engineering:harness-architecture-reviewer | 3 |
| harness-engineering:harness-enforcement-reviewer | 1 |
harness-engineering:harness-architecture-reviewer (3 findings)
.github/workflows/winget-publish-cfl.yml:29
--token ${{ secrets.WINGET_GITHUB_TOKEN }} passes the PAT as a CLI argument, making it visible in /proc//cmdline to other processes on the runner. This is a regression from the removed code, which correctly passed the token via the WINGET_CREATE_GITHUB_TOKEN environment variable that wingetcreate reads natively. Restore the env-var approach and drop the --token flag.
.github/workflows/winget-publish-jtk.yml:29
Same token-as-CLI-arg issue as winget-publish-cfl.yml: --token ${{ secrets.WINGET_GITHUB_TOKEN }} exposes the PAT in the process table. The removed code used WINGET_CREATE_GITHUB_TOKEN env var — restore that pattern.
.github/workflows/release-cfl.yml:63
VERSION: ${{ needs.goreleaser.outputs.version }} depends on the goreleaser job declaring an outputs: version: block, which is not visible in the diff. If the output is undeclared, VERSION will be an empty string and gh workflow run dispatches both publish workflows with -f version="". Because trigger-publish has continue-on-error: true at both the job and step level, this failure is completely invisible. Verify goreleaser declares this output, or add a preflight step that explicitly fails if VERSION is empty.
harness-engineering:harness-enforcement-reviewer (1 findings)
.github/workflows/release-jtk.yml:80
Same goreleaser.outputs.version concern as release-cfl.yml: if the goreleaser job does not declare a version output, VERSION is empty and both jtk publish workflows are dispatched silently with an empty version string, swallowed entirely by the dual continue-on-error.
6 info-level observations excluded. Run with --verbose to include.
2 PR discussion threads considered.
Completed in 2m 59s | $0.78 | sonnet | daemon 0.2.116 | Glorfindel
| Field | Value |
|---|---|
| Model | sonnet |
| Reviewers | hybrid-synthesis, documentation:docs-reviewer, harness-engineering:harness-architecture-reviewer, harness-engineering:harness-enforcement-reviewer, harness-engineering:harness-knowledge-reviewer, harness-engineering:harness-self-documenting-code-reviewer, security:security-code-auditor |
| Engine | claude · sonnet |
| Reviewed by | pr-review-daemon · monit-pr-reviewer |
| Duration | 2m 59s wall · 6m 41s compute (Reviewers: 1m 52s · Synthesis: 1m 04s) |
| Cost | $0.78 |
| Tokens | 285.4k in / 32.7k out |
| Turns | 14 |
Per-workstream usage
| Workstream | Model | In | Out | Cache read | Cache create | Cost |
|---|---|---|---|---|---|---|
| hybrid-synthesis | sonnet | 32.6k | 4.9k | 13.6k | 19.0k (1h) | $0.16 |
| documentation:docs-reviewer | haiku | 7.1k | 13.3k | 0 | 7.1k (1h) | $0.08 |
| harness-engineering:harness-architecture-reviewer | sonnet | 65.0k | 4.9k | 46.5k | 18.5k (1h) | $0.17 |
| harness-engineering:harness-enforcement-reviewer | sonnet | 64.3k | 3.2k | 46.1k | 18.2k (1h) | $0.14 |
| harness-engineering:harness-knowledge-reviewer | sonnet | 88.4k | 4.2k | 69.5k | 18.9k (1h) | $0.16 |
| harness-engineering:harness-self-documenting-code-reviewer | sonnet | 13.8k | 398 | 4.0k | 9.7k (1h) | $0.05 |
| security:security-code-auditor | haiku | 14.2k | 1.8k | 0 | 14.2k (1h) | $0.03 |
Re-reviews only run when @monit-reviewer is re-requested as a reviewer — push as many commits as you need, then re-request when ready. PRs targeting branches other than main, master are skipped, even when @monit-reviewer is re-requested.
| --title "$packageId version $version" ` | ||
| --body "Automated winget manifest update for $packageId version $version." | ||
| --submit ` | ||
| --token ${{ secrets.WINGET_GITHUB_TOKEN }} |
There was a problem hiding this comment.
🟡 Medium (harness-engineering:harness-architecture-reviewer): --token ${{ secrets.WINGET_GITHUB_TOKEN }} passes the PAT as a CLI argument, making it visible in /proc//cmdline to other processes on the runner. This is a regression from the removed code, which correctly passed the token via the WINGET_CREATE_GITHUB_TOKEN environment variable that wingetcreate reads natively. Restore the env-var approach and drop the --token flag.
Reply to this thread when addressed.
There was a problem hiding this comment.
Fixed in the follow-up commit — switched to WINGET_CREATE_GITHUB_TOKEN env var, dropped the --token CLI flag.
| --title "$packageId version $version" ` | ||
| --body "Automated winget manifest update for $packageId version $version." | ||
| --submit ` | ||
| --token ${{ secrets.WINGET_GITHUB_TOKEN }} |
There was a problem hiding this comment.
🟡 Medium (harness-engineering:harness-architecture-reviewer): Same token-as-CLI-arg issue as winget-publish-cfl.yml: --token ${{ secrets.WINGET_GITHUB_TOKEN }} exposes the PAT in the process table. The removed code used WINGET_CREATE_GITHUB_TOKEN env var — restore that pattern.
Reply to this thread when addressed.
There was a problem hiding this comment.
Fixed in the same commit alongside the cfl side.
|
|
||
| trigger-publish: | ||
| needs: goreleaser | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
🟡 Medium (harness-engineering:harness-architecture-reviewer): VERSION: ${{ needs.goreleaser.outputs.version }} depends on the goreleaser job declaring an outputs: version: block, which is not visible in the diff. If the output is undeclared, VERSION will be an empty string and gh workflow run dispatches both publish workflows with -f version="". Because trigger-publish has continue-on-error: true at both the job and step level, this failure is completely invisible. Verify goreleaser declares this output, or add a preflight step that explicitly fails if VERSION is empty.
Reply to this thread when addressed.
There was a problem hiding this comment.
The output IS declared — see release-cfl.yml lines 14-15 (unchanged by this PR):
jobs:
goreleaser:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}It's not visible in the diff because that block wasn't touched, but needs.goreleaser.outputs.version resolves correctly. Acknowledging the daemon couldn't see it from the diff alone.
|
|
||
| trigger-publish: | ||
| needs: goreleaser | ||
| runs-on: ubuntu-latest |
There was a problem hiding this comment.
🟡 Medium (harness-engineering:harness-enforcement-reviewer): Same goreleaser.outputs.version concern as release-cfl.yml: if the goreleaser job does not declare a version output, VERSION is empty and both jtk publish workflows are dispatched silently with an empty version string, swallowed entirely by the dual continue-on-error.
Reply to this thread when addressed.
There was a problem hiding this comment.
Same as the cfl thread — release-jtk.yml lines 14-15 declare the version output identically to release-cfl.yml. Unchanged by this PR; the value is real, not empty.
Wingetcreate accepts the token via WINGET_CREATE_GITHUB_TOKEN env var as well as the --token flag; the env-var form avoids exposing the PAT in the process command line.
|
These are low-value, please approve the PR |
Closes #360
Summary
Pattern source
Adapts open-cli-collective/google-readonly#118 to this monorepo. GoReleaser's `monorepo:` block is Pro-only, so the tag-rename dance and goreleaser configs are left unchanged; instead of relying on `release: published` fanout, the release workflow explicitly dispatches its CLI's publishers. Selective publishing is automatic because each release workflow only invokes its own pair.
Why a Go nudge in each tool?
`auto-release-{cfl,jtk}.yml` gates on `tools/{cfl,jtk}/` or `shared/` Go changes plus a `feat:`/`fix:` prefix on the squash commit. To exercise the new auto-publish path end-to-end on merge, this PR touches one comment line in each `cmd/{cfl,jtk}/main.go` (visible in package docs and traceable to #360). The PR title is `feat(ci): ...` so both auto-release workflows fire on the squash commit. Both releases will publish — that's the test.
TAP_GITHUB_TOKEN preflight
Not relevant here. The new dispatch step uses the built-in `GITHUB_TOKEN` with `permissions: actions: write` scoped to the trigger-publish job. `TAP_GITHUB_TOKEN` is unchanged from its existing tag-push / Homebrew-tap roles.
Test plan