Skip to content

Commit 4ca1c6a

Browse files
committed
Refactor release workflow with versioned builds and helper scripts
Moved complex bash logic from Justfile into dedicated scripts: - scripts/archive.sh: Build and sign, optionally checkout a git tag first - scripts/submit.sh: Submit to Apple notarization service - scripts/staple.sh: Staple ticket and create release zip Builds are now organized by version in build/<version>/ directories, making it easy to manage multiple releases and avoid confusion about which build corresponds to which notarization submission. Usage: just archive v0.0.3 # checks out tag, builds, returns to branch
1 parent b3810b1 commit 4ca1c6a

4 files changed

Lines changed: 195 additions & 168 deletions

File tree

Justfile

Lines changed: 41 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
# CF Cache Status - Build & Release Commands
22
# Usage: just <command>
33

4-
# Load environment from .env if it exists
54
set dotenv-load
65

7-
# Configuration
8-
app_name := "CF Cache Status"
96
project := "CF Cache Status/CF Cache Status.xcodeproj"
107
scheme := "CF Cache Status"
118
build_dir := "build"
12-
archive_path := build_dir / "CacheStatus.xcarchive"
13-
export_path := build_dir / "export"
14-
app_path := export_path / "CF Cache Status.app"
15-
zip_path := build_dir / "CacheStatus.zip"
169

17-
# Default recipe
1810
default:
1911
@just --list
2012

13+
# Show current version from git
14+
version:
15+
@git describe --tags --always 2>/dev/null || echo "untagged"
16+
2117
# Run CDN detection tests
2218
test:
2319
node tests/cdn-detection.test.js
@@ -28,23 +24,13 @@ test:
2824

2925
# Build for development (unsigned)
3026
build-dev:
31-
xcodebuild -project "{{project}}" \
32-
-scheme "{{scheme}}" \
33-
-configuration Debug \
34-
build \
35-
CODE_SIGN_IDENTITY="-" \
36-
CODE_SIGNING_REQUIRED=NO
27+
xcodebuild -project "{{project}}" -scheme "{{scheme}}" -configuration Debug build CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO
3728

3829
# Build release (unsigned, for testing)
3930
build-release:
40-
xcodebuild -project "{{project}}" \
41-
-scheme "{{scheme}}" \
42-
-configuration Release \
43-
build \
44-
CODE_SIGN_IDENTITY="-" \
45-
CODE_SIGNING_REQUIRED=NO
46-
47-
# Clean Xcode build artifacts
31+
xcodebuild -project "{{project}}" -scheme "{{scheme}}" -configuration Release build CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO
32+
33+
# Clean build artifacts
4834
clean:
4935
rm -rf "{{build_dir}}"
5036
xcodebuild -project "{{project}}" -scheme "{{scheme}}" clean
@@ -54,168 +40,55 @@ xcode:
5440
open "{{project}}"
5541

5642
# =============================================================================
57-
# Release (requires APPLE_ID, APPLE_TEAM_ID, APPLE_APP_PASSWORD)
43+
# Release (requires APPLE_ID, APPLE_TEAM_ID, APPLE_APP_PASSWORD in .env)
5844
# =============================================================================
5945

60-
# Build, sign, and archive for distribution
61-
archive:
62-
#!/usr/bin/env bash
63-
set -e
64-
mkdir -p "{{build_dir}}"
65-
66-
xcodebuild archive \
67-
-project "{{project}}" \
68-
-scheme "{{scheme}}" \
69-
-archivePath "{{archive_path}}" \
70-
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
71-
CODE_SIGN_STYLE=Manual \
72-
CODE_SIGN_IDENTITY="Developer ID Application"
73-
74-
cat > "{{build_dir}}/ExportOptions.plist" << EOF
75-
<?xml version="1.0" encoding="UTF-8"?>
76-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
77-
<plist version="1.0">
78-
<dict>
79-
<key>method</key>
80-
<string>developer-id</string>
81-
<key>teamID</key>
82-
<string>$APPLE_TEAM_ID</string>
83-
</dict>
84-
</plist>
85-
EOF
86-
87-
xcodebuild -exportArchive \
88-
-archivePath "{{archive_path}}" \
89-
-exportPath "{{export_path}}" \
90-
-exportOptionsPlist "{{build_dir}}/ExportOptions.plist"
91-
92-
echo "✓ Archive complete: {{app_path}}"
93-
94-
# Submit app for notarization
95-
submit: _check-env
96-
#!/usr/bin/env bash
97-
set -e
98-
99-
if [[ ! -d "{{app_path}}" ]]; then
100-
echo "Error: App not found. Run 'just archive' first."
101-
exit 1
102-
fi
46+
# Build and sign for distribution (optionally specify a tag)
47+
archive tag="":
48+
./scripts/archive.sh {{tag}}
10349

104-
echo "Creating zip..."
105-
ditto -c -k --keepParent "{{app_path}}" "{{zip_path}}"
106-
107-
echo "Submitting for notarization..."
108-
output=$(xcrun notarytool submit "{{zip_path}}" \
109-
--apple-id "$APPLE_ID" \
110-
--team-id "$APPLE_TEAM_ID" \
111-
--password "$APPLE_APP_PASSWORD" \
112-
--output-format json)
113-
114-
submission_id=$(echo "$output" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
115-
echo "$submission_id" > "{{build_dir}}/.submission_id"
116-
117-
echo "✓ Submitted: $submission_id"
118-
echo ""
119-
echo "Check status: just status"
50+
# Submit for notarization
51+
submit version="":
52+
./scripts/submit.sh {{version}}
12053

12154
# Check notarization status
122-
status id="": _check-env
55+
status id="":
12356
#!/usr/bin/env bash
12457
submission_id="{{id}}"
125-
[[ -z "$submission_id" ]] && submission_id=$(cat "{{build_dir}}/.submission_id" 2>/dev/null)
58+
[[ -z "$submission_id" && -f "{{build_dir}}/.current_version" ]] && \
59+
submission_id=$(cat "{{build_dir}}/$(cat {{build_dir}}/.current_version)/.submission_id" 2>/dev/null)
60+
[[ -z "$submission_id" ]] && { echo "No submission ID"; exit 1; }
61+
xcrun notarytool info "$submission_id" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD"
12662

127-
if [[ -z "$submission_id" ]]; then
128-
echo "Error: No submission ID. Provide one or run 'just submit' first."
129-
exit 1
130-
fi
131-
132-
xcrun notarytool info "$submission_id" \
133-
--apple-id "$APPLE_ID" \
134-
--team-id "$APPLE_TEAM_ID" \
135-
--password "$APPLE_APP_PASSWORD"
136-
137-
# Wait for notarization to complete
138-
wait id="": _check-env
63+
# Wait for notarization
64+
wait id="":
13965
#!/usr/bin/env bash
14066
submission_id="{{id}}"
141-
[[ -z "$submission_id" ]] && submission_id=$(cat "{{build_dir}}/.submission_id" 2>/dev/null)
67+
[[ -z "$submission_id" && -f "{{build_dir}}/.current_version" ]] && \
68+
submission_id=$(cat "{{build_dir}}/$(cat {{build_dir}}/.current_version)/.submission_id" 2>/dev/null)
69+
xcrun notarytool wait "$submission_id" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD"
14270

143-
xcrun notarytool wait "$submission_id" \
144-
--apple-id "$APPLE_ID" \
145-
--team-id "$APPLE_TEAM_ID" \
146-
--password "$APPLE_APP_PASSWORD"
71+
# Staple ticket and create final zip
72+
staple version="":
73+
./scripts/staple.sh {{version}}
14774

148-
# Staple notarization ticket and create release zip
149-
staple:
75+
# Full release pipeline: archive, submit, wait, staple
76+
release tag="":
15077
#!/usr/bin/env bash
15178
set -e
152-
153-
if [[ ! -d "{{app_path}}" ]]; then
154-
echo "Error: App not found at {{app_path}}"
155-
exit 1
156-
fi
157-
158-
echo "Stapling ticket..."
159-
xcrun stapler staple "{{app_path}}"
160-
161-
echo "Creating release zip..."
162-
rm -f "{{zip_path}}"
163-
ditto -c -k --keepParent "{{app_path}}" "{{zip_path}}"
164-
165-
echo "✓ Release ready: {{zip_path}}"
166-
167-
# Full release: archive, submit, wait, staple
168-
release: _check-env archive
169-
#!/usr/bin/env bash
170-
set -e
171-
172-
echo "Creating zip..."
173-
ditto -c -k --keepParent "{{app_path}}" "{{zip_path}}"
174-
175-
echo "Submitting for notarization..."
176-
xcrun notarytool submit "{{zip_path}}" \
177-
--apple-id "$APPLE_ID" \
178-
--team-id "$APPLE_TEAM_ID" \
179-
--password "$APPLE_APP_PASSWORD" \
180-
--wait
181-
79+
just archive {{tag}}
80+
just submit
81+
just wait
18282
just staple
183-
echo "✓ Release complete!"
18483

18584
# Show notarization history
186-
history: _check-env
187-
xcrun notarytool history \
188-
--apple-id "$APPLE_ID" \
189-
--team-id "$APPLE_TEAM_ID" \
190-
--password "$APPLE_APP_PASSWORD"
191-
192-
# Get notarization log for a submission
193-
log id: _check-env
194-
xcrun notarytool log "{{id}}" \
195-
--apple-id "$APPLE_ID" \
196-
--team-id "$APPLE_TEAM_ID" \
197-
--password "$APPLE_APP_PASSWORD"
85+
history:
86+
xcrun notarytool history --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD"
19887

199-
# =============================================================================
200-
# Helpers
201-
# =============================================================================
88+
# Get notarization log
89+
log id:
90+
xcrun notarytool log {{id}} --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD"
20291

203-
# Verify required environment variables
204-
[private]
205-
_check-env:
206-
#!/usr/bin/env bash
207-
missing=0
208-
for var in APPLE_ID APPLE_TEAM_ID APPLE_APP_PASSWORD; do
209-
if [[ -z "${!var}" ]]; then
210-
echo "Missing: $var"
211-
missing=1
212-
fi
213-
done
214-
if [[ $missing -eq 1 ]]; then
215-
echo ""
216-
echo "Set these in .env or export them:"
217-
echo " APPLE_ID=your@email.com"
218-
echo " APPLE_TEAM_ID=XXXXXXXXXX"
219-
echo " APPLE_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx"
220-
exit 1
221-
fi
92+
# List available builds
93+
builds:
94+
@ls -d {{build_dir}}/v* {{build_dir}}/dev 2>/dev/null | xargs -I{} basename {} | sort -V || echo "(none)"

scripts/archive.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Build, sign, and archive for distribution
5+
# Usage: ./scripts/archive.sh [tag]
6+
# If a tag is provided, checks out that tag first, builds, then returns
7+
8+
PROJECT="CF Cache Status/CF Cache Status.xcodeproj"
9+
SCHEME="CF Cache Status"
10+
BUILD_DIR="${BUILD_DIR:-build}"
11+
12+
tag="${1:-}"
13+
original_ref=""
14+
15+
# If tag provided, checkout that tag
16+
if [[ -n "$tag" ]]; then
17+
ver="$tag"
18+
19+
if ! git rev-parse "$tag" >/dev/null 2>&1; then
20+
echo "Error: Tag '$tag' not found"
21+
echo "Available tags:"
22+
git tag -l | sort -V | tail -10
23+
exit 1
24+
fi
25+
26+
original_ref=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse HEAD)
27+
echo "Checking out tag: $tag"
28+
git checkout "$tag" --quiet
29+
else
30+
ver=$(git describe --tags --always 2>/dev/null || echo "dev")
31+
fi
32+
33+
cleanup() {
34+
if [[ -n "$original_ref" ]]; then
35+
echo "Returning to: $original_ref"
36+
git checkout "$original_ref" --quiet
37+
fi
38+
}
39+
trap cleanup EXIT
40+
41+
echo "Building version: $ver"
42+
43+
ver_dir="$BUILD_DIR/$ver"
44+
archive_path="$ver_dir/CacheStatus.xcarchive"
45+
export_path="$ver_dir/export"
46+
47+
mkdir -p "$ver_dir"
48+
49+
xcodebuild archive \
50+
-project "$PROJECT" \
51+
-scheme "$SCHEME" \
52+
-archivePath "$archive_path" \
53+
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
54+
CODE_SIGN_STYLE=Manual \
55+
CODE_SIGN_IDENTITY="Developer ID Application"
56+
57+
cat > "$ver_dir/ExportOptions.plist" << EOF
58+
<?xml version="1.0" encoding="UTF-8"?>
59+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
60+
<plist version="1.0">
61+
<dict>
62+
<key>method</key>
63+
<string>developer-id</string>
64+
<key>teamID</key>
65+
<string>$APPLE_TEAM_ID</string>
66+
</dict>
67+
</plist>
68+
EOF
69+
70+
xcodebuild -exportArchive \
71+
-archivePath "$archive_path" \
72+
-exportPath "$export_path" \
73+
-exportOptionsPlist "$ver_dir/ExportOptions.plist"
74+
75+
echo "$ver" > "$BUILD_DIR/.current_version"
76+
77+
echo "✓ Archive complete: $export_path/CF Cache Status.app"

scripts/staple.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Staple notarization ticket and create release zip
5+
# Usage: ./scripts/staple.sh [version]
6+
7+
BUILD_DIR="${BUILD_DIR:-build}"
8+
9+
if [[ -n "$1" ]]; then
10+
ver="$1"
11+
elif [[ -f "$BUILD_DIR/.current_version" ]]; then
12+
ver=$(cat "$BUILD_DIR/.current_version")
13+
else
14+
echo "Error: No version specified. Use './scripts/staple.sh <version>'"
15+
exit 1
16+
fi
17+
18+
ver_dir="$BUILD_DIR/$ver"
19+
app_path="$ver_dir/export/CF Cache Status.app"
20+
zip_path="$ver_dir/CacheStatus-$ver.zip"
21+
22+
if [[ ! -d "$app_path" ]]; then
23+
echo "Error: App not found at $app_path"
24+
exit 1
25+
fi
26+
27+
echo "Stapling version: $ver"
28+
xcrun stapler staple "$app_path"
29+
30+
echo "Creating release zip..."
31+
rm -f "$zip_path"
32+
ditto -c -k --keepParent "$app_path" "$zip_path"
33+
34+
echo "✓ Release ready: $zip_path"

0 commit comments

Comments
 (0)