Files
ttree/scripts/tests/release-workflow.test.sh
T
2026-07-10 22:46:24 +08:00

131 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
WORKFLOW="$ROOT_DIR/.github/workflows/release.yml"
PINNED_CERT_SHA1="B8D254561BB6CAD78AA71FA18D62A32D10F50C08"
fail() {
echo "release workflow contract failed: $*" >&2
exit 1
}
require_text() {
local text="$1"
grep -Fq -- "$text" "$WORKFLOW" || fail "missing: $text"
}
reject_text() {
local text="$1"
if grep -Fq -- "$text" "$WORKFLOW"; then
fail "forbidden text present: $text"
fi
}
line_number() {
local text="$1"
grep -Fnm1 -- "$text" "$WORKFLOW" | cut -d: -f1
}
assert_before() {
local first="$1"
local second="$2"
local first_line second_line
first_line="$(line_number "$first")"
second_line="$(line_number "$second")"
[[ -n "$first_line" && -n "$second_line" && "$first_line" -lt "$second_line" ]] ||
fail "expected '$first' before '$second'"
}
require_text "EXPECTED_MACOS_COMMUNITY_CERT_SHA1: $PINNED_CERT_SHA1"
require_text 'MACOS_COMMUNITY_CERTIFICATE'
require_text 'MACOS_COMMUNITY_CERTIFICATE_PASSWORD'
require_text 'TAURI_SIGNING_PRIVATE_KEY'
require_text 'TAURI_SIGNING_PRIVATE_KEY_PASSWORD'
require_text './scripts/validate-release-secrets.sh'
require_text './scripts/validate-release-secrets.sh certificate'
require_text './scripts/validate-release-secrets.sh updater'
require_text 'package_version="$(jq -r '\''.version'\'' package.json)"'
require_text 'tauri_version="$(jq -r '\''.version'\'' src-tauri/tauri.conf.json)"'
require_text 'expected_tag="v$package_version"'
require_text 'Tag $GITHUB_REF_NAME does not match package version $package_version'
require_text 'package.json version $package_version does not match tauri.conf.json version $tauri_version'
require_text 'npm run ci:install'
reject_text 'run: npm ci'
require_text 'npm run check'
require_text 'npm test'
require_text 'cargo check --manifest-path src-tauri/Cargo.toml'
require_text 'cargo test --manifest-path src-tauri/Cargo.toml'
require_text 'cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets -- -D warnings'
require_text './scripts/package-macos-community.sh universal-apple-darwin'
require_text './scripts/package-macos-community.sh universal-apple-darwin "$GITHUB_RUN_NUMBER" --build-only'
require_text './scripts/package-macos-community.sh universal-apple-darwin "$GITHUB_RUN_NUMBER" --package-only'
require_text './scripts/verify-macos-community-signature.sh'
require_text './scripts/verify-macos-release-assets.sh'
require_text 'shasum -a 256 --check SHA256SUMS'
require_text 'trap cleanup_import_files EXIT'
require_text 'workflow_dispatch:'
require_text "if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')"
require_text 'gh release create "$RELEASE_TAG"'
require_text 'gh release delete "$RELEASE_TAG"'
require_text 'existing_tag="$RELEASE_TAG"'
require_text 'gh release delete "$existing_tag"'
require_text '--json isDraft'
require_text 'Release $RELEASE_TAG is already published'
require_text '--yes'
require_text '--draft'
require_text 'gh release download "$RELEASE_TAG"'
require_text 'gh release edit "$RELEASE_TAG"'
require_text '--draft=false'
require_text 'id: draft-release'
require_text 'id: publish-release'
require_text "steps.draft-release.outcome == 'success'"
require_text "steps.publish-release.outcome != 'success'"
require_text 'TTREE_${APP_VERSION}_universal.dmg'
require_text 'TTREE_universal.app.tar.gz'
require_text 'TTREE_universal.app.tar.gz.sig'
require_text 'latest.json'
reject_text 'APPLE_ID'
reject_text 'APPLE_PASSWORD'
reject_text 'APPLE_TEAM_ID'
reject_text 'APPLE_CERTIFICATE'
reject_text 'xcrun stapler'
reject_text 'tauri-apps/tauri-action@'
reject_text 'secrets.MACOS_COMMUNITY_CERT_SHA1'
reject_text '--cleanup-tag'
verify_job_env="$(awk '
/^ env:/ { in_env = 1; next }
/^ steps:/ { exit }
in_env { print }
' "$WORKFLOW")"
if grep -Fq 'secrets.' <<< "$verify_job_env"; then
fail "verify job-level environment must not expose secrets to every step"
fi
action_count=0
while IFS= read -r action; do
action_count=$((action_count + 1))
if [[ ! "$action" =~ @[0-9a-f]{40}$ ]]; then
fail "third-party action is not pinned to a full commit SHA: $action"
fi
done < <(sed -nE 's/^[[:space:]]*(-[[:space:]]*)?uses:[[:space:]]*([^[:space:]#]+).*/\2/p' "$WORKFLOW")
[[ "$action_count" -ge 5 ]] || fail "expected pinned checkout/setup/cache/upload/download actions"
assert_before './scripts/verify-macos-release-assets.sh' 'actions/upload-artifact@'
assert_before 'brew list minisign' 'MACOS_COMMUNITY_CERTIFICATE: ${{ secrets.MACOS_COMMUNITY_CERTIFICATE }}'
assert_before '--build-only' 'MACOS_COMMUNITY_CERTIFICATE: ${{ secrets.MACOS_COMMUNITY_CERTIFICATE }}'
assert_before 'MACOS_COMMUNITY_CERTIFICATE: ${{ secrets.MACOS_COMMUNITY_CERTIFICATE }}' '--package-only'
assert_before 'Clean up signing keychain' 'Verify final app signature'
assert_before 'Clean up signing keychain' 'actions/upload-artifact@'
assert_before 'gh release create "$RELEASE_TAG"' 'gh release download "$RELEASE_TAG"'
assert_before 'gh release download "$RELEASE_TAG"' 'gh release edit "$RELEASE_TAG"'
assert_before 'gh release create "$RELEASE_TAG"' 'gh release delete "$RELEASE_TAG"'
echo "release workflow tests passed"