name: Publish meta
on:
# We publish meta on workflow run since the release manifest requires artifacts of agent build steps
# to be present in the GitHub release manifest that are built and only present after the Publish step runs
workflow_run:
workflows: [Publish]
types:
- completed
workflow_dispatch:
permissions:
contents: read
jobs:
update-versions:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Verify AWS CLI Installation
run: aws --version
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Download releases and upload assets to S3
run: |
# Download releases data
curl -s "https://api.github.com/repos/medplum/medplum/releases?per_page=100" > releases.json
curl -s "https://api.github.com/repos/medplum/medplum/releases/latest" > latest-tmp.json
# Track whether we should continue syncing
DONE=false
# Process each release and upload assets to S3
jq -c '.[]' releases.json | while read -r release; do
TAG_NAME=$(echo "$release" | jq -r '.tag_name')
echo "Processing release: $TAG_NAME"
# Skip if we've already found a complete release
# This only exists so we don't see a broken pipe error at the end if "break" early
# If we use a literal break it causes jq to attempt to write to a broken pipe...
if [ "$DONE" = true ]; then
continue
fi
# Track if all assets exist for this release
ALL_EXIST=true
# Process each asset in the release
echo "$release" | jq -c '.assets[]' | while read -r asset; do
ASSET_NAME=$(echo "$asset" | jq -r '.name')
DOWNLOAD_URL=$(echo "$asset" | jq -r '.browser_download_url')
S3_KEY="releases/${TAG_NAME}/${ASSET_NAME}"
echo " Checking asset: $ASSET_NAME"
# Check if asset already exists in S3 (idempotent check)
if aws s3 ls "s3://download.medplum.com/${S3_KEY}" > /dev/null 2>&1; then
echo " Asset already exists in S3, skipping"
else
echo " Streaming asset directly to S3"
# Mark that not all assets existed
ALL_EXIST=false
# Stream directly from curl to S3
curl -L "$DOWNLOAD_URL" | aws s3 cp - "s3://download.medplum.com/${S3_KEY}" \
--cache-control "public, max-age=31536000, immutable"
fi
done
# If all assets existed for this release, don't attempt to sync subsequent releases
if [ "$ALL_EXIST" = true ]; then
echo " All assets already exist for this release, will skip older releases"
DONE=true
fi
done
- name: Create JSON manifests with S3 URLs
run: |
# Process JSON with jq to create the desired structure
# Replace GitHub URLs with S3 URLs
jq '{
versions: [
.[] | . as $release | {
tag_name,
version: (.tag_name | ltrimstr("v")),
published_at,
assets: [
.assets[] | {
name,
size,
digest,
browser_download_url: "https://download.medplum.com/releases/\($release.tag_name)/\(.name)"
}
]
}
]
}' releases.json > all.json
# Create latest release file
jq '. as $release | {
tag_name,
version: (.tag_name | ltrimstr("v")),
published_at,
assets: [
.assets[] | {
name,
size,
digest,
browser_download_url: "https://download.medplum.com/releases/\($release.tag_name)/\(.name)"
}
]
}' latest-tmp.json > latest.json
# Extract version tag for versioned filename
VERSION_TAG=$(jq -r '.[0].tag_name' releases.json)
echo "VERSION_TAG=${VERSION_TAG}" >> $GITHUB_ENV
- name: Upload JSON manifests to S3
run: |
# Upload all versions JSON
aws s3 cp all.json s3://meta.medplum.com/releases/all.json \
--content-type "application/json" \
--cache-control "no-cache"
# Upload latest.json
aws s3 cp latest.json s3://meta.medplum.com/releases/latest.json \
--content-type "application/json" \
--cache-control "no-cache"
# Upload versioned copy
aws s3 cp latest.json "s3://meta.medplum.com/releases/${VERSION_TAG}.json" \
--content-type "application/json" \
--cache-control "no-cache"