ci: Automate patch releases and pre-releases

This work by automatically pushing a new tag on main and release
branches after each commit. The tag will be "devel" on main and the
version from postgrest.cabal for release branches. The release
workflow then runs as a tag pipeline, making the actual release.

For release branches, the tag will only be created if a tag for this
version doesn't exist, yet. This means to actually make a new patch
release, we still need to bump the version in postgrest.cabal. We
can automate this later as part of our backport-bot.

This is a back-port of the following commits:
- dd8d51ab
- fe0f2f70
- 58d81334
- 9fe90bf9
- c67f1c39
- 8433f981
- d9ba9a82
- a57d12b1
- b006016d
This commit is contained in:
Wolfgang Walther
2024-05-09 14:08:42 +02:00
committed by Wolfgang Walther
parent 961db7c7ef
commit ac217c120f
3 changed files with 98 additions and 71 deletions
@@ -99,8 +99,15 @@ runs:
} }
archive="$(mktemp)" archive="$(mktemp)"
artifacts="$(mktemp -d)" artifacts="$(mktemp -d)"
curl --no-progress-meter --fail -o "${archive}" \ until curl --no-progress-meter --fail -o "${archive}" \
"https://api.cirrus-ci.com/v1/artifact/task/$(get_external_id)/${{ inputs.download }}.zip" "https://api.cirrus-ci.com/v1/artifact/task/$(get_external_id)/${{ inputs.download }}.zip"
do
# This happens when a tag is pushed on the same commit. In this case the
# job is immediately marked as "completed" for us, so we end up here after a few
# seconds - but the actual Cirrus CI task is still running and didn't produce its artifact, yet.
echo "Artifact not found on Cirrus CI, yet. Waiting..."
sleep 30
done
unzip "${archive}" -d "${artifacts}" unzip "${archive}" -d "${artifacts}"
echo "artifacts=${artifacts}" >> "$GITHUB_OUTPUT" echo "artifacts=${artifacts}" >> "$GITHUB_OUTPUT"
- name: Save artifact to GitHub Actions - name: Save artifact to GitHub Actions
+10 -5
View File
@@ -14,8 +14,13 @@ DOCKER_REPO="$2"
DOCKER_USER="$3" DOCKER_USER="$3"
DOCKER_PASS="$4" DOCKER_PASS="$4"
SCRIPT_DIR="$5" SCRIPT_DIR="$5"
PGRST_VERSION="v$6" PGRST_VERSION="$6"
IS_PRERELEASE="$7"
if [ "$PGRST_VERSION" == "devel" ]; then
PGRST_TAG="$PGRST_VERSION"
else
PGRST_TAG="v$PGRST_VERSION"
fi
DOCKER_BUILD_DIR="$SCRIPT_DIR/docker-env" DOCKER_BUILD_DIR="$SCRIPT_DIR/docker-env"
@@ -38,13 +43,13 @@ cd ~/$DOCKER_BUILD_DIR
# be added to the manifest if they are not in the registry beforehand. # be added to the manifest if they are not in the registry beforehand.
# This image must be manually deleted from Docker Hub at the end of the process. # This image must be manually deleted from Docker Hub at the end of the process.
sudo docker buildx build --build-arg PGRST_GITHUB_COMMIT=$PGRST_GITHUB_COMMIT \ sudo docker buildx build --build-arg PGRST_GITHUB_COMMIT=$PGRST_GITHUB_COMMIT \
-t $DOCKER_REPO/postgrest:$PGRST_VERSION-arm \ -t $DOCKER_REPO/postgrest:$PGRST_TAG-arm \
--push . --push .
# Add the arm images to the manifest # Add the arm images to the manifest
# NOTE: This assumes that there already is a `postgrest:<version>` image # NOTE: This assumes that there already is a `postgrest:<version>` image
# for the amd64 architecture pushed to Docker Hub # for the amd64 architecture pushed to Docker Hub
sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:$PGRST_VERSION $DOCKER_REPO/postgrest:$PGRST_VERSION-arm sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:$PGRST_TAG $DOCKER_REPO/postgrest:$PGRST_TAG-arm
[ -z $IS_PRERELEASE ] && sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:latest $DOCKER_REPO/postgrest:$PGRST_VERSION-arm [ "$PGRST_VERSION" != "devel" ] && sudo docker buildx imagetools create --append -t $DOCKER_REPO/postgrest:latest $DOCKER_REPO/postgrest:$PGRST_TAG-arm
sudo docker logout sudo docker logout
+79 -64
View File
@@ -6,6 +6,7 @@ on:
- main - main
- v[0-9]+ - v[0-9]+
tags: tags:
- devel
- v* - v*
pull_request: pull_request:
branches: branches:
@@ -310,9 +311,11 @@ jobs:
if-no-files-found: error if-no-files-found: error
Prepare-Release: Tag-Release:
name: Prepare release name: Tag Release
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/heads/')
permissions:
contents: write
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: needs:
- Lint-Style - Lint-Style
@@ -321,39 +324,54 @@ jobs:
- Test-Memory-Nix - Test-Memory-Nix
- Build-Static-Nix - Build-Static-Nix
- Build-Stack - Build-Stack
#- Get-FreeBSD-CirrusCI - Get-FreeBSD-CirrusCI
- Build-Cabal-Arm - Build-Cabal-Arm
outputs:
version: ${{ steps.Identify-Version.outputs.version }}
isprerelease: ${{ steps.Identify-Version.outputs.isprerelease }}
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- id: Identify-Version with:
name: Identify the version to be released fetch-tags: true
ssh-key: ${{ secrets.POSTGREST_SSH_KEY }}
- name: Tag latest commit
run: | run: |
tag_version="${GITHUB_REF##*/}"
cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)" cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
if [ "$tag_version" != "v$cabal_version" ]; then if [[ "$cabal_version" == *.*.* ]]; then
echo "Tagged version ($tag_version) does not match the one in postgrest.cabal (v$cabal_version). Aborting release..." if [ -z "$(git tag --list "v$cabal_version")" ]; then
exit 1 git tag "v$cabal_version"
git push origin "v$cabal_version"
fi
else else
echo "Version to be released is $cabal_version" git tag -f "devel"
echo "version=$cabal_version" >> "$GITHUB_OUTPUT" git push -f origin "devel"
fi fi
if [[ "$cabal_version" != *.*.*.* ]]; then
echo "Version is for a full release (version does not have four components)" Prepare-Release:
else name: Prepare release
echo "Version is for a pre-release (version has four components, e.g., 1.1.1.1)" if: startsWith(github.ref, 'refs/tags/')
echo "isprerelease=1" >> "$GITHUB_OUTPUT" runs-on: ubuntu-22.04
needs:
- Lint-Style
- Test-Nix
- Test-Pg-Nix
- Test-Memory-Nix
- Build-Static-Nix
- Build-Stack
- Get-FreeBSD-CirrusCI
- Build-Cabal-Arm
steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Check the version to be released
run: |
cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
if [ "${GITHUB_REF_NAME}" != "devel" ] && [ "${GITHUB_REF_NAME}" != "v$cabal_version" ]; then
echo "Tagged version ($GITHUB_REF_NAME) does not match the one in postgrest.cabal (v$cabal_version). Aborting release..."
exit 1
fi fi
- name: Identify changes from CHANGELOG.md - name: Identify changes from CHANGELOG.md
run: | run: |
version="${{ steps.Identify-Version.outputs.version }}" if [ "${GITHUB_REF_NAME}" == "devel" ]; then
isprerelease="${{ steps.Identify-Version.outputs.isprerelease }}"
if [ -n "$isprerelease" ]; then
echo "Getting unreleased changes..." echo "Getting unreleased changes..."
sed -n "1,/## Unreleased/d;/## \[/q;p" CHANGELOG.md > CHANGES.md sed -n "1,/## Unreleased/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
else else
@@ -377,8 +395,6 @@ jobs:
contents: write contents: write
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: Prepare-Release needs: Prepare-Release
env:
VERSION: ${{ needs.Prepare-Release.outputs.version }}
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Download all artifacts - name: Download all artifacts
@@ -391,24 +407,19 @@ jobs:
mkdir -p release-bundle mkdir -p release-bundle
tar cJvf "release-bundle/postgrest-v$VERSION-linux-static-x64.tar.xz" \ tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-linux-static-x64.tar.xz" \
-C artifacts/postgrest-linux-static-x64 postgrest -C artifacts/postgrest-linux-static-x64 postgrest
# No need to release Ubuntu, as the static Linux binary built with Nix tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-macos-x64.tar.xz" \
# covers all Linux use-cases
#tar cfJv "release-bundle/postgrest-v$VERSION-ubuntu-x64.tar.xz" \
# -C artifacts/postgrest-ubuntu-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-macos-x64.tar.xz" \
-C artifacts/postgrest-macos-x64 postgrest -C artifacts/postgrest-macos-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-freebsd-x64.tar.xz" \ tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-freebsd-x64.tar.xz" \
-C artifacts/postgrest-freebsd-x64 postgrest -C artifacts/postgrest-freebsd-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-ubuntu-aarch64.tar.xz" \ tar cJvf "release-bundle/postgrest-${GITHUB_REF_NAME}-ubuntu-aarch64.tar.xz" \
-C artifacts/postgrest-ubuntu-aarch64 postgrest -C artifacts/postgrest-ubuntu-aarch64 postgrest
zip "release-bundle/postgrest-v$VERSION-windows-x64.zip" \ zip "release-bundle/postgrest-${GITHUB_REF_NAME}-windows-x64.zip" \
artifacts/postgrest-windows-x64/postgrest.exe artifacts/postgrest-windows-x64/postgrest.exe
- name: Save release bundle - name: Save release bundle
@@ -422,14 +433,28 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
isprerelease="${{ needs.Prepare-Release.outputs.isprerelease }}" echo "Releasing version ${GITHUB_REF_NAME} on GitHub..."
echo "Releasing version v$VERSION on GitHub (isprerelease=$isprerelease)..."
gh release delete "v$VERSION" || true if [ "${GITHUB_REF_NAME}" == "devel" ]; then
gh release create "v$VERSION" \ # To replace the existing release, we must first delete the old assets,
-F artifacts/release-changes/CHANGES.md \ # then modify the release, then add the new assets.
${isprerelease:+"--prerelease"} \ gh release view devel --json assets \
release-bundle/* | jq -r '.assets[] | .name' \
| xargs -rn1 \
gh release delete-asset -y devel
gh release edit devel \
-t devel \
--verify-tag \
-F artifacts/release-changes/CHANGES.md \
--prerelease
gh release upload --clobber devel release-bundle/*
else
gh release create "${GITHUB_REF_NAME}" \
-t "${GITHUB_REF_NAME}" \
--verify-tag \
-F artifacts/release-changes/CHANGES.md \
release-bundle/*
fi
Release-Docker: Release-Docker:
@@ -438,18 +463,11 @@ jobs:
needs: needs:
- Prepare-Release - Prepare-Release
env: env:
GITHUB_COMMIT: ${{ github.sha }} DOCKER_REPO: ${{ vars.DOCKER_REPO }}
DOCKER_REPO: postgrest DOCKER_USER: ${{ vars.DOCKER_USER }}
DOCKER_USER: stevechavez
DOCKER_PASS: ${{ secrets.DOCKER_PASS }} DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
VERSION: ${{ needs.Prepare-Release.outputs.version }}
ISPRERELEASE: ${{ needs.Prepare-Release.outputs.isprerelease }}
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: release
- name: Download Docker image - name: Download Docker image
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with: with:
@@ -459,16 +477,16 @@ jobs:
docker login -u "$DOCKER_USER" -p "$DOCKER_PASS" docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
docker load -i postgrest-docker.tar.gz docker load -i postgrest-docker.tar.gz
docker tag postgrest:latest "$DOCKER_REPO/postgrest:v$VERSION" docker tag postgrest:latest "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}"
docker push "$DOCKER_REPO/postgrest:v$VERSION" docker push "$DOCKER_REPO/postgrest:${GITHUB_REF_NAME}"
# Only tag 'latest' for full releases # Only tag 'latest' for full releases
if [[ -z "$ISPRERELEASE" ]]; then if [ "${GITHUB_REF_NAME}" != "devel" ]; then
echo "Pushing to 'latest' tag for full release of v$VERSION ..." echo "Pushing to 'latest' tag for full release of ${GITHUB_REF_NAME} ..."
docker tag postgrest:latest "$DOCKER_REPO"/postgrest:latest docker tag postgrest:latest "$DOCKER_REPO"/postgrest:latest
docker push "$DOCKER_REPO"/postgrest:latest docker push "$DOCKER_REPO"/postgrest:latest
else else
echo "Skipping pushing to 'latest' tag for v$VERSION pre-release..." echo "Skipping push to 'latest' tag for pre-release..."
fi fi
# TODO: Enable dockerhub description update again, once a solution for the permission problem is found: # TODO: Enable dockerhub description update again, once a solution for the permission problem is found:
# https://github.com/docker/hub-feedback/issues/1927 # https://github.com/docker/hub-feedback/issues/1927
@@ -488,15 +506,12 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
needs: needs:
- Build-Cabal-Arm - Build-Cabal-Arm
- Prepare-Release
- Release-Docker - Release-Docker
env: env:
GITHUB_COMMIT: ${{ github.sha }} GITHUB_COMMIT: ${{ github.sha }}
DOCKER_REPO: postgrest DOCKER_REPO: ${{ vars.DOCKER_REPO }}
DOCKER_USER: stevechavez DOCKER_USER: ${{ vars.DOCKER_USER }}
DOCKER_PASS: ${{ secrets.DOCKER_PASS }} DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
VERSION: ${{ needs.Prepare-Release.outputs.version }}
ISPRERELEASE: ${{ needs.Prepare-Release.outputs.isprerelease }}
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Publish images for ARM builds on Docker Hub - name: Publish images for ARM builds on Docker Hub
@@ -509,8 +524,8 @@ jobs:
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }} key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }} fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
script_stop: true script_stop: true
envs: GITHUB_COMMIT,DOCKER_REPO,DOCKER_USER,DOCKER_PASS,REMOTE_DIR,VERSION,ISPRERELEASE envs: GITHUB_COMMIT,DOCKER_REPO,DOCKER_USER,DOCKER_PASS,REMOTE_DIR,GITHUB_REF_NAME
script: bash ~/$REMOTE_DIR/docker-publish.sh "$GITHUB_COMMIT" "$DOCKER_REPO" "$DOCKER_USER" "$DOCKER_PASS" "$REMOTE_DIR" "$VERSION" "$ISPRERELEASE" script: bash ~/$REMOTE_DIR/docker-publish.sh "$GITHUB_COMMIT" "$DOCKER_REPO" "$DOCKER_USER" "$DOCKER_PASS" "$REMOTE_DIR" "$GITHUB_REF_NAME"
Clean-Arm-Server: Clean-Arm-Server:
name: Remove copied files from server name: Remove copied files from server