Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/update-cask.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ on:
paths:
- ".github/workflows/update-cask.yml"
- "scripts/update-cask.sh"
- "scripts/test-update-cask.sh"
schedule:
- cron: "17,47 * * * *"
- cron: "17 5 * * *"
workflow_dispatch:
inputs:
version:
Expand All @@ -29,8 +30,9 @@ jobs:
- uses: actions/checkout@v7
- name: Validate updater
run: |
bash -n scripts/update-cask.sh
shellcheck scripts/update-cask.sh
bash -n scripts/update-cask.sh scripts/test-update-cask.sh
shellcheck scripts/update-cask.sh scripts/test-update-cask.sh
./scripts/test-update-cask.sh

update:
if: github.event_name != 'pull_request'
Expand All @@ -41,6 +43,7 @@ jobs:
- name: Verify release and render cask
id: render
env:
GITHUB_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
run: |
set +e
Expand Down
66 changes: 66 additions & 0 deletions scripts/test-update-cask.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/bash
set -euo pipefail

ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
TEMP_DIRECTORY="$(mktemp -d "${TMPDIR:-/tmp}/headless-cask-test.XXXXXX")"
trap 'rm -rf "$TEMP_DIRECTORY"' EXIT

cat > "$TEMP_DIRECTORY/curl" <<'MOCK'
#!/bin/bash
set -euo pipefail

printf '%s\n' "$*" >> "$MOCK_CURL_ARGUMENTS"
if [[ "$*" == *"/releases/latest"* ]]; then
printf '{"tag_name":"v1.2.3"}\n'
exit 0
fi

output=""
while [[ "$#" -gt 0 ]]; do
if [[ "$1" == "--output" ]]; then
output="$2"
shift 2
continue
fi
shift
done
[[ -z "$output" ]] || : > "$output"
printf '%s' "$MOCK_HTTP_STATUS"
exit 22
MOCK
chmod +x "$TEMP_DIRECTORY/curl"

run_case() {
local expected_exit="$1"
local http_status="$2"
local output="$TEMP_DIRECTORY/output-$http_status"
local result

set +e
PATH="$TEMP_DIRECTORY:$PATH" \
GITHUB_TOKEN="test-token" \
MOCK_CURL_ARGUMENTS="$TEMP_DIRECTORY/curl-arguments-$http_status" \
MOCK_HTTP_STATUS="$http_status" \
"$ROOT/scripts/update-cask.sh" > "$output" 2>&1
result=$?
set -e

[[ "$result" -eq "$expected_exit" ]] || {
echo "Expected HTTP $http_status to exit $expected_exit, got $result" >&2
cat "$output" >&2
exit 1
}
grep -q 'Authorization: Bearer test-token' "$TEMP_DIRECTORY/curl-arguments-$http_status"
}

run_case 78 404
grep -q 'predates the signed distribution contract' "$TEMP_DIRECTORY/output-404"

run_case 22 403
grep -q 'failed to fetch the checksum manifest (HTTP 403)' "$TEMP_DIRECTORY/output-403"
if grep -q 'predates the signed distribution contract' "$TEMP_DIRECTORY/output-403"; then
echo "Transient HTTP failures must not be treated as legacy releases" >&2
exit 1
fi

echo "Cask updater HTTP handling tests passed"
32 changes: 26 additions & 6 deletions scripts/update-cask.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ TEMP_DIRECTORY="$(mktemp -d "${TMPDIR:-/tmp}/headless-cask-update.XXXXXX")"
trap 'rm -rf "$TEMP_DIRECTORY"' EXIT

curl_release() {
curl --fail --silent --show-error --location \
--proto '=https' --tlsv1.2 \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"$1"
local curl_arguments=(
--fail
--silent
--show-error
--location
--proto '=https'
--tlsv1.2
--header 'Accept: application/vnd.github+json'
--header 'X-GitHub-Api-Version: 2022-11-28'
)
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
curl_arguments+=(--header "Authorization: Bearer $GITHUB_TOKEN")
fi
curl "${curl_arguments[@]}" "$@"
}

if [[ -z "$VERSION" ]]; then
Expand All @@ -27,10 +36,21 @@ fi

ASSET="Headless-${VERSION}-macos.zip"
BASE_URL="https://github.com/$REPOSITORY/releases/download/v${VERSION}"
if ! curl_release "$BASE_URL/SHA256SUMS" > "$TEMP_DIRECTORY/SHA256SUMS"; then
set +e
CHECKSUM_HTTP_STATUS="$(curl_release \
--output "$TEMP_DIRECTORY/SHA256SUMS" \
--write-out '%{http_code}' \
"$BASE_URL/SHA256SUMS")"
CHECKSUM_RESULT=$?
set -e
if [[ "$CHECKSUM_RESULT" -ne 0 && "$CHECKSUM_HTTP_STATUS" == "404" ]]; then
echo "Homebrew update: Headless $VERSION predates the signed distribution contract; no cask update" >&2
exit 78
fi
if [[ "$CHECKSUM_RESULT" -ne 0 ]]; then
echo "Homebrew update: failed to fetch the checksum manifest (HTTP $CHECKSUM_HTTP_STATUS)" >&2
exit "$CHECKSUM_RESULT"
fi
curl_release "$BASE_URL/$ASSET" > "$TEMP_DIRECTORY/$ASSET"

EXPECTED_SHA256="$(awk -v asset="$ASSET" '$2 == asset { print $1 }' "$TEMP_DIRECTORY/SHA256SUMS")"
Expand Down