Skip to content

CI/CD

CI/CD #421

Workflow file for this run

name: CI/CD
on:
push:
branches: [ '**' ] # this triggers only on branch commits, which prevents triggering off of tag-only commits
paths-ignore:
- .github/workflows/examples.yml
- .github/workflows/move-tags.yml
workflow_dispatch:
concurrency:
group: ${{ github.ref }}
jobs:
version:
runs-on: ubuntu-latest
outputs:
elixir-version: ${{ steps.parse.outputs.elixir-version }}
otp-version: ${{ steps.parse.outputs.otp-version }}
previous-release-tag: ${{ steps.parse.outputs.previous-release-tag }}
releasable: ${{ steps.parse.outputs.releasable }}
semver: ${{ steps.parse.outputs.semver }}
tag-exists: ${{ steps.parse.outputs.tag-exists }}
steps:
- uses: actions/checkout@v6
- uses: pkgxdev/dev@fix-erlang
- name: Parse version
id: parse
uses: ./.github/actions/version
with:
semver: ${{ env.VERSION }}
- name: Show outputs
run: echo -e "Outputs:\n${{ toJSON(steps.parse.outputs) }}"
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pkgxdev/dev@fix-erlang
- run: mix deps.get
- run: mix deps.compile
- run: mix test
audit:
needs: [ version ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pkgxdev/dev@fix-erlang
- run: mix deps.get
- run: mix deps.compile
- uses: ./.github/actions/dialyzer-cache
with:
otp-version: ${{ needs.version.outputs.otp-version }}
elixir-version: ${{ needs.version.outputs.elixir-version }}
- run: bin/audit --skip-check-image
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/build-tar-image
with:
build-file: .github/Dockerfile
build-context: .
vulnerability-scanner:
needs: [ build ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/load-tar-image
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
exit-code: '1'
format: 'sarif'
ignore-unfixed: true
image-ref: ${{ env.IMAGE_NAME }}
output: 'trivy-results.sarif'
severity: 'MEDIUM,HIGH,CRITICAL'
vuln-type: library
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: 'trivy-results.sarif'
e2e-tests-discovery:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v6
- uses: pkgxdev/dev@fix-erlang
- name: Resolve ERL_BASE
run: |
unset ERL_ROOTDIR
ERL_BIN="$(command -v erl)"
ERL_BIN_REAL="$(readlink -f "$ERL_BIN")"
ERL_DIR="$(dirname "$(dirname "$ERL_BIN_REAL")")"
if [ -d "$ERL_DIR/lib/erlang" ]; then
ERL_BASE="$ERL_DIR/lib/erlang"
else
ERL_BASE="$ERL_DIR"
fi
echo "ERL_BASE=$ERL_BASE" >> "$GITHUB_ENV"
echo "ERL_ROOTDIR=$ERL_BASE" >> "$GITHUB_ENV"
- run: pkgx +invisible-island.net/ncurses -- mix deps.get
- run: pkgx +invisible-island.net/ncurses -- mix deps.compile
- id: set-matrix
name: Discover E2E tests
run: pkgx +invisible-island.net/ncurses -- mix e2e.set_github_matrix matrix
e2e-tests:
needs: [ build, e2e-tests-discovery ]
strategy:
fail-fast: false
matrix: ${{fromJson(needs.e2e-tests-discovery.outputs.matrix)}}
runs-on: ubuntu-latest
name: "e2e tests (${{ matrix.name }})"
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/load-tar-image
- uses: ./.github/actions/run-e2e
with:
image-name: ${{ env.IMAGE_NAME }}
script: ${{ matrix.script }}
expected: ${{ matrix.expected }}
env:
GH_TOKEN: ${{ secrets.PAT }}
push:
needs: [ version, test, audit, build, e2e-tests, vulnerability-scanner ]
runs-on: ubuntu-latest
name: ${{ needs.version.outputs.releasable == 'true' && 'push' || 'push (dry-run)' }}
permissions:
packages: write
steps:
- uses: actions/checkout@v6
- uses: docker/setup-buildx-action@v3
- uses: ./.github/actions/load-tar-image
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- uses: ./.github/actions/push-tar-image
with:
source-image: ${{ env.IMAGE_NAME }}
semver: ${{ needs.version.outputs.semver }}
exists: ${{ needs.version.outputs.tag-exists }}
push: ${{ needs.version.outputs.releasable }}
release:
needs: [ version, push ]
runs-on: ubuntu-latest
name: ${{ needs.version.outputs.releasable == 'true' && 'release' || 'release (dry-run)' }}
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Generate release description
run: |
log_content() {
local content="$1"
local label="${2:-}"
if [[ -n "$label" ]]; then
# Replace the beginning of each line with two spaces
local indented_content="${content//$'\n'/$'\n' }"
printf "%s:\n %s\n" "$label" "$indented_content"
else
echo "$content"
fi
}
CHANGELOG_URL="https://github.com/${{ github.event.repository.full_name }}/compare/${{ needs.version.outputs.previous-release-tag }}...v${{ needs.version.outputs.semver }}"
echo "BODY=**Full Changelog**: $CHANGELOG_URL" >> $GITHUB_ENV
echo ::group::Set outputs
log_content "$(cat "$GITHUB_ENV")" "GITHUB_ENV"
echo ::endgroup::
- uses: softprops/action-gh-release@v2
if: needs.version.outputs.releasable == 'true'
with:
body: ${{ env.BODY }}
generate_release_notes: false
tag_name: v${{ needs.version.outputs.semver }}
token: ${{ secrets.PAT }} # using our own PAT so other workflows run