Skip to content

Commit

Permalink
hack: generate releases.json from GitHub Releases
Browse files Browse the repository at this point in the history
We are currently using the GitHub API in our setup-buildx-action
to check for latest and tagged releases to make sure they exist
before download. But this requires using a token to avoid
rate-limit. It's fine for public runners but GHES runners don't
have the `github.token` populated automatically. They need to
create a PAT.

This PR will solve this issue by generating and pushing a
`releases.json` file in this repo that will then be fetched through
`raw.githubusercontent.com` endpoint on `setup-buildx-action` repo.
This endpoint is better served for our purpose with 5000 requests per
hour compared to the GitHub API endpoint that is limited to 60 requests
per hour (unauth) and 1000 request per hour when authenticated.

Signed-off-by: CrazyMax <[email protected]>
  • Loading branch information
crazy-max committed Jan 28, 2023
1 parent a718d07 commit de1f3be
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
7 changes: 7 additions & 0 deletions docker-bake.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,10 @@ target "image-local" {
inherits = ["image"]
output = ["type=docker"]
}

target "gen-releases-json" {
dockerfile = "./hack/dockerfiles/gen-releases-json.Dockerfile"
target = "generate-update"
output = ["${DESTDIR}"]
secret = ["id=GITHUB_TOKEN,env=GITHUB_TOKEN"]
}
14 changes: 14 additions & 0 deletions hack/dockerfiles/gen-releases-json.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# syntax=docker/dockerfile:1

ARG ALPINE_VERSION=3.17

FROM alpine:${ALPINE_VERSION} AS base
RUN apk add --no-cache bash coreutils curl jq

FROM base AS generate
RUN --mount=type=bind,source=./hack/gen-releases-json,target=/usr/local/bin/gen-releases-json \
--mount=type=secret,id=GITHUB_TOKEN \
DESTDIR=/out GITHUB_TOKEN=$(cat /run/secrets/GITHUB_TOKEN) gen-releases-json

FROM scratch AS generate-update
COPY --from=generate /out /
63 changes: 63 additions & 0 deletions hack/gen-releases-json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -e

: "${DESTDIR=./bin}"
: "${TOKEN="token ${GITHUB_TOKEN}"}"

headers=(-H "Authorization: ${TOKEN}")
repo="https://api.github.com/repos/docker/buildx"
releaseURL="${repo}/releases?per_page=100"
latestURL="${repo}/releases/latest"
output=$(mktemp -d -t buildx-output.XXXXXXXXXX)

# Loop over the paginated results from GitHub releases
_next_page() {
releases=$(curl -s "${headers[@]}" "${releaseURL}")
# "Link:" header from GitHub returns the link for the next page.
releaseURL=$(curl -s -I -H "${headers[@]}" "${releaseURL}" | grep "^link:" | sed -n 's/link:.* <\([^>]\+\)>; rel="next".*/\1/p')
}

# Init releases.json
jq -n '{latest: {}}' > "$output"/releases.json

# Fetch all releases
while [ "${releaseURL}" != "" ]; do
_next_page
for release in $(echo "${releases}" | jq -r '.[] | @base64'); do
_jq() {
echo "${release}" | base64 --decode | jq -r "${1}"
}
id=$(_jq '.id')
tag_name=$(_jq '.tag_name')
html_url=$(_jq '.html_url')
echo "${tag_name}"
(
jq '. += {($tag_name): {tag_name: $tag_name, id: $id, html_url: $html_url, assets:[]}}' --arg tag_name "${tag_name}" --arg id "${id}" --arg html_url "${html_url}" "$output"/releases.json > "$output"/releases.json.tmp
mv "$output"/releases.json.tmp "$output"/releases.json
)
for asset in $(_jq '.assets' | jq -r '.[] | @base64'); do
_jq() {
echo "${asset}" | base64 --decode | jq -r "${1}"
}
asset_browser_download_url=$(_jq '.browser_download_url')
echo " ${asset_browser_download_url}"
(
jq '.[$tag_name].assets += [$browser_download_url]' --arg tag_name "${tag_name}" --arg browser_download_url "${asset_browser_download_url}" "$output"/releases.json > "$output"/releases.json.tmp
mv "$output"/releases.json.tmp "$output"/releases.json
)
done
done
done

# Latest release
latestTag=$(curl -s "${headers[@]}" "${latestURL}" | jq -r ".tag_name")
echo "latest: ${latestTag}"
(
jq '(.latest = .[$tag_name])' --arg tag_name "${latestTag}" "$output"/releases.json > "$output"/releases.json.tmp
mv "$output"/releases.json.tmp "$output"/releases.json
)

set -x
mkdir -p "$DESTDIR"
mv "$output"/releases.json "$DESTDIR"/
cat "$DESTDIR"/releases.json

0 comments on commit de1f3be

Please sign in to comment.