diff --git a/.github/workflows/cicd.yaml b/.github/workflows/cicd.yaml new file mode 100644 index 0000000..594aad5 --- /dev/null +++ b/.github/workflows/cicd.yaml @@ -0,0 +1,38 @@ +name: ci/cd + +on: + push: + branches: [ master ] + pull_request: + +jobs: + # CI is run on pull requests and pushes to master (i.e merging PRs) + ci: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: ./bin/make ci + + # Release is run only on pushes to master (i.e. merging PRs) + release: + runs-on: ubuntu-latest + needs: [ ci ] + if: github.event_name == 'push' + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: ./bin/make release + + # Send failure notification to slack if push to master job fails + howl-on-fail: + runs-on: ubuntu-latest + needs: [ ci, release ] + if: failure() && github.event_name == 'push' + steps: + - uses: foxygoat/howl@v1 + env: + SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} + SLACK_TEXT: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a3417b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/out/ diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..ead7e4a --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,38 @@ +issues: + exclude-use-default: false + exclude: + - "^don't use ALL_CAPS" + - "^ST1003: should not use ALL_CAPS" + - "^G304: Potential file inclusion via variable" + +linters: + enable-all: true + disable: + - cyclop + - depguard + - execinquery + - exhaustive + - exhaustruct + - forbidigo + - forcetypeassert + - funlen + - gochecknoglobals + - gocognit + - goconst + - gocyclo + - godox + - gomnd + - ireturn + - lll + - nlreturn + - nonamedreturns + - paralleltest + - revive + - rowserrcheck + - sqlclosecheck + - tagalign + - testpackage + - varnamelen + - wastedassign + - wrapcheck + - wsl diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..91bbfb6 --- /dev/null +++ b/Makefile @@ -0,0 +1,126 @@ +# Run `make help` to display help +.DEFAULT_GOAL := help + +# --- Global ------------------------------------------------------------------- +O = out +COVERAGE = 0 +VERSION ?= $(shell git describe --tags --dirty --always) + +## Build and lint +all: build lint + @if [ -e .git/rebase-merge ]; then git --no-pager log -1 --pretty='%h %s'; fi + @echo '$(COLOUR_GREEN)Success$(COLOUR_NORMAL)' + +## Full clean build and up-to-date checks as run on CI +ci: clean check-uptodate all + +check-uptodate: tidy + test -z "$$(git status --porcelain -- go.mod go.sum)" || { git status; false; } + +## Remove generated files +clean:: + -rm -rf $(O) + +.PHONY: all check-uptodate ci clean + +# --- Build -------------------------------------------------------------------- +GO_TAGS = +GO_LDFLAGS = -X main.version=$(VERSION) +GO_FLAGS += $(if $(GO_TAGS),-tags='$(GO_TAGS)') +GO_FLAGS += $(if $(GO_LDFLAGS),-ldflags='$(GO_LDFLAGS)') +GO_BIN_NAME = git-credential-fdoss$(if $(GOOS),_$(GOOS))$(if $(GOARCH),_$(GOARCH)) + +## Build git-credential-fdoss binary +build: | $(O) + go build -o $(O)/$(GO_BIN_NAME) $(GO_FLAGS) . + +## Build and install binaries in $GOBIN +install: + go install $(GO_FLAGS) . + +## Tidy go modules with "go mod tidy" +tidy: + go mod tidy + +clean:: + +.PHONY: build install tidy + +# --- Lint --------------------------------------------------------------------- +## Lint go source code +lint: + golangci-lint run + +.PHONY: lint + +# --- Release ------------------------------------------------------------------- +RELEASE_DIR = $(O)/release + +## Tag and release binaries for different OS on GitHub release +release: tag-release .WAIT build-release .WAIT publish-release + +tag-release: nexttag + git tag $(RELEASE_TAG) + git push origin $(RELEASE_TAG) + +build-release: + $(MAKE) build GOOS=linux GOARCH=amd64 O=$(RELEASE_DIR) + $(MAKE) build GOOS=linux GOARCH=arm64 O=$(RELEASE_DIR) + $(MAKE) build GOOS=linux GOARCH=arm O=$(RELEASE_DIR) + $(MAKE) build GOOS=linux GOARCH=386 O=$(RELEASE_DIR) + +publish-release: + gh release create $(RELEASE_TAG) --generate-notes $(RELEASE_DIR)/* + +nexttag: + $(if $(RELEASE_TAG),,$(eval RELEASE_TAG := $(shell $(NEXTTAG_CMD)))) + +.PHONY: build-release nexttag publish-release release tag-release + +define NEXTTAG_CMD +{ git tag --list --merged HEAD --sort=-v:refname; echo v0.0.0; } +| grep -E "^v?[0-9]+.[0-9]+.[0-9]+$$" +| head -n1 +| awk -F . '{ print $$1 "." $$2 "." $$3 + 1 }' +endef + +# --- Utilities ---------------------------------------------------------------- +COLOUR_NORMAL = $(shell tput sgr0 2>/dev/null) +COLOUR_RED = $(shell tput setaf 1 2>/dev/null) +COLOUR_GREEN = $(shell tput setaf 2 2>/dev/null) +COLOUR_WHITE = $(shell tput setaf 7 2>/dev/null) + +help: + $(eval export HELP_AWK) + @awk "$${HELP_AWK}" $(MAKEFILE_LIST) | sort | column -s "$$(printf \\t)" -t + +$(O): + @mkdir -p $@ + +.PHONY: help + +# Awk script to extract and print target descriptions for `make help`. +define HELP_AWK +/^## / { desc = desc substr($$0, 3) } +/^[A-Za-z0-9%_-]+:/ && desc { + sub(/::?$$/, "", $$1) + printf "$(COLOUR_WHITE)%s$(COLOUR_NORMAL)\t%s\n", $$1, desc + desc = "" +} +endef + +define nl + + +endef +ifndef ACTIVE_HERMIT +$(eval $(subst \n,$(nl),$(shell bin/hermit env -r | sed 's/^\(.*\)$$/export \1\\n/'))) +endif + +# Ensure make version is gnu make 4.4 or higher (for .WAIT target) +ifeq ($(filter shell-export,$(value .FEATURES)),) +$(error Unsupported Make version. \ + $(nl)Use GNU Make 4.4 or higher (current: $(MAKE_VERSION)). \ + $(nl)Activate 🐚 hermit with `. bin/activate-hermit` and run again \ + $(nl)or use `bin/make`) +endif diff --git a/bin/.gh-2.54.0.pkg b/bin/.gh-2.54.0.pkg new file mode 120000 index 0000000..383f451 --- /dev/null +++ b/bin/.gh-2.54.0.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/bin/.go-1.22.5.pkg b/bin/.go-1.22.5.pkg new file mode 120000 index 0000000..383f451 --- /dev/null +++ b/bin/.go-1.22.5.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/bin/.golangci-lint-1.59.1.pkg b/bin/.golangci-lint-1.59.1.pkg new file mode 120000 index 0000000..383f451 --- /dev/null +++ b/bin/.golangci-lint-1.59.1.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/bin/.make-4.4.pkg b/bin/.make-4.4.pkg new file mode 120000 index 0000000..383f451 --- /dev/null +++ b/bin/.make-4.4.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/bin/gh b/bin/gh new file mode 120000 index 0000000..dcb47c7 --- /dev/null +++ b/bin/gh @@ -0,0 +1 @@ +.gh-2.54.0.pkg \ No newline at end of file diff --git a/bin/go b/bin/go new file mode 120000 index 0000000..5c26cb9 --- /dev/null +++ b/bin/go @@ -0,0 +1 @@ +.go-1.22.5.pkg \ No newline at end of file diff --git a/bin/gofmt b/bin/gofmt new file mode 120000 index 0000000..5c26cb9 --- /dev/null +++ b/bin/gofmt @@ -0,0 +1 @@ +.go-1.22.5.pkg \ No newline at end of file diff --git a/bin/golangci-lint b/bin/golangci-lint new file mode 120000 index 0000000..99e3296 --- /dev/null +++ b/bin/golangci-lint @@ -0,0 +1 @@ +.golangci-lint-1.59.1.pkg \ No newline at end of file diff --git a/bin/make b/bin/make new file mode 120000 index 0000000..46c1196 --- /dev/null +++ b/bin/make @@ -0,0 +1 @@ +.make-4.4.pkg \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..53fffdd --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module foxygo.at/git-credential-fdoss + +go 1.22.5 + +require github.com/alecthomas/kong v0.9.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..524151d --- /dev/null +++ b/go.sum @@ -0,0 +1,8 @@ +github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU= +github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/kong v0.9.0 h1:G5diXxc85KvoV2f0ZRVuMsi45IrBgx9zDNGNj165aPA= +github.com/alecthomas/kong v0.9.0/go.mod h1:Y47y5gKfHp1hDc7CH7OeXgLIpp+Q2m1Ni0L5s3bI8Os= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= diff --git a/main.go b/main.go new file mode 100644 index 0000000..a17000c --- /dev/null +++ b/main.go @@ -0,0 +1,28 @@ +// cmd git-credential-fdoss is a git credentials helper that uses the +// freedesktop.org secret service for storing and retrieving git credentials. +package main + +import ( + "github.com/alecthomas/kong" +) + +var version string = "v0.0.0" + +const description = ` +git-credential-fdoss manages your git credentials using the freedesktop.org +Secret Service. +` + +type CLI struct { + Version kong.VersionFlag `short:"V" help:"Print program version"` +} + +func main() { + cli := &CLI{} + kctx := kong.Parse(cli, + kong.Description(description), + kong.Vars{"version": version}, + ) + err := kctx.Run(cli) + kctx.FatalIfErrorf(err) +}