chore(release): prepare V1.0.2

This commit is contained in:
zhukang
2026-03-14 22:41:05 +08:00
parent 86e6ea1d80
commit 40405f1993
14 changed files with 513 additions and 22 deletions

View File

@@ -21,6 +21,7 @@ APP_SIGNING_KEYCHAIN="$(atlas_resolve_app_signing_keychain "$APP_SIGN_IDENTITY")
APP_SIGNING_MODE="$(atlas_signing_mode_for_identity "$APP_SIGN_IDENTITY")"
INSTALLER_SIGN_IDENTITY="$(atlas_resolve_installer_signing_identity)"
NOTARY_PROFILE="${ATLAS_NOTARY_PROFILE:-}"
NOTARY_KEYCHAIN="${ATLAS_NOTARY_KEYCHAIN:-}"
mkdir -p "$DIST_DIR"
@@ -122,10 +123,15 @@ echo "Installer package: $PKG_PATH"
echo "Checksums: $SHA_PATH"
if [[ -n "$NOTARY_PROFILE" && "$APP_SIGNING_MODE" == "developer-id" && -n "$INSTALLER_SIGN_IDENTITY" ]]; then
xcrun notarytool submit "$PKG_PATH" --keychain-profile "$NOTARY_PROFILE" --wait
notarytool_args=(--keychain-profile "$NOTARY_PROFILE")
if [[ -n "$NOTARY_KEYCHAIN" ]]; then
notarytool_args+=(--keychain "$NOTARY_KEYCHAIN")
fi
xcrun notarytool submit "$PKG_PATH" "${notarytool_args[@]}" --wait
xcrun stapler staple "$PKG_PATH"
xcrun notarytool submit "$DMG_PATH" --keychain-profile "$NOTARY_PROFILE" --wait
xcrun notarytool submit "$ZIP_PATH" --keychain-profile "$NOTARY_PROFILE" --wait
xcrun notarytool submit "$DMG_PATH" "${notarytool_args[@]}" --wait
xcrun notarytool submit "$ZIP_PATH" "${notarytool_args[@]}" --wait
xcrun stapler staple "$PACKAGED_APP_PATH"
/usr/bin/ditto -c -k --sequesterRsrc --keepParent "$PACKAGED_APP_PATH" "$ZIP_PATH"
(

105
scripts/atlas/prepare-release.sh Executable file
View File

@@ -0,0 +1,105 @@
#!/bin/bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
PROJECT_FILE="$ROOT_DIR/project.yml"
APP_MODEL_FILE="$ROOT_DIR/Apps/AtlasApp/Sources/AtlasApp/AtlasAppModel.swift"
CHANGELOG_FILE="$ROOT_DIR/CHANGELOG.md"
usage() {
cat <<'EOF'
Usage:
./scripts/atlas/prepare-release.sh <version> [build-number] [release-date]
Examples:
./scripts/atlas/prepare-release.sh 1.0.2
./scripts/atlas/prepare-release.sh 1.0.2 3
./scripts/atlas/prepare-release.sh 1.0.2 3 2026-03-14
Behavior:
- updates MARKETING_VERSION and CURRENT_PROJECT_VERSION in project.yml
- updates AtlasApp fallback version/build strings
- inserts a changelog section for the requested version if it does not already exist
EOF
}
if [[ $# -lt 1 || $# -gt 3 ]]; then
usage >&2
exit 1
fi
VERSION="$1"
BUILD_NUMBER="${2:-}"
RELEASE_DATE="${3:-$(date +%F)}"
if [[ ! "$VERSION" =~ ^[0-9]+(\.[0-9]+){1,2}([.-][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid version: $VERSION" >&2
exit 1
fi
if [[ -n "$BUILD_NUMBER" && ! "$BUILD_NUMBER" =~ ^[0-9]+$ ]]; then
echo "Build number must be numeric: $BUILD_NUMBER" >&2
exit 1
fi
if [[ ! "$RELEASE_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "Release date must use YYYY-MM-DD: $RELEASE_DATE" >&2
exit 1
fi
if [[ ! -f "$PROJECT_FILE" || ! -f "$APP_MODEL_FILE" || ! -f "$CHANGELOG_FILE" ]]; then
echo "Expected release files are missing." >&2
exit 1
fi
if [[ -z "$BUILD_NUMBER" ]]; then
current_build="$(
sed -n 's/.*CURRENT_PROJECT_VERSION: \([0-9][0-9]*\).*/\1/p' "$PROJECT_FILE" | head -1
)"
if [[ -z "$current_build" ]]; then
echo "Could not determine current build number from project.yml" >&2
exit 1
fi
BUILD_NUMBER="$((current_build + 1))"
fi
current_version="$(
sed -n 's/.*MARKETING_VERSION: "\(.*\)"/\1/p' "$PROJECT_FILE" | head -1
)"
perl -0pi -e 's/MARKETING_VERSION: "[^"]+"/MARKETING_VERSION: "'"$VERSION"'"/g' "$PROJECT_FILE"
perl -0pi -e 's/CURRENT_PROJECT_VERSION: \d+/CURRENT_PROJECT_VERSION: '"$BUILD_NUMBER"'/g' "$PROJECT_FILE"
perl -0pi -e 's/(CFBundleShortVersionString"\] as\? String \?\? )"[^"]+"/${1}"'"$VERSION"'"/' "$APP_MODEL_FILE"
perl -0pi -e 's/(CFBundleVersion"\] as\? String \?\? )"[^"]+"/${1}"'"$BUILD_NUMBER"'"/' "$APP_MODEL_FILE"
if ! grep -Fq "## [$VERSION] - $RELEASE_DATE" "$CHANGELOG_FILE"; then
tmpfile="$(mktemp "${TMPDIR:-/tmp}/atlas-changelog.XXXXXX")"
awk -v version="$VERSION" -v date="$RELEASE_DATE" '
BEGIN { inserted = 0 }
{
print
if (!inserted && $0 == "## [Unreleased]") {
print ""
print "## [" version "] - " date
print ""
print "### Added"
print ""
print "### Changed"
print ""
print "### Fixed"
print ""
inserted = 1
}
}
' "$CHANGELOG_FILE" > "$tmpfile"
mv "$tmpfile" "$CHANGELOG_FILE"
fi
printf 'Prepared Atlas release files\n'
printf 'Previous version: %s\n' "${current_version:-UNKNOWN}"
printf 'New version: %s\n' "$VERSION"
printf 'Build number: %s\n' "$BUILD_NUMBER"
printf 'Release date: %s\n' "$RELEASE_DATE"
printf 'Updated: %s\n' "$PROJECT_FILE"
printf 'Updated: %s\n' "$APP_MODEL_FILE"
printf 'Updated: %s\n' "$CHANGELOG_FILE"

View File

@@ -0,0 +1,151 @@
#!/bin/bash
set -euo pipefail
require_env() {
local name="$1"
if [[ -z "${!name:-}" ]]; then
echo "Missing required environment variable: $name" >&2
exit 1
fi
}
write_env() {
local name="$1"
local value="$2"
if [[ -n "${GITHUB_ENV:-}" ]]; then
printf '%s=%s\n' "$name" "$value" >> "$GITHUB_ENV"
else
printf 'export %s=%q\n' "$name" "$value"
fi
}
append_keychain_search_list() {
local keychain_path="$1"
local current_keychains=()
local line=""
while IFS= read -r line; do
line="${line#"${line%%[![:space:]]*}"}"
line="${line%\"}"
line="${line#\"}"
[[ -n "$line" ]] && current_keychains+=("$line")
done < <(security list-keychains -d user 2> /dev/null || true)
if printf '%s\n' "${current_keychains[@]}" | grep -Fx "$keychain_path" > /dev/null 2>&1; then
return 0
fi
security list-keychains -d user -s "$keychain_path" "${current_keychains[@]}" > /dev/null
}
decode_base64_to_file() {
local encoded="$1"
local destination="$2"
printf '%s' "$encoded" | base64 --decode > "$destination"
}
detect_identity() {
local policy="$1"
local prefix="$2"
local keychain_path="$3"
security find-identity -v -p "$policy" "$keychain_path" 2> /dev/null |
sed -n "s/.*\"\\($prefix.*\\)\"/\\1/p" |
head -1
}
require_env ATLAS_RELEASE_APP_CERT_P12_BASE64
require_env ATLAS_RELEASE_APP_CERT_P12_PASSWORD
require_env ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64
require_env ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD
require_env ATLAS_NOTARY_KEY_ID
require_env ATLAS_NOTARY_API_KEY_BASE64
KEYCHAIN_PATH="${ATLAS_RELEASE_KEYCHAIN_PATH:-${RUNNER_TEMP:-${TMPDIR:-/tmp}}/atlas-release.keychain-db}"
KEYCHAIN_PASSWORD="${ATLAS_RELEASE_KEYCHAIN_PASSWORD:-$(uuidgen | tr '[:upper:]' '[:lower:]')}"
NOTARY_PROFILE="${ATLAS_NOTARY_PROFILE:-atlas-release}"
tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/atlas-release-signing.XXXXXX")"
cleanup() {
rm -rf "$tmpdir"
}
trap cleanup EXIT
APP_CERT_PATH="$tmpdir/application-cert.p12"
INSTALLER_CERT_PATH="$tmpdir/installer-cert.p12"
NOTARY_KEY_PATH="$tmpdir/AuthKey.p8"
decode_base64_to_file "$ATLAS_RELEASE_APP_CERT_P12_BASE64" "$APP_CERT_PATH"
decode_base64_to_file "$ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64" "$INSTALLER_CERT_PATH"
decode_base64_to_file "$ATLAS_NOTARY_API_KEY_BASE64" "$NOTARY_KEY_PATH"
if [[ -f "$KEYCHAIN_PATH" ]]; then
rm -f "$KEYCHAIN_PATH"
fi
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" > /dev/null
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
append_keychain_search_list "$KEYCHAIN_PATH"
security import "$APP_CERT_PATH" \
-k "$KEYCHAIN_PATH" \
-P "$ATLAS_RELEASE_APP_CERT_P12_PASSWORD" \
-f pkcs12 \
-A \
-T /usr/bin/codesign \
-T /usr/bin/security \
-T /usr/bin/productbuild > /dev/null
security import "$INSTALLER_CERT_PATH" \
-k "$KEYCHAIN_PATH" \
-P "$ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD" \
-f pkcs12 \
-A \
-T /usr/bin/codesign \
-T /usr/bin/security \
-T /usr/bin/productbuild > /dev/null
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" > /dev/null
APP_IDENTITY="${ATLAS_CODESIGN_IDENTITY:-$(detect_identity codesigning 'Developer ID Application:' "$KEYCHAIN_PATH")}"
INSTALLER_IDENTITY="${ATLAS_INSTALLER_SIGN_IDENTITY:-$(detect_identity basic 'Developer ID Installer:' "$KEYCHAIN_PATH")}"
if [[ -z "$APP_IDENTITY" ]]; then
echo "Developer ID Application identity was not imported successfully." >&2
exit 1
fi
if [[ -z "$INSTALLER_IDENTITY" ]]; then
echo "Developer ID Installer identity was not imported successfully." >&2
exit 1
fi
notarytool_args=(
store-credentials
"$NOTARY_PROFILE"
--key "$NOTARY_KEY_PATH"
--key-id "$ATLAS_NOTARY_KEY_ID"
--keychain "$KEYCHAIN_PATH"
--validate
)
if [[ -n "${ATLAS_NOTARY_ISSUER_ID:-}" ]]; then
notarytool_args+=(--issuer "$ATLAS_NOTARY_ISSUER_ID")
fi
xcrun notarytool "${notarytool_args[@]}" > /dev/null
write_env ATLAS_CODESIGN_KEYCHAIN "$KEYCHAIN_PATH"
write_env ATLAS_CODESIGN_IDENTITY "$APP_IDENTITY"
write_env ATLAS_INSTALLER_SIGN_IDENTITY "$INSTALLER_IDENTITY"
write_env ATLAS_NOTARY_PROFILE "$NOTARY_PROFILE"
write_env ATLAS_NOTARY_KEYCHAIN "$KEYCHAIN_PATH"
printf 'Configured Atlas release signing\n'
printf 'App identity: %s\n' "$APP_IDENTITY"
printf 'Installer identity: %s\n' "$INSTALLER_IDENTITY"
printf 'Notary profile: %s\n' "$NOTARY_PROFILE"
printf 'Keychain: %s\n' "$KEYCHAIN_PATH"

View File

@@ -7,6 +7,7 @@ source "$ROOT_DIR/scripts/atlas/signing-common.sh"
APP_IDENTITY_OVERRIDE="${ATLAS_CODESIGN_IDENTITY:-}"
INSTALLER_IDENTITY_OVERRIDE="${ATLAS_INSTALLER_SIGN_IDENTITY:-}"
NOTARY_PROFILE_OVERRIDE="${ATLAS_NOTARY_PROFILE:-}"
NOTARY_KEYCHAIN_OVERRIDE="${ATLAS_NOTARY_KEYCHAIN:-}"
codesign_output="$(security find-identity -v -p codesigning 2> /dev/null || true)"
basic_output="$(security find-identity -v -p basic 2> /dev/null || true)"
@@ -26,6 +27,9 @@ printf '======================\n'
printf 'Developer ID Application: %s\n' "${app_identity:-MISSING}"
printf 'Developer ID Installer: %s\n' "${installer_identity:-MISSING}"
printf 'Notary profile: %s\n' "${NOTARY_PROFILE_OVERRIDE:-MISSING}"
if [[ -n "$NOTARY_KEYCHAIN_OVERRIDE" ]]; then
printf 'Notary keychain: %s\n' "$NOTARY_KEYCHAIN_OVERRIDE"
fi
if [[ -n "$local_identity" ]]; then
printf 'Stable local app identity: %s\n' "$local_identity"
else
@@ -47,7 +51,12 @@ if [[ -z "$NOTARY_PROFILE_OVERRIDE" ]]; then
fi
if [[ -n "$NOTARY_PROFILE_OVERRIDE" ]]; then
if xcrun notarytool history --keychain-profile "$NOTARY_PROFILE_OVERRIDE" > /dev/null 2>&1; then
notarytool_args=(history --keychain-profile "$NOTARY_PROFILE_OVERRIDE")
if [[ -n "$NOTARY_KEYCHAIN_OVERRIDE" ]]; then
notarytool_args+=(--keychain "$NOTARY_KEYCHAIN_OVERRIDE")
fi
if xcrun notarytool "${notarytool_args[@]}" > /dev/null 2>&1; then
echo '✓ notarytool profile is usable'
else
echo '✗ notarytool profile could not be validated'