diff --git a/.woodpecker/build.yaml b/.woodpecker/build.yaml new file mode 100644 index 0000000..ae310ad --- /dev/null +++ b/.woodpecker/build.yaml @@ -0,0 +1,108 @@ + + +variables: + - &golang_image 'golang:1.20-alpine' + - &goproxy_override '' + - &goproxy_setup |- + if [ -n "$${GOPROXY_OVERRIDE:-}" ]; then + export GOPROXY="$${GOPROXY_OVERRIDE}"; + echo "Using goproxy from goproxy_override \"$${GOPROXY}\""; + elif [ -n "$${GOPROXY_DEFAULT:-}" ]; then + export GOPROXY="$${GOPROXY_DEFAULT}"; + echo "Using goproxy from goproxy_default (secret) not displaying"; + else + export GOPROXY="https://proxy.golang.org,direct"; + echo "No goproxy overrides or defaults given, using \"$${GOPROXY}\""; + fi + - &buildx_image 'woodpeckerci/plugin-docker-buildx:2.2.1' + - &platforms 'linux/amd64' + +workspace: + base: /go + path: go-import-redirector + +steps: + deps: + image: *golang_image + pull: true + environment: + GOPROXY_OVERRIDE: *goproxy_override + secrets: + - goproxy_default + commands: + - *goproxy_setup + - make vendor + - make checks + - make lint + + build: + image: *golang_image + environment: + GOPROXY_OVERRIDE: *goproxy_override + secrets: + - goproxy_default + commands: + - *goproxy_setup + - make release + - make dockerize + + build-docker-next: + image: *buildx_image + pull: true + settings: + platforms: *platforms + dockerfile: Dockerfile + context: dist/docker/ + registry: + from_secret: registry_domain + repo: + from_secret: target_image_name + password: + from_secret: registry_token + username: + from_secret: registry_user + auto_tag: true + tag: [next, "next-${CI_COMMIT_SHA:0:8}"] + when: + branch: ${CI_REPO_DEFAULT_BRANCH} + event: push + + build-docker-branch: + image: *buildx_image + pull: true + settings: + platforms: *platforms + dockerfile: Dockerfile + context: dist/docker/ + registry: + from_secret: registry_domain + repo: + from_secret: target_image_name + password: + from_secret: registry_token + username: + from_secret: registry_user + auto_tag: true + tag: ["${CI_COMMIT_BRANCH}", "${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:8}"] + when: + event: [push, manual] + + build-docker-tag: + image: *buildx_image + pull: true + settings: + platforms: *platforms + dockerfile: Dockerfile + context: dist/docker/ + registry: + from_secret: registry_domain + repo: + from_secret: target_image_name + password: + from_secret: registry_token + username: + from_secret: registry_user + auto_tag: true + tag: [latest, "${CI_COMMIT_TAG}", "tag-${CI_COMMIT_SHA:0:8}"] + when: + event: [tag] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..45696e1 --- /dev/null +++ b/Makefile @@ -0,0 +1,176 @@ +GO_PACKAGE ?= git.kle.li/tools/go-import-redirector +BINARY_BASE_NAME ?= $(shell echo ${GO_PACKAGE} | rev | cut -d'/' -f1 | rev) + +DIST := dist +DIST_BIN_DIR := $(DIST)/binaries +DIST_RELEASE_DIR := $(DIST)/release +DIST_DOCKER_DIR := $(DIST)/docker +DIST_DIRS := $(DIST_BIN_DIR) $(DIST_RELEASE_DIR) $(DIST_DOCKER_DIR) + +# Tool packages +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@latest +XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest +GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest +GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 + +# Allow overriding the go binary +GO ?= go + +SHASUM ?= shasum -a 256 + +# Construct the version strings + +# VERSION default to dev or in CI next +ifneq ($(CI),) + # in CI + VERSION ?= next +else + # not in CI + VERSION ?= dev +endif + +# VERSION_NUMBER semver compliant without the v prefix +VERSION_NUMBER ?= 0.0.0 + +# Use CI_COMMIT_TAG from CI if set as version and version number +ifneq ($(CI_COMMIT_TAG),) + VERSION := $(CI_COMMIT_TAG:v%=%) + VERSION_NUMBER := ${VERSION} +endif + +# Use CI provided SHA, else use git +ifneq ($(CI_COMMIT_SHA),) + SOURCE_SHA := $(CI_COMMIT_SHA) +endif + +SOURCE_SHA ?= $(shell git rev-parse HEAD) +SOURCE_SHA_SHORT := $(shell echo ${SOURCE_SHA} | head -c 8) + +# VERSIONED_BINARY is the base output name for xgo +VERSIONED_BINARY := $(BINARY_BASE_NAME)-$(VERSION) + +# https://docs.gitlab.com/ee/ci/variables/predefined_variables.html +# https://woodpecker-ci.org/docs/next/usage/environment +# gl GITLAB_CI CI CI_COMMIT_TAG CI_DEFAULT_BRANCH CI_COMMIT_SHA CI_COMMIT_SHORT_SHA CI_MERGE_REQUEST_IID CI_PIPELINE_SOURCE +# WP CI=woodpecker CI_COMMIT_TAG CI_REPO_DEFAULT_BRANCH CI_COMMIT_SHA CI_COMMIT_PULL_REQUEST + +# Default LDFlags, stripping, dwarfing, statically linking and adding the version and commit to pkg/meta, extendable via LDFLAGS +LDFLAGS := $(LDFLAGS) -s -w -X ${GO_PACKAGE}/pkg/meta.version=${VERSION} -X ${GO_PACKAGE}/pkg/meta.commit=${SOURCE_SHA} +# Disable cgo, but overridable +CGO_ENABLED ?= 0 + +HAS_GO = $(shell hash go > /dev/null 2>&1 && echo "GO" || echo "NOGO" ) +ifeq ($(HAS_GO),GO) + GOPATH ?= $(shell $(GO) env GOPATH) + export PATH := $(GOPATH)/bin:$(PATH) + CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS) +endif + +GOFLAGS := -v -trimpath +EXECUTABLE ?= $(BINARY_BASE_NAME) + +# Release packagin stuffs... +STORED_VERSION_FILE := VERSION +TAR_EXCLUDES := .git $(EXECUTABLE) $(DIST) + +# just print the help instead of running any builds... +all: help + +##@ Prerequisites + +.PHONY: go-check +go-check: ## Check Go version >= go.mod version + $(eval MIN_GO_VERSION_STR := $(shell grep -Eo '^go\s+[0-9]+\.[0-9]+' go.mod | cut -d' ' -f2)) + $(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' '))) + $(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');)) + @if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \ + echo "This project requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \ + exit 1; \ + fi + +##@ Convention Checking + +.PHONY: checks ## Run all checks +checks: tidy-check security-check + +.PHONY: tidy-check +tidy-check: tidy ## Check that mods have been cleaned up before checking in + @diff=$$(git diff --color=always go.mod go.sum); \ + if [ -n "$$diff" ]; then \ + echo "Please run 'make tidy' and commit the result:"; \ + echo "$${diff}"; \ + exit 1; \ + fi + +.PHONY: security-check +security-check: + go run $(GOVULNCHECK_PACKAGE) ./... + +##@ Linting + +.PHONY: lint +lint: ## Lint code + @echo "Running golangci-lint" + go run $(GOLANGCI_LINT_PACKAGE) run --timeout 10m + +##@ Others + +# Help prints all targets (identified by ##) and categories (identified by ##@) +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +.PHONY: clean +clean: ## Cleanup + $(GO) clean -i ./... + rm -rf $(EXECUTABLE) $(DIST) vendor + +.PHONY: tidy +tidy: ## Tidy mods + $(eval MIN_GO_VERSION := $(shell grep -Eo '^go\s+[0-9]+\.[0-9.]+' go.mod | cut -d' ' -f2)) + $(GO) mod tidy -compat=$(MIN_GO_VERSION) + +vendor: go.mod go.sum ## Download mods to vendor + $(GO) mod vendor + @touch vendor + +.PHONY: build +build: go-check build-linux ## Build the binary matching the local system + +$(DIST_DIRS): + mkdir -p $(DIST_DIRS) + +.PHONY: build-linux +build-linux: | $(DIST_DIRS) + CGO_ENABLED="$(CGO_ENABLED)" CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) -tags 'netgo osusergo tzdata $(TAGS)' -ldflags '$(LDFLAGS)' -o $(DIST_BIN_DIR)/$(VERSIONED_BINARY) + +.PHONY: release-copy +release-copy: | $(DIST_DIRS) + cd $(DIST); for file in `find . -type f -name "*"`; do cp $${file} ./release/; done; + +.PHONY: release-check +release-check: | $(DIST_DIRS) + cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done; + +.PHONY: release-compress +release-compress: | $(DIST_DIRS) + cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && $(GO) run $(GXZ_PAGAGE) -k -9 $${file}; done; + +.PHONY: release-sources +release-sources: | $(DIST_DIRS) + echo $(VERSION) > $(STORED_VERSION_FILE) +# bsdtar needs a ^ to prevent matching subdirectories + $(eval EXCL := --exclude=$(shell tar --help | grep -q bsdtar && echo "^")./) +# use transform to a add a release-folder prefix; in bsdtar the transform parameter equivalent is -s + $(eval TRANSFORM := $(shell tar --help | grep -q bsdtar && echo "-s '/^./$(BINARY_BASE_NAME)-src-$(VERSION)/'" || echo "--transform 's|^./|$(BINARY_BASE_NAME)-src-$(VERSION)/|'")) + tar $(addprefix $(EXCL),$(TAR_EXCLUDES)) $(TRANSFORM) -czf $(DIST)/release/$(BINARY_BASE_NAME)-src-$(VERSION).tar.gz . + rm -f $(STORED_VERSION_FILE) + +.PHONY: release ## Prepare a full release +release: build-linux release-copy release-compress vendor release-sources release-check + +.PHONY: dockerize +dockerize: | $(DIST_DIRS) + cp -R docker/fscopy/* $(DIST_DOCKER_DIR)/ + cp $(DIST_BIN_DIR)/$(VERSIONED_BINARY) $(DIST_DOCKER_DIR)/bin/$(BINARY_BASE_NAME) + docker/make_dockerfile.sh > $(DIST_DOCKER_DIR)/Dockerfile diff --git a/docker/fscopy/etc/group b/docker/fscopy/etc/group new file mode 100644 index 0000000..592e811 --- /dev/null +++ b/docker/fscopy/etc/group @@ -0,0 +1 @@ +root:x:0:randomuser diff --git a/docker/fscopy/etc/passwd b/docker/fscopy/etc/passwd new file mode 100644 index 0000000..7f4372f --- /dev/null +++ b/docker/fscopy/etc/passwd @@ -0,0 +1 @@ +randomuser:x:1000:0:randomuser:/home/randomuser:/bin/false diff --git a/docker/make_dockerfile.sh b/docker/make_dockerfile.sh new file mode 100755 index 0000000..bec6e35 --- /dev/null +++ b/docker/make_dockerfile.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +cat <