Build release artifacts #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build release artifacts | |
| "on": | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Release tag. Defaults to v<version>." | |
| required: false | |
| type: string | |
| draft: | |
| description: "Create the GitHub Release as a draft" | |
| required: true | |
| default: false | |
| type: boolean | |
| prerelease: | |
| description: "Mark the GitHub Release as a prerelease" | |
| required: true | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: build-release-artifacts-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| name: Build macOS release artifacts | |
| runs-on: macos-15 | |
| timeout-minutes: 60 | |
| env: | |
| APP_BUNDLE_NAME: ClipDock | |
| APP_EXECUTABLE_NAME: ClipDock | |
| BUNDLE_IDENTIFIER: com.apkdv.clipdock | |
| APP_ARCHS: arm64 x86_64 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Print toolchain | |
| run: | | |
| sw_vers | |
| xcodebuild -version | |
| swift --version | |
| cargo --version | |
| - name: Resolve release metadata | |
| id: release | |
| env: | |
| INPUT_TAG: ${{ inputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| source scripts/app-metadata.sh | |
| version="$(read_app_info_value CFBundleShortVersionString 0.1.0)" | |
| build="$(read_app_info_value CFBundleVersion 1)" | |
| tag="$INPUT_TAG" | |
| if [[ ! "$version" =~ ^[0-9]+(\.[0-9]+){1,2}$ ]]; then | |
| echo "version must be numeric, such as 0.1.0" >&2 | |
| exit 1 | |
| fi | |
| if [[ ! "$build" =~ ^[0-9]+$ ]]; then | |
| echo "build must be a positive integer" >&2 | |
| exit 1 | |
| fi | |
| if [[ -z "$tag" ]]; then | |
| tag="v$version" | |
| fi | |
| if [[ ! "$tag" =~ ^[A-Za-z0-9._/-]+$ ]]; then | |
| echo "tag may only contain letters, numbers, dot, underscore, slash, or dash" >&2 | |
| exit 1 | |
| fi | |
| artifact_dir="$GITHUB_WORKSPACE/.codex/artifacts/release/$version" | |
| { | |
| echo "version=$version" | |
| echo "build=$build" | |
| echo "tag=$tag" | |
| echo "artifact_dir=$artifact_dir" | |
| echo "dmgs=$artifact_dir/ClipDock-$version-*.dmg" | |
| echo "checksums=$artifact_dir/SHA256SUMS" | |
| echo "manifest=$artifact_dir/ClipDock-release-manifest.txt" | |
| echo "release_notes=$artifact_dir/ClipDock-release-notes.md" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Generate release notes from commits | |
| env: | |
| RELEASE_VERSION: ${{ steps.release.outputs.version }} | |
| RELEASE_BUILD: ${{ steps.release.outputs.build }} | |
| RELEASE_TAG: ${{ steps.release.outputs.tag }} | |
| RELEASE_NOTES: ${{ steps.release.outputs.release_notes }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "$(dirname "$RELEASE_NOTES")" | |
| target_commit="$GITHUB_SHA" | |
| if git rev-parse -q --verify "refs/tags/$RELEASE_TAG^{commit}" >/dev/null; then | |
| target_commit="$(git rev-list -n 1 "$RELEASE_TAG")" | |
| previous_tag="$(git describe --tags --abbrev=0 "$RELEASE_TAG^" 2>/dev/null || true)" | |
| else | |
| previous_tag="$(git describe --tags --abbrev=0 "$target_commit" 2>/dev/null || true)" | |
| fi | |
| if [[ -n "$previous_tag" ]]; then | |
| commit_range="$previous_tag..$target_commit" | |
| else | |
| commit_range="$target_commit" | |
| fi | |
| { | |
| echo "## ClipDock $RELEASE_VERSION" | |
| echo | |
| echo "- Build: $RELEASE_BUILD" | |
| echo "- Commit: $target_commit" | |
| if [[ -n "$previous_tag" ]]; then | |
| echo "- Changes since: $previous_tag" | |
| fi | |
| echo | |
| echo "## Commits" | |
| echo | |
| } > "$RELEASE_NOTES" | |
| commit_count="$(git rev-list --count "$commit_range" 2>/dev/null || true)" | |
| if [[ "${commit_count:-0}" =~ ^[0-9]+$ && "$commit_count" -gt 0 ]]; then | |
| git log --format="- %s (%h)" --reverse "$commit_range" >> "$RELEASE_NOTES" | |
| else | |
| git log -1 --format="- %s (%h)" "$target_commit" >> "$RELEASE_NOTES" | |
| fi | |
| cat "$RELEASE_NOTES" | |
| - name: Build release bundle | |
| env: | |
| RELEASE_DIR: ${{ steps.release.outputs.artifact_dir }} | |
| CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY || '-' }} | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} | |
| run: scripts/release-macos.sh | |
| - name: Upload workflow artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ClipDock-${{ steps.release.outputs.version }}-macos | |
| path: | | |
| ${{ steps.release.outputs.dmgs }} | |
| ${{ steps.release.outputs.checksums }} | |
| ${{ steps.release.outputs.manifest }} | |
| if-no-files-found: error | |
| retention-days: 30 | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: ${{ steps.release.outputs.tag }} | |
| target_commitish: ${{ github.sha }} | |
| name: ClipDock ${{ steps.release.outputs.version }} | |
| body_path: ${{ steps.release.outputs.release_notes }} | |
| draft: ${{ inputs.draft }} | |
| prerelease: ${{ inputs.prerelease }} | |
| fail_on_unmatched_files: true | |
| overwrite_files: true | |
| files: | | |
| ${{ steps.release.outputs.dmgs }} | |
| ${{ steps.release.outputs.checksums }} | |
| ${{ steps.release.outputs.manifest }} |