Skip to content

Build release artifacts #12

Build release artifacts

Build release artifacts #12

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 }}