From cca120d1c0d12dbba15966d8cee4cde60c6f643e Mon Sep 17 00:00:00 2001 From: "Felipe M." Date: Tue, 7 Apr 2026 18:08:21 +0200 Subject: [PATCH 1/2] ci: migrate from Woodpecker to Forgejo Actions and simplify dev tooling Switch CI pipelines to GitHub/Forgejo Actions using ci-base container image, simplify Makefile by removing tools/bin versioned-symlink pattern, update Containerfile with multi-stage build for CA certs and non-root user, and clean up GoReleaser config with ldflags and explicit release target. --- .github/workflows/ci.yml | 58 +++++++++++++++ .github/workflows/release.yml | 30 ++++++++ .goreleaser.yml | 32 +++----- .woodpecker/ci.yml | 26 ------- .woodpecker/release.yml | 22 ------ Containerfile | 24 ++++-- Makefile | 136 +++++++++------------------------- 7 files changed, 156 insertions(+), 172 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml delete mode 100644 .woodpecker/ci.yml delete mode 100644 .woodpecker/release.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9e13b63 --- /dev/null +++ b/.github/workflows/ci.yml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1f41606 --- /dev/null +++ b/.github/workflows/release.yml @@ -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 }} diff --git a/.goreleaser.yml b/.goreleaser.yml index 5c311a6..23e0421 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -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 @@ -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 diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml deleted file mode 100644 index b1ecb4d..0000000 --- a/.woodpecker/ci.yml +++ /dev/null @@ -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 diff --git a/.woodpecker/release.yml b/.woodpecker/release.yml deleted file mode 100644 index 608061a..0000000 --- a/.woodpecker/release.yml +++ /dev/null @@ -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 diff --git a/Containerfile b/Containerfile index e74285c..4472a6e 100644 --- a/Containerfile +++ b/Containerfile @@ -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 " +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"] diff --git a/Makefile b/Makefile index 4d17b22..879fad3 100644 --- a/Makefile +++ b/Makefile @@ -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 " -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 -- 2.52.0 From e1b48724efaffff81df6c145faf493d2b053de80 Mon Sep 17 00:00:00 2001 From: "Felipe M." Date: Tue, 7 Apr 2026 18:11:22 +0200 Subject: [PATCH 2/2] ci: trigger pipeline -- 2.52.0