mirror of
https://github.com/ivuorinen/actions.git
synced 2026-03-02 08:53:49 +00:00
* fix(deps): replace step-security/retry with nick-fields/retry * chore(deps): update github action sha pins via pinact * refactor: remove common-retry references from tests and validators * chore: simplify description fallback and update action count * docs: remove hardcoded test counts from memory and docs Replace exact "769 tests" references with qualitative language so these files don't go stale as test count grows.
263 lines
8.6 KiB
YAML
263 lines
8.6 KiB
YAML
# yaml-language-server: $schema=https://json.schemastore.org/github-action.json
|
|
# permissions:
|
|
# - contents: read # Required for checking out repository
|
|
---
|
|
name: Go Build
|
|
description: 'Builds the Go project.'
|
|
author: 'Ismo Vuorinen'
|
|
|
|
branding:
|
|
icon: package
|
|
color: blue
|
|
|
|
inputs:
|
|
go-version:
|
|
description: 'Go version to use.'
|
|
required: false
|
|
destination:
|
|
description: 'Build destination directory.'
|
|
required: false
|
|
default: './bin'
|
|
max-retries:
|
|
description: 'Maximum number of retry attempts for go mod download operations'
|
|
required: false
|
|
default: '3'
|
|
token:
|
|
description: 'GitHub token for authentication'
|
|
required: false
|
|
default: ''
|
|
|
|
outputs:
|
|
build_status:
|
|
description: 'Build completion status (success/failure)'
|
|
value: ${{ steps.build.outputs.status }}
|
|
test_status:
|
|
description: 'Test execution status (success/failure/skipped)'
|
|
value: ${{ steps.test.outputs.status }}
|
|
go_version:
|
|
description: 'Version of Go used'
|
|
value: ${{ steps.detect-go-version.outputs.detected-version }}
|
|
binary_path:
|
|
description: 'Path to built binaries'
|
|
value: ${{ inputs.destination }}
|
|
coverage_path:
|
|
description: 'Path to coverage report'
|
|
value: 'coverage.out'
|
|
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Checkout Repository
|
|
uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta
|
|
with:
|
|
token: ${{ inputs.token || github.token }}
|
|
|
|
- name: Detect Go Version
|
|
id: detect-go-version
|
|
shell: sh
|
|
env:
|
|
DEFAULT_VERSION: "${{ inputs.go-version || '1.24' }}"
|
|
run: |
|
|
set -eu
|
|
|
|
# Function to validate version format
|
|
validate_version() {
|
|
version=$1
|
|
case "$version" in
|
|
[0-9]*\.[0-9]* | [0-9]*\.[0-9]*\.[0-9]*)
|
|
return 0
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Function to clean version string
|
|
clean_version() {
|
|
printf '%s' "$1" | sed 's/^[vV]//' | tr -d ' \n\r'
|
|
}
|
|
|
|
detected_version=""
|
|
|
|
# Parse .tool-versions file
|
|
if [ -f .tool-versions ]; then
|
|
echo "Checking .tool-versions for golang..." >&2
|
|
version=$(awk '/^golang[[:space:]]/ {gsub(/#.*/, ""); print $2; exit}' .tool-versions 2>/dev/null || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found Go version in .tool-versions: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Parse Dockerfile
|
|
if [ -z "$detected_version" ] && [ -f Dockerfile ]; then
|
|
echo "Checking Dockerfile for golang..." >&2
|
|
version=$(grep -iF "FROM" Dockerfile | grep -F "golang:" | head -1 | \
|
|
sed -n -E "s/.*golang:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found Go version in Dockerfile: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Parse devcontainer.json
|
|
if [ -z "$detected_version" ] && [ -f .devcontainer/devcontainer.json ]; then
|
|
echo "Checking devcontainer.json for golang..." >&2
|
|
if command -v jq >/dev/null 2>&1; then
|
|
version=$(jq -r '.image // empty' .devcontainer/devcontainer.json 2>/dev/null | sed -n -E "s/.*golang:([0-9]+(\.[0-9]+)*)(-[^:]*)?. */\1/p" || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found Go version in devcontainer: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Parse .go-version file
|
|
if [ -z "$detected_version" ] && [ -f .go-version ]; then
|
|
echo "Checking .go-version..." >&2
|
|
version=$(tr -d '\r' < .go-version | head -1)
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found Go version in .go-version: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Parse go.mod
|
|
if [ -z "$detected_version" ] && [ -f go.mod ]; then
|
|
echo "Checking go.mod..." >&2
|
|
version=$(grep -E '^go[[:space:]]+[0-9]' go.mod | awk '{print $2}' | head -1 || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found Go version in go.mod: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Use default version if nothing detected
|
|
if [ -z "$detected_version" ]; then
|
|
detected_version="$DEFAULT_VERSION"
|
|
echo "Using default Go version: $detected_version" >&2
|
|
fi
|
|
|
|
# Set output
|
|
printf 'detected-version=%s\n' "$detected_version" >> "$GITHUB_OUTPUT"
|
|
echo "Final detected Go version: $detected_version" >&2
|
|
|
|
- name: Setup Go
|
|
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
|
with:
|
|
go-version: ${{ steps.detect-go-version.outputs.detected-version }}
|
|
cache: true
|
|
|
|
- name: Download Dependencies
|
|
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
|
|
with:
|
|
timeout_minutes: 10
|
|
max_attempts: ${{ inputs.max-retries }}
|
|
command: |
|
|
echo "Downloading Go dependencies..."
|
|
go mod download
|
|
go mod verify
|
|
|
|
- name: Build Go Project
|
|
id: build
|
|
shell: sh
|
|
env:
|
|
DESTINATION: ${{ inputs.destination }}
|
|
run: |
|
|
set -eu
|
|
echo "Building Go project..."
|
|
|
|
# Create destination directory
|
|
mkdir -p "$DESTINATION"
|
|
|
|
build_success=true
|
|
# Check if there are any main packages
|
|
if find . -name "*.go" -exec grep -l "package main" {} \; | head -1 | grep -q .; then
|
|
# Build all main packages
|
|
find . -name "*.go" -exec grep -l "package main" {} \; | xargs dirname | sort -u | while IFS= read -r main_dir; do
|
|
echo "Building package in $main_dir..."
|
|
output_name=$(basename -- "$main_dir")
|
|
if ! go build -ldflags="-s -w" -o "$DESTINATION/$output_name" "$main_dir"; then
|
|
build_success=false
|
|
fi
|
|
done
|
|
else
|
|
echo "No main packages found, building library..."
|
|
if ! go build ./...; then
|
|
build_success=false
|
|
fi
|
|
fi
|
|
|
|
if [ "$build_success" = true ]; then
|
|
echo "status=success" >> "$GITHUB_OUTPUT"
|
|
echo "Build completed successfully"
|
|
else
|
|
echo "status=failure" >> "$GITHUB_OUTPUT"
|
|
echo "Build failed"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Run Tests
|
|
id: test
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
echo "Running Go tests..."
|
|
if find . -name "*_test.go" | grep -q .; then
|
|
# Check if race detector is supported on this platform
|
|
# The race detector is only supported on specific GOOS/GOARCH combinations:
|
|
# linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64,
|
|
# freebsd/amd64, netbsd/amd64
|
|
RACE_FLAG=""
|
|
GOOS=$(go env GOOS)
|
|
GOARCH=$(go env GOARCH)
|
|
|
|
case "${GOOS}/${GOARCH}" in
|
|
linux/amd64|linux/arm64|darwin/amd64|darwin/arm64|windows/amd64|freebsd/amd64|netbsd/amd64)
|
|
RACE_FLAG="-race"
|
|
echo "Race detector enabled for ${GOOS}/${GOARCH}"
|
|
;;
|
|
*)
|
|
echo "Race detector not supported on ${GOOS}/${GOARCH}, skipping -race flag"
|
|
;;
|
|
esac
|
|
|
|
if go test -v ./... $RACE_FLAG -coverprofile=coverage.out; then
|
|
echo "status=success" >> "$GITHUB_OUTPUT"
|
|
echo "Tests completed successfully"
|
|
else
|
|
echo "status=failure" >> "$GITHUB_OUTPUT"
|
|
echo "Tests failed"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "No test files found, skipping test execution."
|
|
echo "status=skipped" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Upload Build Artifacts
|
|
if: always()
|
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
|
with:
|
|
name: go-build-artifacts
|
|
path: |
|
|
${{ inputs.destination }}/*
|
|
coverage.out
|
|
if-no-files-found: ignore
|