Skip to content

Release

Release #29

Workflow file for this run

name: Release
# Build a DMG and publish it to a tagged GitHub Release.
#
# Triggers:
# • push of a v* tag → versioned, published release with the DMG
# • workflow_dispatch (tag) → re-run the build for an existing tag
#
# Tagging itself is automated: every Sources-bearing commit on main is
# auto-tagged by .github/workflows/auto-tag.yml, which pushes the new tag
# and dispatches this workflow. For larger bumps use Bump & Release.
#
# `https://github.com/<owner>/<repo>/releases/latest` always redirects to
# the newest published release, which is the stable URL the in-app
# UpdateChecker uses and what should appear in the Install section of the
# README.
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Existing tag to release (e.g. v0.1.0)"
required: true
permissions:
contents: write
concurrency:
# One in-flight run per release target. Different tags are independent
# so simultaneous releases don't supersede each other in the queue.
group: release-${{ inputs.tag || github.ref }}
cancel-in-progress: false
jobs:
release:
name: Build & publish DMG
runs-on: macos-15
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ inputs.tag || github.ref }}
fetch-depth: 0
- name: Plan release
id: plan
run: |
REF="${{ inputs.tag || github.ref_name }}"
if [[ "$REF" != v* ]]; then
echo "::error::Expected a v* tag, got '$REF'."
exit 1
fi
VERSION="${REF#v}"
{
echo "tag=$REF"
echo "version=$VERSION"
echo "dmg_name=YouMenuTube-${VERSION}.dmg"
} >> "$GITHUB_OUTPUT"
echo "Plan → tag=$REF version=$VERSION"
- name: Show toolchain
run: |
xcodebuild -version
swift --version
- name: Install tooling
run: brew install xcodegen create-dmg
- name: Generate Xcode project
run: xcodegen generate --quiet
- name: Resolve Swift packages
run: |
xcodebuild -resolvePackageDependencies \
-project YouMenuTube.xcodeproj \
-scheme YouMenuTube
- name: Build (Release, ad-hoc signed)
run: |
xcodebuild \
-project YouMenuTube.xcodeproj \
-scheme YouMenuTube \
-configuration Release \
-destination 'platform=macOS' \
-derivedDataPath build \
CODE_SIGN_IDENTITY="-" \
CODE_SIGN_STYLE=Manual \
CODE_SIGNING_REQUIRED=YES \
CODE_SIGNING_ALLOWED=YES \
build
- name: Locate built .app
id: app
run: |
APP=$(find build/Build/Products/Release -maxdepth 1 -name "*.app" | head -1)
if [[ -z "$APP" ]]; then
echo "No .app produced under build/Build/Products/Release!" >&2
exit 1
fi
echo "path=$APP" >> "$GITHUB_OUTPUT"
echo "Built: $APP"
- name: Re-sign deeply (ad-hoc)
run: codesign --force --deep --sign - "${{ steps.app.outputs.path }}"
- name: Verify signature
run: codesign --display --verbose=2 "${{ steps.app.outputs.path }}" || true
- name: Package DMG
run: |
DMG="${{ steps.plan.outputs.dmg_name }}"
create-dmg \
--volname "YouMenuTube ${{ steps.plan.outputs.version }}" \
--window-size 540 380 \
--icon-size 96 \
--icon "YouMenuTube.app" 140 180 \
--app-drop-link 400 180 \
--no-internet-enable \
--skip-jenkins \
"$DMG" \
"${{ steps.app.outputs.path }}"
echo "Built $DMG ($(du -h "$DMG" | cut -f1))"
- name: Publish release
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3
with:
tag_name: ${{ steps.plan.outputs.tag }}
name: ${{ steps.plan.outputs.tag }}
draft: false
prerelease: false
generate_release_notes: true
files: YouMenuTube-*.dmg
body: |
## Install
Download the `.dmg` below, open it, drag **YouMenuTube.app** into `/Applications`.
> ⚠️ **First launch**: this build is **ad-hoc signed** (no paid Apple Developer ID), so Gatekeeper will refuse a normal double-click. Either:
> - Right-click the app → **Open** → **Open** again in the prompt, *or*
> - System Settings → Privacy & Security → "YouMenuTube was blocked …" → **Open Anyway**.
>
> Subsequent launches work normally.
See the [README](https://github.com/${{ github.repository }}#install) for full install / disclaimer / privacy notes.