Skip to content

Go

Go #308

Workflow file for this run

# 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/staticcheck-action@v1.3.1
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: "automation@founda.dev"
GIT_COMMITTER_NAME: "Founda Automation"
GIT_COMMITTER_EMAIL: "automation@founda.dev"
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: "automation@founda.dev"
GIT_COMMITTER_NAME: "Founda Automation"
GIT_COMMITTER_EMAIL: "automation@founda.dev"