Files
postgrest/.github/workflows/ci.yaml
T
Wolfgang Walther fd1efa4635 ci: Merge CI and Loadtest workflows
The reason why those workflows were split in the first place was just to obtain loadtest
results quicker, because the in the separated workflow, only the single loadtest job
needs to finish before the artifacts can be downloaded.

However, the disadvantage of this approach was, that the results were not as easily
accessible as they could be in a single workflow. Additionally, it's possible to depend
on the "prepopulate nix" job for efficiency if the loadtest runs in the main workflow.
2024-02-10 20:15:35 +01:00

575 lines
19 KiB
YAML

name: CI
on:
push:
branches:
- main
- rel-*
tags:
- v*
pull_request:
branches:
- main
- rel-*
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
# Terminate all previous runs of the same workflow and branch, except for main and release branches
cancel-in-progress: "${{ !(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/rel-')) }}"
jobs:
Lint-Style:
name: Lint & check code style
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: style
- name: Run linter (check locally with `nix-shell --run postgrest-lint`)
run: postgrest-lint
- name: Run style check (auto-format with `nix-shell --run postgrest-style`)
run: postgrest-style-check
Test-Nix:
name: Test (Nix)
runs-on: ubuntu-latest
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: tests
- name: Run coverage (IO tests and Spec tests against PostgreSQL 15)
run: postgrest-coverage
- name: Upload coverage to codecov
uses: codecov/codecov-action@v3.1.5
with:
files: ./coverage/codecov.json
- name: Run doctests
if: always()
run: nix-shell --run postgrest-test-doctests
- name: Check the spec tests for idempotence
if: always()
run: postgrest-test-spec-idempotence
Test-Pg-Nix:
strategy:
fail-fast: false
matrix:
pgVersion: [9.6, 10, 11, 12, 13, 14, 15, 16]
name: Test PG ${{ matrix.pgVersion }} (Nix)
runs-on: ubuntu-latest
defaults:
run:
# Hack for enabling color output, see:
# https://github.com/actions/runner/issues/241#issuecomment-842566950
shell: script -qec "bash --noprofile --norc -eo pipefail {0}"
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: tests withTools
- name: Run spec tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} postgrest-test-spec
- name: Run IO tests
if: always()
run: postgrest-with-postgresql-${{ matrix.pgVersion }} -f test/io/fixtures.sql postgrest-test-io -vv
Test-Memory-Nix:
name: Test memory (Nix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: memory
- name: Run memory tests
run: postgrest-test-memory
Loadtest-Nix:
name: Loadtest (Nix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
tools: loadtest
- uses: actions-ecosystem/action-get-latest-tag@v1
id: get-latest-tag
with:
semver_only: true
- name: Run loadtest
run: |
postgrest-loadtest-against main ${{ steps.get-latest-tag.outputs.tag }}
postgrest-loadtest-report > loadtest/loadtest.md
- name: Upload report
uses: actions/upload-artifact@v4
with:
name: loadtest.md
path: loadtest/loadtest.md
if-no-files-found: error
Build-Static-Nix:
name: Build Linux static (Nix)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build static executable
run: nix-build -A postgrestStatic
- name: Save built executable as artifact
uses: actions/upload-artifact@v4
with:
name: postgrest-linux-static-x64
path: result/bin/postgrest
if-no-files-found: error
- name: Build Docker image
run: nix-build -A docker.image --out-link postgrest-docker.tar.gz
- name: Save built Docker image as artifact
uses: actions/upload-artifact@v4
with:
name: postgrest-docker-x64
path: postgrest-docker.tar.gz
if-no-files-found: error
Build-Macos-Nix:
name: Build MacOS (Nix)
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build everything
run: |
nix-build
Build-Stack:
strategy:
fail-fast: false
matrix:
include:
- name: Linux
runs-on: ubuntu-latest
cache: |
~/.stack
.stack-work
# no artifact for Linux, because we use the static build
- name: MacOS
runs-on: macos-latest
cache: |
~/.stack
.stack-work
artifact: postgrest-macos-x64
- name: Windows
runs-on: windows-latest
cache: |
~\AppData\Roaming\stack
~\AppData\Local\Programs\stack
.stack-work
deps: Add-Content $env:GITHUB_PATH $env:PGBIN
artifact: postgrest-windows-x64
name: Build ${{ matrix.name }} (Stack)
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v4
- name: Stack working files cache
uses: actions/cache@v4
with:
path: ${{ matrix.cache }}
key: cache-stack-${{ runner.os }}-${{ hashFiles('stack.yaml.lock') }}
restore-keys: |
cache-stack-${{ runner.os }}-
- name: Install dependencies
if: ${{ matrix.deps }}
run: ${{ matrix.deps }}
- name: Build with Stack
run: stack build --local-bin-path result --copy-bins
- name: Strip Executable
run: strip result/postgrest*
- name: Save built executable as artifact
if: ${{ matrix.artifact }}
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: |
result/postgrest
result/postgrest.exe
if-no-files-found: error
Get-FreeBSD-CirrusCI:
name: Get FreeBSD build from CirrusCI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get FreeBSD executable from CirrusCI
env:
# GITHUB_SHA does weird things for pull request, so we roll our own:
GITHUB_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: .github/get_cirrusci_freebsd
- name: Save executable as artifact
uses: actions/upload-artifact@v4
with:
name: postgrest-freebsd-x64
path: postgrest
if-no-files-found: error
Build-Cabal:
strategy:
matrix:
ghc: ['9.4.8', '9.6.4', '9.8.1']
fail-fast: false
name: Build Linux (Cabal, GHC ${{ matrix.ghc }})
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Workaround runner image issue
# https://github.com/actions/runner-images/issues/7061
run: sudo chown -R "$USER" /usr/local/.ghcup
- name: ghcup
run: |
ghcup install ghc ${{ matrix.ghc }}
ghcup set ghc ${{ matrix.ghc }}
- name: Copy cabal.project & fix caching
run: |
mkdir ~/.cabal
cp cabal.project.non-nix cabal.project
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.cabal/packages
~/.cabal/store
dist-newstyle
key: cache-cabal-${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('postgrest.cabal', 'cabal.project', 'cabal.project.freeze') }}
restore-keys: |
cache-cabal-${{ runner.os }}-${{ matrix.ghc }}-
- name: Install dependencies
run: |
cabal update
cabal build --only-dependencies --enable-tests --enable-benchmarks
- name: Build
run: cabal build --enable-tests --enable-benchmarks all
Build-Cabal-Arm:
strategy:
matrix:
ghc: ['9.4.8']
fail-fast: false
name: Build aarch64 (Cabal, GHC ${{ matrix.ghc }})
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/rel-') }}
runs-on: ubuntu-latest
outputs:
remotepath: ${{ steps.Remote-Dir.outputs.remotepath }}
env:
GITHUB_COMMIT: ${{ github.sha }}
GHC_VERSION: ${{ matrix.ghc }}
steps:
- uses: actions/checkout@v4
- id: Remote-Dir
name: Unique directory name for the remote build
run: echo "remotepath=postgrest-build-$(uuidgen)" >> "$GITHUB_OUTPUT"
- name: Copy script files to the remote server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
source: ".github/scripts/arm/*"
target: ${{ steps.Remote-Dir.outputs.remotepath }}
strip_components: 3
- name: Build ARM
uses: appleboy/ssh-action@master
env:
REMOTE_DIR: ${{ steps.Remote-Dir.outputs.remotepath }}
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
command_timeout: 120m
script_stop: true
envs: GITHUB_COMMIT,REMOTE_DIR,GHC_VERSION
script: bash ~/$REMOTE_DIR/build.sh "$GITHUB_COMMIT" "$REMOTE_DIR" "GHC_VERSION"
- name: Download binaries from remote server
uses: nicklasfrahm/scp-action@main
with:
direction: download
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
source: "${{ steps.Remote-Dir.outputs.remotepath }}/result.tar.xz"
target: "result.tar.xz"
- name: Extract downloaded binaries
run: tar -xvf result.tar.xz && rm result.tar.xz
- name: Save aarch64 executable as artifact
uses: actions/upload-artifact@v4
with:
name: postgrest-ubuntu-aarch64
path: result/postgrest
if-no-files-found: error
Prepare-Release:
name: Prepare release
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
needs:
- Lint-Style
- Test-Nix
- Test-Pg-Nix
- Test-Memory-Nix
- Build-Static-Nix
- Build-Stack
#- Get-FreeBSD-CirrusCI
- Build-Cabal-Arm
outputs:
version: ${{ steps.Identify-Version.outputs.version }}
isprerelease: ${{ steps.Identify-Version.outputs.isprerelease }}
steps:
- uses: actions/checkout@v4
- id: Identify-Version
name: Identify the version to be released
run: |
tag_version="${GITHUB_REF##*/}"
cabal_version="$(grep -oP '^version:\s*\K.*' postgrest.cabal)"
if [ "$tag_version" != "v$cabal_version" ]; then
echo "Tagged version ($tag_version) does not match the one in postgrest.cabal (v$cabal_version). Aborting release..."
exit 1
else
echo "Version to be released is $cabal_version"
echo "version=$cabal_version" >> "$GITHUB_OUTPUT"
fi
if [[ "$cabal_version" != *.*.*.* ]]; then
echo "Version is for a full release (version does not have four components)"
else
echo "Version is for a pre-release (version has four components, e.g., 1.1.1.1)"
echo "isprerelease=1" >> "$GITHUB_OUTPUT"
fi
- name: Identify changes from CHANGELOG.md
run: |
version="${{ steps.Identify-Version.outputs.version }}"
isprerelease="${{ steps.Identify-Version.outputs.isprerelease }}"
if [ -n "$isprerelease" ]; then
echo "Getting unreleased changes..."
sed -n "1,/## Unreleased/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
else
echo "Full release (no '-' in version), getting changes for version $version ..."
sed -n "1,/## \[$version\]/d;/## \[/q;p" CHANGELOG.md > CHANGES.md
fi
echo "Relevant extract from CHANGELOG.md:"
cat CHANGES.md
- name: Save CHANGES.md as artifact
uses: actions/upload-artifact@v4
with:
name: release-changes
path: CHANGES.md
if-no-files-found: error
Release-GitHub:
name: Release on GitHub
permissions:
contents: write
runs-on: ubuntu-latest
needs: Prepare-Release
env:
VERSION: ${{ needs.Prepare-Release.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create release bundle with archives for all builds
run: |
find artifacts -type f -iname postgrest -exec chmod +x {} \;
mkdir -p release-bundle
tar cJvf "release-bundle/postgrest-v$VERSION-linux-static-x64.tar.xz" \
-C artifacts/postgrest-linux-static-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-macos-x64.tar.xz" \
-C artifacts/postgrest-macos-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-freebsd-x64.tar.xz" \
-C artifacts/postgrest-freebsd-x64 postgrest
tar cJvf "release-bundle/postgrest-v$VERSION-ubuntu-aarch64.tar.xz" \
-C artifacts/postgrest-ubuntu-aarch64 postgrest
zip "release-bundle/postgrest-v$VERSION-windows-x64.zip" \
artifacts/postgrest-windows-x64/postgrest.exe
- name: Save release bundle
uses: actions/upload-artifact@v4
with:
name: release-bundle
path: release-bundle
if-no-files-found: error
- name: Publish release on GitHub
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
isprerelease="${{ needs.Prepare-Release.outputs.isprerelease }}"
echo "Releasing version v$VERSION on GitHub (isprerelease=$isprerelease)..."
gh release delete "v$VERSION" || true
gh release create "v$VERSION" \
-F artifacts/release-changes/CHANGES.md \
${isprerelease:+"--prerelease"} \
release-bundle/*
Release-Docker:
name: Release on Docker Hub
runs-on: ubuntu-latest
needs:
- Prepare-Release
env:
GITHUB_COMMIT: ${{ github.sha }}
DOCKER_REPO: postgrest
DOCKER_USER: stevechavez
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
VERSION: ${{ needs.Prepare-Release.outputs.version }}
ISPRERELEASE: ${{ needs.Prepare-Release.outputs.isprerelease }}
steps:
- uses: actions/checkout@v4
- name: Setup Nix Environment
uses: ./.github/actions/setup-nix
with:
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
tools: release
- name: Download Docker image
uses: actions/download-artifact@v4
with:
name: postgrest-docker-x64
- name: Publish images on Docker Hub
run: |
docker login -u "$DOCKER_USER" -p "$DOCKER_PASS"
docker load -i postgrest-docker.tar.gz
docker tag postgrest:latest "$DOCKER_REPO/postgrest:v$VERSION"
docker push "$DOCKER_REPO/postgrest:v$VERSION"
# Only tag 'latest' for full releases
if [[ -z "$ISPRERELEASE" ]]; then
echo "Pushing to 'latest' tag for full release of v$VERSION ..."
docker tag postgrest:latest "$DOCKER_REPO"/postgrest:latest
docker push "$DOCKER_REPO"/postgrest:latest
else
echo "Skipping pushing to 'latest' tag for v$VERSION pre-release..."
fi
# TODO: Enable dockerhub description update again, once a solution for the permission problem is found:
# https://github.com/docker/hub-feedback/issues/1927
# - name: Update descriptions on Docker Hub
# env:
# DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
# run: |
# if [[ -z "$ISPRERELEASE" ]]; then
# echo "Updating description on Docker Hub..."
# postgrest-release-dockerhub-description
# else
# echo "Skipping updating description for pre-release..."
# fi
Release-Docker-Arm:
name: Release Arm Builds on Docker Hub
runs-on: ubuntu-latest
needs:
- Build-Cabal-Arm
- Prepare-Release
- Release-Docker
env:
GITHUB_COMMIT: ${{ github.sha }}
DOCKER_REPO: postgrest
DOCKER_USER: stevechavez
DOCKER_PASS: ${{ secrets.DOCKER_PASS }}
VERSION: ${{ needs.Prepare-Release.outputs.version }}
ISPRERELEASE: ${{ needs.Prepare-Release.outputs.isprerelease }}
steps:
- uses: actions/checkout@v4
- name: Publish images for ARM builds on Docker Hub
uses: appleboy/ssh-action@master
env:
REMOTE_DIR: ${{ needs.Build-Cabal-Arm.outputs.remotepath }}
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
script_stop: true
envs: 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" "$VERSION" "$ISPRERELEASE"
Clean-Arm-Server:
name: Remove copied files from server
needs:
- Build-Cabal-Arm
- Release-Docker-Arm
if: success() ||
needs.Build-Cabal-Arm.result == 'failure' ||
needs.Build-Cabal-Arm.result == 'cancelled' ||
(needs.Build-Cabal-Arm.result == 'success' && !startsWith(github.ref, 'refs/tags/v'))
runs-on: ubuntu-latest
env:
REMOTE_DIR: ${{ needs.Build-Cabal-Arm.outputs.remotepath }}
steps:
- uses: actions/checkout@v4
- name: Remove uploaded files from server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_ARM_HOST }}
username: ubuntu
key: ${{ secrets.SSH_ARM_PRIVATE_KEY }}
fingerprint: ${{ secrets.SSH_ARM_FINGERPRINT }}
envs: REMOTE_DIR
script: rm -rf $REMOTE_DIR