ci: migrate from Woodpecker to Forgejo Actions and simplify dev tooling #6

Merged
fmartingr merged 2 commits from feat/forgejo-actions into main 2026-04-07 18:22:05 +02:00
7 changed files with 156 additions and 172 deletions

58
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,58 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
format:
runs-on: docker
container: git.nakama.town/fmartingr/ci-images/ci-base:1.0.0
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: go.mod
- run: make format
- run: git diff --exit-code
goreleaser-lint:
runs-on: docker
container: git.nakama.town/fmartingr/ci-images/ci-base:1.0.0
steps:
- uses: actions/checkout@v6
- uses: actions/goreleaser-action@v6.4.0
with:
args: check
lint:
runs-on: docker
container: git.nakama.town/fmartingr/ci-images/ci-base:1.0.0
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: go.mod
- run: make ci-lint
test:
runs-on: docker
container: git.nakama.town/fmartingr/ci-images/ci-base:1.0.0
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: go.mod
- run: make test
build:
runs-on: docker
container: git.nakama.town/fmartingr/ci-images/ci-base:1.0.0
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version-file: go.mod
- run: make build

30
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,30 @@
name: Release
on:
push:
tags: ["v*"]
jobs:
release:
runs-on: docker
container: git.nakama.town/fmartingr/ci-images/ci-base:1.0.0
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Login to container registry
run: echo "${{ secrets.FORGEJO_TOKEN }}" | docker login git.nakama.town -u ${{ github.actor }} --password-stdin
- name: Run GoReleaser
uses: actions/goreleaser-action@v6.4.0
with:
args: release --clean
env:
GORELEASER_FORCE_TOKEN: gitea
GITEA_TOKEN: ${{ secrets.FORGEJO_TOKEN }}

View file

@ -1,29 +1,18 @@
version: 2
gitea_urls:
api: https://git.nakama.town/api/v1
download: https://git.nakama.town
project_name: smtp2shoutrrr
before:
hooks:
- go mod tidy
gomod:
proxy: true
env:
- GOPROXY=https://proxy.golang.org,direct
- GOSUMDB=sum.golang.org
git:
ignore_tags:
- "{{ if not .IsNightly }}*-rc*{{ end }}"
builds:
- binary: smtp2shoutrrr
main: ./cmd/smtp2shoutrrr
env:
- CGO_ENABLED=0
- GIN_MODE=release
ldflags:
- -s -w
tags:
- netgo
- osusergo
@ -67,8 +56,7 @@ dockers_v2:
- linux/arm/v7
tags:
- "{{ .Version }}"
# Uncomment to enable latest tag:
# - latest
- latest
nfpms:
- maintainer: Felipe Martin <me@fmartingr.com>
@ -89,10 +77,7 @@ upx:
goarm: ["7"]
checksum:
name_template: 'checksums.txt'
snapshot:
version_template: "{{ incpatch .Version }}-next"
name_template: checksums.txt
changelog:
sort: asc
@ -126,4 +111,11 @@ changelog:
- "^chore\\(deps\\):"
release:
gitea:
owner: fmartingr
name: smtp2shoutrrr
prerelease: auto
gitea_urls:
api: https://git.nakama.town/api/v1
download: https://git.nakama.town

View file

@ -1,26 +0,0 @@
variables:
- &golang_image 'golang:1.25.6'
when:
event:
- push
- pull_request
branch:
- main
steps:
format:
image: *golang_image
commands:
- make format
- git diff --exit-code # Fail if files were changed
lint:
image: *golang_image
commands:
- make lint
test:
image: *golang_image
commands:
- make test

View file

@ -1,22 +0,0 @@
variables:
- &golang_image 'golang:1.25.6-alpine'
when:
- event: tag
branch: main
steps:
- name: Release
image: *golang_image
environment:
GITEA_TOKEN:
from_secret: GITEA_TOKEN
DOCKER_HOST: unix:///var/run/docker.sock
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
commands:
- apk add --no-cache docker-cli docker-cli-buildx git make
- docker buildx create --use --name container-builder --driver docker-container
- make install-tool-goreleaser
- docker login -u fmartingr -p $GITEA_TOKEN git.nakama.town
- tools/bin/goreleaser release --clean

View file

@ -1,7 +1,21 @@
# This file is used directly by the goreleaser build
# It is used to build the final container image
# Build dependencies on native arch (no QEMU needed)
FROM --platform=$BUILDPLATFORM alpine:3.20 AS base
RUN apk add --no-cache ca-certificates tzdata
RUN addgroup -g 1000 smtp2shoutrrr && adduser -u 1000 -G smtp2shoutrrr -s /bin/sh -D smtp2shoutrrr
# Runtime image
FROM scratch
LABEL maintainer="Felipe Martin <me@fmartingr.com>"
LABEL org.opencontainers.image.source="https://git.nakama.town/fmartingr/smtp2shoutrrr"
ARG TARGETPLATFORM
WORKDIR /
COPY $TARGETPLATFORM/smtp2shoutrrr /usr/bin/smtp2shoutrrr
ENTRYPOINT ["/usr/bin/smtp2shoutrrr"]
COPY --from=base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=base /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=base /etc/passwd /etc/passwd
COPY --from=base /etc/group /etc/group
COPY $TARGETPLATFORM/smtp2shoutrrr /usr/local/bin/smtp2shoutrrr
USER smtp2shoutrrr
ENTRYPOINT ["/usr/local/bin/smtp2shoutrrr"]

136
Makefile
View file

@ -1,119 +1,57 @@
PROJECT_NAME := smtp2shoutrrr
SOURCE_FILES ?=./...
TEST_OPTIONS ?= -v -failfast -race -bench=. -benchtime=100000x -cover -coverprofile=coverage.out
TEST_TIMEOUT ?=1m
GOLANGCI_LINT_VERSION ?= v2.8.0
GORELEASER_VERSION ?= v2.13.3
TOOLS_BIN := tools/bin
CLEAN_OPTIONS ?=-modcache -testcache
CGO_ENABLED := 0
BUILDS_PATH := ./dist
FROM_MAKEFILE := y
DIST_PATH := ./dist
TEST_OPTIONS := -v -failfast -race -bench=. -benchtime=100000x -cover -coverprofile=coverage.out
CONTAINERFILE_NAME := Containerfile
CONTAINER_ALPINE_VERSION := 3.20
CONTAINER_SOURCE_URL := "https://git.nakama.town/fmartingr/${PROJECT_NAME}"
CONTAINER_MAINTAINER := "Felipe Martin <me@fmartingr.com>"
CONTAINER_BIN_NAME := ${PROJECT_NAME}
GOLANGCI_LINT_VERSION := v2.8.0
BUILDX_PLATFORMS := linux/amd64,linux/arm64,linux/arm/v7
.DEFAULT_GOAL := help
export PROJECT_NAME
export FROM_MAKEFILE
export CGO_ENABLED
export SOURCE_FILES
export TEST_OPTIONS
export TEST_TIMEOUT
export BUILDS_PATH
export CONTAINERFILE_NAME
export CONTAINER_ALPINE_VERSION
export CONTAINER_SOURCE_URL
export CONTAINER_MAINTAINER
export CONTAINER_BIN_NAME
export BUILDX_PLATFORMS
.PHONY: all
all: help
# this is godly
# https://news.ycombinator.com/item?id=11939200
## help: Display this help message
.PHONY: help
help: ### this screen. Keep it first target to be default
ifeq ($(UNAME), Linux)
@grep -P '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
else
@# this is not tested, but prepared in advance for you, Mac drivers
@awk -F ':.*###' '$$0 ~ FS {printf "%15s%s\n", $$1 ":", $$2}' \
$(MAKEFILE_LIST) | grep -v '@awk' | sort
endif
.PHONY: clean
clean: ### clean test cache, build files
$(info: Make: Clean)
@rm -rf ${BUILDS_PATH}
@go clean ${CLEAN_OPTIONS}
@-docker buildx rm ${PROJECT_NAME}_builder
help:
@echo "Available targets:"
@grep -E '^## ' $(MAKEFILE_LIST) | sed 's/## / /' | sort
## build: Build project using goreleaser (snapshot)
.PHONY: build
build: install-tool-goreleaser clean ### builds the project for the setup os/arch combinations
$(info: Make: Build)
@${TOOLS_BIN}/goreleaser --clean --snapshot
build:
goreleaser build --snapshot --clean
## quick-run: Execute project directly using go run
.PHONY: quick-run
quick-run: ### Executes the project using golang
CGO_ENABLED=${CGO_ENABLED} go run ./cmd/${PROJECT_NAME}/*.go
quick-run:
CGO_ENABLED=$(CGO_ENABLED) go run ./cmd/$(PROJECT_NAME)
## run: Build and execute the local binary
.PHONY: run
run: ### Executes the project build locally
@make build
${BUILDS_PATH}/${PROJECT_NAME}
run: build
$(DIST_PATH)/$(PROJECT_NAME)
## format: Format code and tidy modules
.PHONY: format
format: ### Executes the formatting pipeline on the project
$(info: Make: Format)
@go fmt ./...
@go mod tidy
format:
go fmt ./...
go mod tidy
.PHONY: install-tools
install-tools: install-tool-golangci-lint install-tool-goreleaser
.PHONY: install-tool-golangci-lint
install-tool-golangci-lint: ${TOOLS_BIN}/golangci-lint-${GOLANGCI_LINT_VERSION}
@ln -sf golangci-lint-${GOLANGCI_LINT_VERSION} ${TOOLS_BIN}/golangci-lint
${TOOLS_BIN}/golangci-lint-${GOLANGCI_LINT_VERSION}:
$(info: Installing golangci-lint ${GOLANGCI_LINT_VERSION})
@mkdir -p ${TOOLS_BIN}
@GOBIN=$(CURDIR)/${TOOLS_BIN} go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}
@mv ${TOOLS_BIN}/golangci-lint ${TOOLS_BIN}/golangci-lint-${GOLANGCI_LINT_VERSION}
.PHONY: install-tool-goreleaser
install-tool-goreleaser: ${TOOLS_BIN}/goreleaser-${GORELEASER_VERSION}
@ln -sf goreleaser-${GORELEASER_VERSION} ${TOOLS_BIN}/goreleaser
${TOOLS_BIN}/goreleaser-${GORELEASER_VERSION}:
$(info: Installing goreleaser ${GORELEASER_VERSION})
@mkdir -p ${TOOLS_BIN}
@GOBIN=$(CURDIR)/${TOOLS_BIN} go install github.com/goreleaser/goreleaser/v2@${GORELEASER_VERSION}
@mv ${TOOLS_BIN}/goreleaser ${TOOLS_BIN}/goreleaser-${GORELEASER_VERSION}
## ci-lint: Run golangci-lint (installs if missing)
.PHONY: ci-lint
ci-lint:
@which golangci-lint > /dev/null 2>&1 || go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
golangci-lint run ./...
## lint: Run linters
.PHONY: lint
lint: install-tools ### Check the project for errors
$(info: Make: Lint)
@${TOOLS_BIN}/golangci-lint run ./...
lint: ci-lint
## test: Run tests with coverage
.PHONY: test
test: ### Runs the test suite
$(info: Make: Test)
CGO_ENABLED=1 go test ${TEST_OPTIONS} -timeout=${TEST_TIMEOUT} ${SOURCE_FILES}
test:
CGO_ENABLED=1 go test $(TEST_OPTIONS) -timeout 1m ./...
## clean: Remove build artifacts
.PHONY: clean
clean:
rm -rf $(DIST_PATH)
go clean -cache -testcache