-
Notifications
You must be signed in to change notification settings - Fork 134
Repair the release pipeline for 3.0 #394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,31 +1,38 @@ | ||
| name: Brew Bump | ||
|
|
||
| on: | ||
| # Fires only for non-prerelease publications, so `rc` tags never reach | ||
| # homebrew-core. Manual dispatch remains available for re-runs. | ||
| release: | ||
| types: [released] | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| type: string | ||
| required: true | ||
| description: "Release tag to use. e.g. refs/tags/2.2.4" | ||
| description: "Release tag to bump to, e.g. 3.0.0" | ||
|
|
||
| jobs: | ||
| update_brew_formula: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| # - name: Update Homebrew tap | ||
| # uses: dawidd6/action-homebrew-bump-formula@v3 | ||
| # with: | ||
| # token: ${{ secrets.HOMEBREW_BUMP_ACCESS_TOKEN }} | ||
| # org: XCTestHTMLReport | ||
| # tap: XCTestHTMLReport/homebrew-xchtmlreport | ||
| # formula: xchtmlreport | ||
| # tag: ${{ github.event.inputs.version }} | ||
| - name: Resolve tag | ||
| id: tag | ||
| run: | | ||
| if [[ -n "${{ github.event.inputs.version }}" ]]; then | ||
| TAG="${{ github.event.inputs.version }}" | ||
| else | ||
| TAG="${{ github.event.release.tag_name }}" | ||
| fi | ||
| # Tolerate a full ref being pasted into the manual input. | ||
| TAG="${TAG#refs/tags/}" | ||
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | ||
| echo "bumping to ${TAG}" | ||
|
|
||
| - name: Update Official Homebrew formula | ||
| uses: dawidd6/action-homebrew-bump-formula@v3.10.1 | ||
| uses: dawidd6/action-homebrew-bump-formula@v8 | ||
|
Check failure on line 34 in .github/workflows/homebrew-bump.yml
|
||
| with: | ||
| token: ${{ secrets.HOMEBREW_BUMP_ACCESS_TOKEN }} | ||
| # org: XCTestHTMLReport | ||
| formula: xctesthtmlreport | ||
| tag: ${{ github.event.inputs.version }} | ||
| tag: ${{ steps.tag.outputs.tag }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,32 +5,61 @@ | |
| tags: | ||
| - '[0-9]+.[0-9]+.[0-9]+' | ||
| - '[0-9]+.[0-9]+.[0-9]+rc[0-9]+' | ||
| # Lets the whole build/sign/package path be exercised without publishing | ||
| # anything. Before this existed the only way to test a release was to cut one. | ||
| workflow_dispatch: | ||
| inputs: | ||
| dry_run: | ||
| type: boolean | ||
| default: true | ||
| description: "Build, sign and package, but do not notarize or publish" | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: macos-latest | ||
| outputs: | ||
| prerelease: ${{ steps.metadata.outputs.prerelease }} | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Configure Signing | ||
| uses: Apple-Actions/import-codesign-certs@v1 | ||
| uses: Apple-Actions/import-codesign-certs@v7 | ||
|
Check failure on line 27 in .github/workflows/release.yml
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: printf '%s\n' '--- release workflow ---'
cat -n .github/workflows/release.yml | sed -n '1,180p'
printf '%s\n' '--- homebrew workflow ---'
cat -n .github/workflows/homebrew-bump.yml | sed -n '1,70p'
printf '%s\n' '--- changed workflow summary ---'
git diff --stat -- .github/workflows/release.yml .github/workflows/homebrew-bump.yml
printf '%s\n' '--- changed action references ---'
git diff --unified=3 -- .github/workflows/release.yml .github/workflows/homebrew-bump.yml | rg -n '^[+-].*uses:|^@@' || trueRepository: XCTestHTMLReport/XCTestHTMLReport Length of output: 8891 🏁 Script executed: python3 - <<'PY'
import re
from pathlib import Path
files = [
Path(".github/workflows/release.yml"),
Path(".github/workflows/homebrew-bump.yml"),
]
use_re = re.compile(r"^\s*uses:\s*([^#\s]+)")
sha_re = re.compile(r"^[0-9a-fA-F]{40}$")
for path in files:
print(path)
for number, line in enumerate(path.read_text().splitlines(), 1):
match = use_re.match(line)
if not match:
continue
ref = match.group(1).rsplit("@", 1)[-1]
kind = "full commit SHA" if sha_re.fullmatch(ref) else "tag or branch ref"
print(f"{number}: {match.group(1)} -> {kind}")
PYRepository: XCTestHTMLReport/XCTestHTMLReport Length of output: 714 Pin each changed action to a full commit SHA. These version tags can change after review. The actions access signing credentials or release tokens. Retain the intended version in an inline comment.
🧰 Tools🪛 GitHub Check: SonarCloud Code Analysis[failure] 27-27: Use full commit SHA hash for this dependency. 📍 Affects 2 files
🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| with: | ||
| p12-file-base64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} | ||
| p12-password: ${{ secrets.P12_PASSWORD }} | ||
|
|
||
| - name: Setup Xcode version | ||
| uses: maxim-lobanov/[email protected] | ||
| uses: maxim-lobanov/[email protected] | ||
| with: | ||
| xcode-version: ^16 | ||
| xcode-version: latest-stable | ||
|
|
||
| - name: Generate Metadata | ||
| id: metadata | ||
| run: | | ||
| [[ "$GITHUB_REF" =~ refs/tags ]] && VERSION=${GITHUB_REF/refs\/tags\//} || exit | ||
| echo ::set-output name=version::${VERSION} | ||
| echo ::set-output name=bin_path::.build/universal/release/xchtmlreport | ||
| echo ::set-output name=archive_name::xchtmlreport-${VERSION}.zip | ||
| if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]; then | ||
| VERSION="${GITHUB_REF#refs/tags/}" | ||
| else | ||
| VERSION="0.0.0-dryrun" | ||
| fi | ||
| # `rc` tags carry no hyphen, so a `contains(github.ref, '-')` test | ||
| # never fired for them and release candidates shipped as full releases. | ||
| if [[ "$VERSION" == *rc* ]]; then PRERELEASE=true; else PRERELEASE=false; fi | ||
| { | ||
| echo "version=${VERSION}" | ||
| echo "prerelease=${PRERELEASE}" | ||
| echo "bin_path=.build/universal/release/xchtmlreport" | ||
| echo "archive_name=xchtmlreport-${VERSION}.zip" | ||
| } >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Stamp version into the binary | ||
| # Version.swift was only ever written by the post-release bump job, so the | ||
| # released binary reported whatever happened to be on main rather than the | ||
| # tag it was built from. Stamping here makes `--version` match the tag. | ||
| run: | | ||
| echo "let version = \"${{ steps.metadata.outputs.version }}\"" \ | ||
|
Comment on lines
+40
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Validate release tags before reuse. Line 60 interpolates a tag-derived output into shell source. A tag containing a quote or shell syntax can alter the generated command. Validate Proposed fix - name: Stamp version into the binary
+ env:
+ VERSION: ${{ steps.metadata.outputs.version }}
run: |
- echo "let version = \"${{ steps.metadata.outputs.version }}\"" \
+ printf 'let version = "%s"\n' "$VERSION" \
> Sources/XCTestHTMLReport/Version.swift🧰 Tools🪛 zizmor (1.29.0)[info] 60-60: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| > Sources/XCTestHTMLReport/Version.swift | ||
| cat Sources/XCTestHTMLReport/Version.swift | ||
|
|
||
| - name: Build (arm64) | ||
| run: swift build -v -c release --triple arm64-apple-macosx | ||
|
|
@@ -44,16 +73,28 @@ | |
| lipo -create -output ${{ steps.metadata.outputs.bin_path }} \ | ||
| .build/arm64-apple-macosx/release/xchtmlreport \ | ||
| .build/x86_64-apple-macosx/release/xchtmlreport | ||
| lipo -info ${{ steps.metadata.outputs.bin_path }} | ||
|
|
||
| - name: Verify the built binary reports the tagged version | ||
| run: | | ||
| REPORTED=$(${{ steps.metadata.outputs.bin_path }} --version) | ||
| echo "reported: ${REPORTED}" | ||
| if [[ "${REPORTED}" != "${{ steps.metadata.outputs.version }}" ]]; then | ||
| echo "::error::binary reports '${REPORTED}' but this is release '${{ steps.metadata.outputs.version }}'" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Sign | ||
| run: | | ||
| codesign --verbose --verify --options=runtime -f \ | ||
| -s "Developer ID Application: Tyler Vick (${{ secrets.AC_TEAM_ID }})" \ | ||
| ${{ steps.metadata.outputs.bin_path }} | ||
|
|
||
| - name: Verify | ||
| # --deep is deprecated by Apple and is not the right check for a lone | ||
| # executable; --strict on the binary itself is. | ||
| run: | | ||
| codesign -vvv --deep --strict ${{ steps.metadata.outputs.bin_path }} | ||
| codesign -vvv --strict ${{ steps.metadata.outputs.bin_path }} | ||
|
|
||
| - name: Package | ||
| run: | | ||
|
|
@@ -62,6 +103,7 @@ | |
| ${{ steps.metadata.outputs.archive_name }} | ||
|
|
||
| - name: Notarize | ||
| if: github.event_name == 'push' | ||
| run: | | ||
| xcrun notarytool submit ${{ steps.metadata.outputs.archive_name }} \ | ||
| --apple-id ${{ secrets.AC_USERNAME }} \ | ||
|
|
@@ -75,19 +117,26 @@ | |
| name: application | ||
| path: ${{ steps.metadata.outputs.archive_name }} | ||
|
|
||
| - name: Dry run summary | ||
| if: github.event_name == 'workflow_dispatch' | ||
| run: | | ||
| echo "### Dry run complete" >> "$GITHUB_STEP_SUMMARY" | ||
| echo "Built, signed and packaged \`${{ steps.metadata.outputs.archive_name }}\`." >> "$GITHUB_STEP_SUMMARY" | ||
| echo "Notarization and publishing were skipped." >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| release: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| needs: build | ||
|
|
||
| if: github.event_name == 'push' | ||
|
|
||
| steps: | ||
| - name: Download | ||
| uses: actions/download-artifact@v4.1.7 | ||
| uses: actions/download-artifact@v4 | ||
|
|
||
| - name: Release | ||
| uses: softprops/action-gh-release@v1 | ||
| uses: softprops/action-gh-release@v3 | ||
|
Check failure on line 137 in .github/workflows/release.yml
|
||
| with: | ||
| prerelease: ${{ contains(github.ref, '-') }} | ||
| prerelease: ${{ needs.build.outputs.prerelease == 'true' }} | ||
| generate_release_notes: true | ||
| files: | | ||
| application/xchtmlreport-* | ||
|
|
@@ -97,11 +146,14 @@ | |
| bump_version: | ||
| runs-on: ubuntu-latest | ||
| needs: release | ||
| if: github.event_name == 'push' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| # Bumps the patch component only. Major and minor bumps are deliberate | ||
| # decisions and are made by hand before tagging. | ||
| - name: Get next version | ||
| uses: reecetech/version-increment@2022.5.1 | ||
| uses: reecetech/version-increment@2024.10.1 | ||
|
Check failure on line 156 in .github/workflows/release.yml
|
||
| id: version | ||
| with: | ||
| scheme: semver | ||
|
|
@@ -111,7 +163,7 @@ | |
| run: echo 'let version = "${{ steps.version.outputs.version }}"' > Sources/XCTestHTMLReport/Version.swift | ||
|
|
||
| - name: Create Pull Request | ||
| uses: peter-evans/create-pull-request@v3 | ||
| uses: peter-evans/create-pull-request@v8 | ||
|
Check failure on line 166 in .github/workflows/release.yml
|
||
| with: | ||
| title: "${{ steps.version.outputs.version }} Version Bump" | ||
| body: "Bumping version from ${{ steps.version.outputs.current-version }} to ${{ steps.version.outputs.version }}" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| let version = "2.5.2-pre.bc4e30e" | ||
| let version = "3.0.0-pre" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Do not interpolate tag values into shell source.
Lines 23-26 expand manual input and release metadata before Bash parses the script. A crafted value can terminate the quoted assignment and execute commands. Map both values through
env, then use quoted shell variables. Validate the resolved tag before publishing it.Proposed fix
- name: Resolve tag id: tag + env: + INPUT_VERSION: ${{ inputs.version }} + RELEASE_TAG: ${{ github.event.release.tag_name }} run: | - if [[ -n "${{ github.event.inputs.version }}" ]]; then - TAG="${{ github.event.inputs.version }}" + if [[ -n "$INPUT_VERSION" ]]; then + TAG="$INPUT_VERSION" else - TAG="${{ github.event.release.tag_name }}" + TAG="$RELEASE_TAG" fi🧰 Tools
🪛 zizmor (1.29.0)
[error] 23-23: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 24-24: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
[error] 26-26: code injection via template expansion (template-injection): may expand into attacker-controllable code
(template-injection)
🤖 Prompt for AI Agents
Source: Linters/SAST tools