Go #313
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This workflow will build a golang project | |
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go | |
name: Go | |
env: | |
REGISTRY: ghcr.io | |
IMAGE_NAME: ${{ github.repository }} | |
# Note: we _have_ to run on `push` instead of `pull_request`. When using `pull_request` the branch used is not | |
# the source branch you've used locally, but a "virtual" branch (in the form of `refs/pull/<id>/merge`) that | |
# contains the result of the actual merge. The logic inside semantic-release does not allow you to configure | |
# this branch, that is, as this branch is not present as a remote head (remember the "virtual") so it is filtered | |
# out. The direct consequence is that semantic-release does not consider the current branch to be configured and | |
# aborts. Just to reiterate: semantic-release looks at the remote heads, so configuring `refs/pull/<id>/merge` as | |
# a branch does not solve the problem: that branch will never exist as a remote head. | |
# The filtering on branches happens here: | |
# https://github.com/semantic-release/semantic-release/blob/4bddb37de2fc6743a82299e277d5852d153e2ba8/index.js#L69 | |
# And the remote heads lookup happens here: | |
# https://github.com/semantic-release/semantic-release/blob/4bddb37de2fc6743a82299e277d5852d153e2ba8/lib/git.js#L67 | |
on: | |
push: | |
branches-ignore: | |
- 'dependabot/**' | |
workflow_run: | |
workflows: [ "Dependabot PR" ] | |
types: | |
- completed | |
jobs: | |
# This job only runs if this workflow is triggered by Dependabot, in that case we make | |
# sure the triggering workflow 'Dependabot PR' completed successfully. That should | |
# always be the case, if not, something is seriously wrong. | |
check-result-dependabot-pr: | |
runs-on: ubuntu-latest | |
if: ${{ (github.event_name == 'workflow_run') && (github.event.workflow_run.conclusion == 'failure') }} | |
steps: | |
- run: echo "The 'Dependabot PR' workflow failed, this should never happen" && exit 1 | |
format: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
# Use the go version as specified in the go.mod, using the latest available | |
# patch release, see: | |
# https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22' | |
cache-dependency-path: go.sum | |
- name: Verify formatting | |
run: test -z "$(gofmt -l ./)" | |
vet: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
# Use the go version as specified in the go.mod, using the latest available | |
# patch release, see: | |
# https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22' | |
cache-dependency-path: go.sum | |
- name: Run Go Vet | |
run: go vet ./... | |
goimports: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
# Use the go version as specified in the go.mod, using the latest available | |
# patch release, see: | |
# https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22' | |
cache-dependency-path: go.sum | |
- name: Check imports | |
run: | | |
go install golang.org/x/tools/cmd/goimports@latest | |
test -z "$(goimports -local founda.com -l .)" | |
tidy: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
# Use the go version as specified in the go.mod, using the latest available | |
# patch release, see: | |
# https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22' | |
cache-dependency-path: go.sum | |
- name: Verify go.mod is tidy | |
run: | | |
go mod tidy | |
git diff --exit-code go.mod go.sum | |
staticcheck: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
# Use the go version as specified in the go.mod, using the latest available | |
# patch release, see: | |
# https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22' | |
cache-dependency-path: go.sum | |
- name: Run Staticcheck | |
uses: dominikh/[email protected] | |
with: | |
version: "2023.1.3" | |
install-go: false | |
version: | |
runs-on: ubuntu-latest | |
# Map a step output to a job output, see: | |
# https://stackoverflow.com/a/61236803 | |
outputs: | |
version: ${{ steps.version.outputs.VERSION }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version: "lts/*" | |
- name: Install dependencies | |
run: | | |
npm i -g \ | |
semantic-release \ | |
@semantic-release/changelog \ | |
@semantic-release/exec \ | |
@semantic-release/git \ | |
conventional-changelog-conventionalcommits | |
# The following two steps only run if this workflow is triggered by | |
# Dependabot, in that case we download the artifact created by the | |
# `Dependabot PR` workflow. This artifact contains the PR number of | |
# the PR that Dependabot opened. We will use the number as (part of) | |
# the tags for our Docker images. We need this tag as we need to push | |
# our `aws-rds-authenticator` base-image also in the case of a workflow | |
# triggered by Dependabot. Our database client images depend on a | |
# published version of our base-image, otherwise they can't pull it. | |
# By using the PR number we guarantee we are using a unique tag per | |
# Dependabot-branch which also do not collide SemVer, so no risk of | |
# overwriting existing images. | |
- name: Download file containing the Dependabot PR number | |
if: ${{ github.event_name == 'workflow_run' }} | |
uses: dawidd6/action-download-artifact@v3 | |
with: | |
github_token: ${{ secrets.GITHUB_TOKEN }} | |
run_id: ${{ github.event.workflow_run.id }} | |
- name: Read the PR number | |
id: pr_number_reader | |
if: ${{ github.event_name == 'workflow_run' }} | |
uses: juliangruber/read-file-action@v1 | |
with: | |
path: ./pr_number/pr_number.txt | |
- name: Get latest version | |
id: version | |
run: | | |
if ${{ (github.event_name != 'workflow_run') }}; then | |
semantic-release --dry-run --branches main,${{ github.ref_name }} --no-ci --debug | |
cat version.env >> $GITHUB_OUTPUT | |
else | |
echo "VERSION=dependabot-${{ steps.pr_number_reader.outputs.content }}" | tr -d '\n' >> $GITHUB_OUTPUT | |
fi | |
env: | |
GITHUB_TOKEN: ${{ secrets.FOUNDA_DEV_PAT }} | |
GIT_AUTHOR_NAME: "Founda Automation" | |
GIT_AUTHOR_EMAIL: "[email protected]" | |
GIT_COMMITTER_NAME: "Founda Automation" | |
GIT_COMMITTER_EMAIL: "[email protected]" | |
test: | |
runs-on: ubuntu-latest | |
# Test Report needs to be able to update checks, see: | |
# https://github.com/mikepenz/action-junit-report#pr-run-permissions | |
permissions: | |
checks: write | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
# Use the go version as specified in the go.mod, using the latest available | |
# patch release, see: | |
# https://github.com/actions/setup-go#getting-go-version-from-the-gomod-file | |
- name: Set up Go | |
uses: actions/setup-go@v5 | |
with: | |
go-version: '1.22' | |
cache-dependency-path: go.sum | |
- name: Install dependencies | |
run: go get . | |
- name: Test with Go | |
run: | | |
go install github.com/jstemmer/go-junit-report/v2@latest | |
go test -v ./... | go-junit-report -iocopy -out report.xml -set-exit-code | |
- name: Publish Test Report | |
uses: mikepenz/action-junit-report@v4 | |
if: always() | |
with: | |
report_paths: report.xml | |
docker-build: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
needs: | |
- format | |
- vet | |
- goimports | |
- tidy | |
- staticcheck | |
- version | |
- test | |
strategy: | |
matrix: | |
target: [ "alpine", "bullseye", "scratch" ] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Log in to the Container registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Extract metadata (tags, labels) for Docker | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
# We will not create a `latest` tag by default, it does not seem to work: | |
# it adds the `latest` tag also on branch-builds, which is undesired. | |
# We'll configure `latest` ourselves, see: | |
# https://github.com/marketplace/actions/docker-metadata-action#flavor-input. | |
flavor: | | |
latest=false | |
# Configure the global suffix | |
suffix=${{ fromJSON(format('["-{0}",""]', matrix.target))[matrix.target == 'scratch'] }},onlatest=true | |
# Configure a tag of type `raw`, so we have no constraints on the format, | |
# as our Dependabot builds do not follow SemVer when creating their tags. | |
# See: https://github.com/marketplace/actions/docker-metadata-action#typeraw. | |
# Note that builds triggered by Dependabot can also run from `main`, so our | |
# check if we run on `main` is no longer enough to alone determine which | |
# tags to publish. We add a second condition to check which event triggered | |
# this build, when we see `workflow_run` we treat it always as a branch build | |
# even if triggered on `main`. | |
tags: | | |
# Push `latest` when on the default branch, but not when triggered | |
# via Dependabot. | |
type=raw,value=latest,enable=${{ (github.ref_name == github.event.repository.default_branch) && (github.event_name != 'workflow_run') }} | |
# Push version without branch suffix when on the default branch, or | |
# when triggered via Dependabot. The tag is then already unique, so | |
# no need for another suffix. | |
type=raw,value=${{ needs.version.outputs.version }},enable=${{ (github.ref_name == github.event.repository.default_branch) || (github.event_name == 'workflow_run') }} | |
# Push the version with branch suffix otherwise. | |
type=raw,value=${{ needs.version.outputs.version }}-{{branch}},enable=${{ (github.ref_name != github.event.repository.default_branch) && (github.event_name != 'workflow_run') }} | |
- name: Build and push Docker image | |
uses: docker/build-push-action@v5 | |
with: | |
context: . | |
platforms: linux/amd64,linux/arm64 | |
push: true | |
provenance: false | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
target: ${{ matrix.target }} | |
docker-build-clients: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
needs: | |
- docker-build | |
- version | |
strategy: | |
matrix: | |
target: [ "postgres", "mysql" ] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Log in to the Container registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Extract metadata (tags, labels) for Docker | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-${{ matrix.target }} | |
# Configure a tag of type `raw`, so we have no constraints on the format, | |
# as our Dependabot builds do not follow SemVer when creating their tags. | |
# See: https://github.com/marketplace/actions/docker-metadata-action#typeraw. | |
# Note that builds triggered by Dependabot can also run from `main`, so our | |
# check if we run on `main` is no longer enough to alone determine which | |
# tags to publish. We add a second condition to check which event triggered | |
# this build, when we see `workflow_run` we treat it always as a branch build | |
# even if triggered on `main`. | |
tags: | | |
# Push `latest` when on the default branch, but not when triggered | |
# via Dependabot. | |
type=raw,value=latest,enable=${{ (github.ref_name == github.event.repository.default_branch) && (github.event_name != 'workflow_run') }} | |
# Push version without branch suffix when on the default branch, or | |
# when triggered via Dependabot. The tag is then already unique, so | |
# no need for another suffix. | |
type=raw,value=${{ needs.version.outputs.version }},enable=${{ (github.ref_name == github.event.repository.default_branch) || (github.event_name == 'workflow_run') }} | |
# Push the version with branch suffix otherwise. | |
type=raw,value=${{ needs.version.outputs.version }}-{{branch}},enable=${{ (github.ref_name != github.event.repository.default_branch) && (github.event_name != 'workflow_run') }} | |
- name: Build and push Docker image | |
uses: docker/build-push-action@v5 | |
with: | |
context: ./clients/${{ matrix.target }} | |
platforms: linux/amd64,linux/arm64 | |
build-args: VERSION=${{ needs.version.outputs.version }}${{ fromJSON(format('["-{0}",""]', github.ref_name))[github.ref_name == github.event.repository.default_branch] }} | |
push: true | |
provenance: false | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
release: | |
runs-on: ubuntu-latest | |
# Semantic-release need the following permissions: | |
# - content:write in order to create releases | |
# - issues:write in order to post issue comments and add labels | |
# - pull_requests:write to post PR comments and add labels | |
# see: https://github.com/semantic-release/semantic-release/issues/2469#issuecomment-1158013884 | |
permissions: | |
contents: write | |
issues: write | |
pull-requests: write | |
needs: | |
- docker-build-clients | |
if: github.ref_name == github.event.repository.default_branch | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
persist-credentials: false | |
- name: Setup Node.js | |
uses: actions/setup-node@v4 | |
with: | |
node-version: "lts/*" | |
- name: Install dependencies | |
run: | | |
npm i -g \ | |
semantic-release \ | |
@semantic-release/changelog \ | |
@semantic-release/exec \ | |
@semantic-release/git \ | |
conventional-changelog-conventionalcommits | |
- name: Release new version | |
run: semantic-release | |
env: | |
GITHUB_TOKEN: ${{ secrets.FOUNDA_DEV_PAT }} | |
GIT_AUTHOR_NAME: "Founda Automation" | |
GIT_AUTHOR_EMAIL: "[email protected]" | |
GIT_COMMITTER_NAME: "Founda Automation" | |
GIT_COMMITTER_EMAIL: "[email protected]" |