| @@ -25,6 +25,9 @@ EOF · 24 unmodified lines |
| 25 | cat > "$FAKE_BIN/codesign" <<'EOF' | 25 | cat > "$FAKE_BIN/codesign" <<'EOF' |
| 26 | #!/usr/bin/env bash | 26 | #!/usr/bin/env bash |
| 27 | printf '%s\n' "$*" >> "${MOCK_CODESIGN_LOG:?}" | 27 | printf '%s\n' "$*" >> "${MOCK_CODESIGN_LOG:?}" |
| | 28 | if [[ " $* " == *' --check-notarization '* && "${MOCK_NOTARIZATION_REJECT:-0}" == 1 ]]; then |
| | 29 | exit 1 |
| | 30 | fi |
| 28 | case " $* " in | 31 | case " $* " in |
| 29 | *' -dvvv '*) | 32 | *' -dvvv '*) |
| 30 | { | 33 | { |
| @@ -36,6 +39,32 @@ case " $* " in · 5 unmodified lines |
| 36 | esac | 39 | esac |
| 37 | EOF | 40 | EOF |
| 38 | | 41 | |
| | 42 | cat > "$FAKE_BIN/ditto" <<'EOF' |
| | 43 | #!/usr/bin/env bash |
| | 44 | previous= |
| | 45 | for arg in "$@"; do |
| | 46 | source=$previous |
| | 47 | previous=$arg |
| | 48 | done |
| | 49 | cp "$source" "$previous" |
| | 50 | printf 'ditto %s\n' "$*" >> "${MOCK_CODESIGN_LOG:?}" |
| | 51 | EOF |
| | 52 | |
| | 53 | cat > "$FAKE_BIN/xcrun" <<'EOF' |
| | 54 | #!/usr/bin/env bash |
| | 55 | printf 'xcrun %s\n' "$*" >> "${MOCK_CODESIGN_LOG:?}" |
| | 56 | printf '{"id":"12345678-1234-1234-1234-123456789abc","status":"%s"}\n' "${MOCK_NOTARY_STATUS:-Accepted}" |
| | 57 | EOF |
| | 58 | |
| | 59 | cat > "$FAKE_BIN/plutil" <<'EOF' |
| | 60 | #!/usr/bin/env bash |
| | 61 | case "${2:-}" in |
| | 62 | status) printf '%s\n' "${MOCK_NOTARY_STATUS:-Accepted}" ;; |
| | 63 | id) printf '%s\n' '12345678-1234-1234-1234-123456789abc' ;; |
| | 64 | *) exit 1 ;; |
| | 65 | esac |
| | 66 | EOF |
| | 67 | |
| 39 | cat > "$FAKE_BIN/lipo" <<'EOF' | 68 | cat > "$FAKE_BIN/lipo" <<'EOF' |
| 40 | #!/usr/bin/env bash | 69 | #!/usr/bin/env bash |
| 41 | case "${2:-}" in | 70 | case "${2:-}" in |
| @@ -47,6 +76,7 @@ EOF · 5 unmodified lines |
| 47 | chmod 0755 "$FAKE_BIN"/* | 76 | chmod 0755 "$FAKE_BIN"/* |
| 48 | export PATH="$FAKE_BIN:$PATH" | 77 | export PATH="$FAKE_BIN:$PATH" |
| 49 | export MOCK_CODESIGN_LOG="$WORK_DIR/codesign.log" | 78 | export MOCK_CODESIGN_LOG="$WORK_DIR/codesign.log" |
| | 79 | unset NOTARYTOOL_KEYCHAIN_PROFILE |
| 50 | | 80 | |
| 51 | test_binary="$WORK_DIR/gitcrawl" | 81 | test_binary="$WORK_DIR/gitcrawl" |
| 52 | cat > "$test_binary" <<'EOF' | 82 | cat > "$test_binary" <<'EOF' |
| @@ -62,15 +92,48 @@ if CODESIGN_IDENTITY='Developer ID Application: Peter Steinberger (Y5PE65HELJ)' · 9 unmodified lines |
| 62 | echo "package script accepted personal signing identity" >&2 | 92 | echo "package script accepted personal signing identity" >&2 |
| 63 | exit 1 | 93 | exit 1 |
| 64 | fi | 94 | fi |
| | 95 | if CODESIGN_IDENTITY="$EXPECTED_AUTHORITY" \ |
| | 96 | "$ROOT/scripts/package-release.sh" v0.7.1 >/dev/null 2>&1; then |
| | 97 | echo "package script accepted a missing notary profile" >&2 |
| | 98 | exit 1 |
| | 99 | fi |
| 65 | if GITCRAWL_REQUIRE_CODESIGN=1 \ | 100 | if GITCRAWL_REQUIRE_CODESIGN=1 \ |
| 66 | CODESIGN_IDENTITY='Developer ID Application: Peter Steinberger (Y5PE65HELJ)' \ | 101 | CODESIGN_IDENTITY='Developer ID Application: Peter Steinberger (Y5PE65HELJ)' \ |
| 67 | "$ROOT/scripts/codesign-macos.sh" "$test_binary" >/dev/null 2>&1; then | 102 | "$ROOT/scripts/codesign-macos.sh" "$test_binary" >/dev/null 2>&1; then |
| 68 | echo "personal signing identity was accepted" >&2 | 103 | echo "personal signing identity was accepted" >&2 |
| 69 | exit 1 | 104 | exit 1 |
| 70 | fi | 105 | fi |
| | 106 | if GITCRAWL_REQUIRE_CODESIGN=1 \ |
| | 107 | CODESIGN_IDENTITY="$EXPECTED_AUTHORITY" \ |
| | 108 | "$ROOT/scripts/codesign-macos.sh" "$test_binary" >/dev/null 2>&1; then |
| | 109 | echo "official signing accepted a missing notary profile" >&2 |
| | 110 | exit 1 |
| | 111 | fi |
| 71 | GITCRAWL_REQUIRE_CODESIGN=1 \ | 112 | GITCRAWL_REQUIRE_CODESIGN=1 \ |
| 72 | CODESIGN_IDENTITY="$EXPECTED_AUTHORITY" \ | 113 | CODESIGN_IDENTITY="$EXPECTED_AUTHORITY" \ |
| | 114 | NOTARYTOOL_KEYCHAIN_PROFILE=test-profile \ |
| 73 | "$ROOT/scripts/codesign-macos.sh" "$test_binary" | 115 | "$ROOT/scripts/codesign-macos.sh" "$test_binary" |
| | 116 | grep -F -- '--identifier org.openclaw.gitcrawl' "$MOCK_CODESIGN_LOG" >/dev/null |
| | 117 | grep -F 'FWJYW4S8P8' "$MOCK_CODESIGN_LOG" >/dev/null |
| | 118 | grep -F -- 'notarytool submit' "$MOCK_CODESIGN_LOG" >/dev/null |
| | 119 | grep -F -- '--keychain-profile test-profile --no-s3-acceleration --wait --output-format json' "$MOCK_CODESIGN_LOG" >/dev/null |
| | 120 | signed_hash=$(shasum -a 256 "$test_binary" | awk '{ print $1 }') |
| | 121 | if GITCRAWL_REQUIRE_CODESIGN=1 \ |
| | 122 | CODESIGN_IDENTITY="$EXPECTED_AUTHORITY" \ |
| | 123 | NOTARYTOOL_KEYCHAIN_PROFILE=test-profile \ |
| | 124 | MOCK_NOTARY_STATUS=Invalid \ |
| | 125 | "$ROOT/scripts/codesign-macos.sh" "$test_binary" >/dev/null 2>&1; then |
| | 126 | echo "invalid notarization status was accepted" >&2 |
| | 127 | exit 1 |
| | 128 | fi |
| | 129 | [[ "$(shasum -a 256 "$test_binary" | awk '{ print $1 }')" == "$signed_hash" ]] || { |
| | 130 | echo "failed notarization mutated the release binary" >&2 |
| | 131 | exit 1 |
| | 132 | } |
| | 133 | if find "$WORK_DIR" -maxdepth 1 -name '.gitcrawl-notary.*' | grep -q .; then |
| | 134 | echo "ephemeral notarization files were not removed" >&2 |
| | 135 | exit 1 |
| | 136 | fi |
| 74 | | 137 | |
| 75 | ARTIFACTS="$WORK_DIR/artifacts" | 138 | ARTIFACTS="$WORK_DIR/artifacts" |
| 76 | mkdir -p "$ARTIFACTS" | 139 | mkdir -p "$ARTIFACTS" |
| @@ -84,7 +147,14 @@ for arch in amd64 arm64; do · 7 unmodified lines |
| 84 | shasum -a 256 "$ARTIFACTS/$archive" | awk -v name="$archive" '{ print $1 " " name }' >> "$ARTIFACTS/checksums.txt" | 147 | shasum -a 256 "$ARTIFACTS/$archive" | awk -v name="$archive" '{ print $1 " " name }' >> "$ARTIFACTS/checksums.txt" |
| 85 | done | 148 | done |
| 86 | | 149 | |
| | 150 | : > "$MOCK_CODESIGN_LOG" |
| 87 | "$ROOT/scripts/verify-release.sh" v0.7.1 "$ARTIFACTS" | 151 | "$ROOT/scripts/verify-release.sh" v0.7.1 "$ARTIFACTS" |
| | 152 | [[ "$(grep -F -c -- '--verify --strict --check-notarization -R=notarized' "$MOCK_CODESIGN_LOG")" == 2 ]] |
| | 153 | if MOCK_NOTARIZATION_REJECT=1 \ |
| | 154 | "$ROOT/scripts/verify-release.sh" v0.7.1 "$ARTIFACTS" >/dev/null 2>&1; then |
| | 155 | echo "release verifier accepted a missing notarization ticket" >&2 |
| | 156 | exit 1 |
| | 157 | fi |
| 88 | if MOCK_CODESIGN_AUTHORITY='Developer ID Application: Peter Steinberger (Y5PE65HELJ)' \ | 158 | if MOCK_CODESIGN_AUTHORITY='Developer ID Application: Peter Steinberger (Y5PE65HELJ)' \ |
| 89 | "$ROOT/scripts/verify-release.sh" v0.7.1 "$ARTIFACTS" >/dev/null 2>&1; then | 159 | "$ROOT/scripts/verify-release.sh" v0.7.1 "$ARTIFACTS" >/dev/null 2>&1; then |
| 90 | echo "personal signature was accepted" >&2 | 160 | echo "personal signature was accepted" >&2 |
| @@ -104,9 +174,6 @@ if "$ROOT/scripts/verify-release.sh" v0.7.1 "$ARTIFACTS" >/dev/null 2>&1; then · 13 unmodified lines |
| 104 | exit 1 | 174 | exit 1 |
| 105 | fi | 175 | fi |
| 106 | | 176 | |
| 107 | grep -F -- '--identifier org.openclaw.gitcrawl' "$MOCK_CODESIGN_LOG" >/dev/null | | |
| 108 | grep -F 'FWJYW4S8P8' "$MOCK_CODESIGN_LOG" >/dev/null | | |
| 109 | | | |
| 110 | release_workflow="$ROOT/.github/workflows/release-assets.yml" | 177 | release_workflow="$ROOT/.github/workflows/release-assets.yml" |
| 111 | grep -F 'contents: write' "$release_workflow" >/dev/null | 178 | grep -F 'contents: write' "$release_workflow" >/dev/null |
| 112 | grep -F "github.ref == format('refs/heads/{0}', github.event.repository.default_branch)" "$release_workflow" >/dev/null | 179 | grep -F "github.ref == format('refs/heads/{0}', github.event.repository.default_branch)" "$release_workflow" >/dev/null |
| @@ -121,6 +188,10 @@ grep -F 'persist-credentials: false' "$release_workflow" >/dev/null · 8 unmodified lines |
| 121 | grep -F 'tag_name == $tag and (.draft == ($draft == "true"))' "$release_workflow" >/dev/null | 188 | grep -F 'tag_name == $tag and (.draft == ($draft == "true"))' "$release_workflow" >/dev/null |
| 122 | grep -F 'Accept: application/octet-stream' "$release_workflow" >/dev/null | 189 | grep -F 'Accept: application/octet-stream' "$release_workflow" >/dev/null |
| 123 | grep -F 'unset GH_TOKEN GITHUB_TOKEN' "$release_workflow" >/dev/null | 190 | grep -F 'unset GH_TOKEN GITHUB_TOKEN' "$release_workflow" >/dev/null |
| | 191 | if grep -R -F 'NOTARYTOOL_KEYCHAIN_PROFILE' "$ROOT/.github/workflows" >/dev/null; then |
| | 192 | echo "notary profile must not be configured in GitHub Actions" >&2 |
| | 193 | exit 1 |
| | 194 | fi |
| 124 | if grep -F 'gh release download' "$release_workflow" >/dev/null; then | 195 | if grep -F 'gh release download' "$release_workflow" >/dev/null; then |
| 125 | echo "release workflow cannot resolve draft assets through gh release download" >&2 | 196 | echo "release workflow cannot resolve draft assets through gh release download" >&2 |
| 126 | exit 1 | 197 | exit 1 |