Go CI/CD #63
Workflow file for this run
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
name: Go CI/CD | |
on: | |
push: | |
branches: [ main ] | |
tags: | |
- 'v[0-9]+.[0-9]+.[0-9]+' # Matches v0.1.0, v1.0.0, etc. | |
pull_request: | |
branches: [ main ] | |
permissions: | |
contents: write | |
pull-requests: write | |
jobs: | |
test: | |
name: Test & Lint | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Set up Go | |
uses: actions/setup-go@v4 | |
with: | |
go-version: '1.21' | |
cache: true | |
- name: Install dependencies | |
run: | | |
go mod download | |
go install golang.org/x/tools/cmd/goimports@latest | |
- name: Run tests | |
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./... | |
- name: Run golangci-lint | |
uses: golangci/golangci-lint-action@v3 | |
with: | |
version: latest | |
args: --timeout=5m --out-format=colored-line-number --issues-exit-code=1 | |
only-new-issues: true | |
skip-pkg-cache: true | |
skip-build-cache: false | |
- name: Upload coverage | |
if: success() | |
uses: codecov/codecov-action@v3 | |
with: | |
file: ./coverage.txt | |
fail_ci_if_error: false | |
verbose: true | |
build: | |
name: Build Binary | |
needs: test | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Set up Go | |
uses: actions/setup-go@v4 | |
with: | |
go-version: '1.21' | |
cache: true | |
- name: Build | |
run: | | |
VERSION=$(git describe --tags --always --dirty) | |
mkdir -p hapax | |
go build -v -ldflags="-X main.Version=${VERSION}" -o hapax/hapax . | |
- name: Upload artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: hapax-binary | |
path: ./hapax | |
retention-days: 5 | |
release: | |
name: Create Release | |
needs: [test, build] | |
runs-on: ubuntu-latest | |
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/v') | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Generate changelog | |
id: changelog | |
run: | | |
echo "CHANGELOG<<EOF" >> $GITHUB_ENV | |
# Get tag message for overview | |
TAG_MSG=$(git tag -l --format='%(contents)' $(git describe --tags --abbrev=0)) | |
echo "$TAG_MSG" >> $GITHUB_ENV | |
echo "" >> $GITHUB_ENV | |
# For first release, get all commits | |
if ! git tag --sort=-v:refname | grep -q '^v'; then | |
RANGE="$(git rev-list --max-parents=0 HEAD)..HEAD" | |
else | |
RANGE="$(git describe --tags --abbrev=0 HEAD^)..HEAD" | |
fi | |
echo "## Changes" >> $GITHUB_ENV | |
echo "" >> $GITHUB_ENV | |
# Features | |
echo "### Features" >> $GITHUB_ENV | |
# First maintainer commits without attribution | |
git log $RANGE --pretty=format:'* %s ([%h](https://github.com/teilomillet/hapax/commit/%H))' --author="teilomillet" | grep -i '^* feat' | sed 's/feat: /* /' >> $GITHUB_ENV || true | |
# Then contributor commits with attribution | |
git log $RANGE --pretty=format:'* %s (%aN) ([%h](https://github.com/teilomillet/hapax/commit/%H))' | grep -i '^* feat' | grep -v '(teilomillet)' | sed 's/feat: /* /' >> $GITHUB_ENV || true | |
echo "" >> $GITHUB_ENV | |
# Fixes | |
echo "### Bug Fixes" >> $GITHUB_ENV | |
# Maintainer fixes without attribution | |
git log $RANGE --pretty=format:'* %s ([%h](https://github.com/teilomillet/hapax/commit/%H))' --author="teilomillet" | grep -i '^* fix' | sed 's/fix: /* /' >> $GITHUB_ENV || true | |
# Contributor fixes with attribution | |
git log $RANGE --pretty=format:'* %s (%aN) ([%h](https://github.com/teilomillet/hapax/commit/%H))' | grep -i '^* fix' | grep -v '(teilomillet)' | sed 's/fix: /* /' >> $GITHUB_ENV || true | |
echo "" >> $GITHUB_ENV | |
# Documentation | |
echo "### Documentation" >> $GITHUB_ENV | |
# Maintainer docs without attribution | |
git log $RANGE --pretty=format:'* %s ([%h](https://github.com/teilomillet/hapax/commit/%H))' --author="teilomillet" | grep -i '^* docs' | sed 's/docs: /* /' >> $GITHUB_ENV || true | |
# Contributor docs with attribution | |
git log $RANGE --pretty=format:'* %s (%aN) ([%h](https://github.com/teilomillet/hapax/commit/%H))' | grep -i '^* docs' | grep -v '(teilomillet)' | sed 's/docs: /* /' >> $GITHUB_ENV || true | |
echo "" >> $GITHUB_ENV | |
# Dependencies | |
echo "## Dependency Updates" >> $GITHUB_ENV | |
echo "" >> $GITHUB_ENV | |
if [ -f "go.mod" ]; then | |
echo '```diff' >> $GITHUB_ENV | |
if git rev-parse --verify HEAD^ >/dev/null 2>&1; then | |
git diff HEAD^ HEAD go.mod | grep '^[+-]' | grep -v '^[+-]module' >> $GITHUB_ENV || true | |
fi | |
echo '```' >> $GITHUB_ENV | |
fi | |
echo "" >> $GITHUB_ENV | |
# List contributors (excluding maintainer) | |
echo "## Contributors" >> $GITHUB_ENV | |
git log $RANGE --format='%aN' | sort -u | grep -v 'teilomillet' | while read name; do | |
echo "* @$name" >> $GITHUB_ENV | |
done | |
echo "EOF" >> $GITHUB_ENV | |
- name: Download binary | |
uses: actions/download-artifact@v4 | |
with: | |
name: hapax-binary | |
path: ./ | |
- name: Create Release | |
uses: softprops/action-gh-release@v1 | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
with: | |
body: ${{ env.CHANGELOG }} | |
files: ./hapax/hapax | |
draft: false | |
prerelease: false | |
generate_release_notes: false |