diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index c73a8f1a5..835b23bab 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -184,4 +184,4 @@ jobs: - name: Test Tauri crate on Windows working-directory: packages/tauri-app/src-tauri - run: cargo test --locked + run: cargo test --locked -- --test-threads=1 diff --git a/.github/workflows/reusable-release.yml b/.github/workflows/reusable-release.yml index 59b1b0583..d8286eb8e 100644 --- a/.github/workflows/reusable-release.yml +++ b/.github/workflows/reusable-release.yml @@ -80,11 +80,19 @@ jobs: if gh release view "$TAG" >/dev/null 2>&1; then echo "Release $TAG already exists" else + args=(--title "$TAG" --generate-notes) + if [ "${IS_PRERELEASE}" = "true" ]; then - gh release create "$TAG" --title "$TAG" --generate-notes --prerelease + args+=(--prerelease) else - gh release create "$TAG" --title "$TAG" --generate-notes + pr_body="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls" \ + --jq 'map(select(.merged_at != null and .base.ref == "main")) | sort_by(.merged_at) | last | .body // ""')" + if [ -n "$pr_body" ]; then + args+=(--notes "$pr_body") + fi fi + + gh release create "$TAG" "${args[@]}" fi build-and-upload: diff --git a/.github/workflows/update-winget.yml b/.github/workflows/update-winget.yml index fd9a656f3..0fb40207c 100644 --- a/.github/workflows/update-winget.yml +++ b/.github/workflows/update-winget.yml @@ -117,7 +117,7 @@ jobs: echo "Resolved version: ${{ steps.release_asset.outputs.version }}" echo "Resolved SHA-256: ${{ steps.release_asset.outputs.asset_sha256 }}" - - name: Validate fork configuration + - name: Validate fork write access env: GH_TOKEN: ${{ secrets.WINGET_GITHUB_TOKEN }} EXPECTED_OWNER: ${{ env.WINGET_FORK_OWNER }} @@ -138,6 +138,14 @@ jobs: exit 1 fi + default_branch="$(gh api "repos/$fork_name" --jq '.default_branch')" + default_sha="$(gh api "repos/$fork_name/git/ref/heads/$default_branch" --jq '.object.sha')" + test_branch="codenomad-winget-token-check-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" + gh api --method POST "repos/$fork_name/git/refs" \ + -f ref="refs/heads/$test_branch" \ + -f sha="$default_sha" >/dev/null + gh api --method DELETE "repos/$fork_name/git/refs/heads/$test_branch" >/dev/null + echo "Validated fork: $fork_name" - name: Submit update to Winget diff --git a/docs/guides/winget-release-automation.md b/docs/guides/winget-release-automation.md index b61639c03..3ca27f161 100644 --- a/docs/guides/winget-release-automation.md +++ b/docs/guides/winget-release-automation.md @@ -14,7 +14,7 @@ CodeNomad publishes Winget updates from the stable GitHub release pipeline. `.gi ### Repository secret -- `WINGET_GITHUB_TOKEN`: Classic GitHub PAT with `public_repo` scope. +- `WINGET_GITHUB_TOKEN`: GitHub token with write access to the configured fork (for example, a classic PAT with `public_repo` scope or a GitHub CLI OAuth token with `repo` scope). - The token owner must own the fork that submits to `microsoft/winget-pkgs`. - Komac-based submission cannot open the PR with a fine-grained token today. @@ -33,7 +33,7 @@ CodeNomad publishes Winget updates from the stable GitHub release pipeline. `.gi 1. Resolve the target release by tag through the GitHub API, then derive the package version from the resolved release tag. 2. Poll the release API until exactly one uploaded asset matches the configured Windows Tauri asset template. 3. Download the matched asset once and compute a SHA-256 for logging and verification. -4. Verify the PAT owner matches `WINGET_FORK_OWNER` and that `${WINGET_FORK_OWNER}/winget-pkgs` is a fork of `microsoft/winget-pkgs`. +4. Verify the token owner matches `WINGET_FORK_OWNER`, that `${WINGET_FORK_OWNER}/winget-pkgs` is a fork of `microsoft/winget-pkgs`, and that the token can create and delete a temporary branch. 5. Invoke `vedantmgoyal9/winget-releaser@v2`, which uses Komac under the hood to update the existing `NeuralNomadsAI.CodeNomad` manifest and open the PR. ## Notes