diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ff80d61..6d679fb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,148 +2,75 @@ name: Release on: push: - branches: [main, master] + branches: [main] permissions: - contents: write - packages: write - issues: write - pull-requests: write - id-token: write + contents: read env: - GO_VERSION: "1.25" + GO_VERSION: "1.26.x" jobs: - version: - name: Determine Version + semantic-release: + name: Semantic Release + permissions: + contents: write + issues: write + pull-requests: write runs-on: ubuntu-latest outputs: - version: ${{ steps.svu.outputs.version }} - tag: ${{ steps.svu.outputs.tag }} + release-version: ${{ steps.semantic.outputs.release-version }} + new-release-published: ${{ steps.semantic.outputs.new-release-published }} steps: - name: Checkout - uses: actions/checkout@v4 - - name: Install svu - run: | - curl -sL https://github.com/caarlos0/svu/releases/download/v3.2.4/svu_3.2.4_linux_amd64.tar.gz | tar xz - sudo mv svu /usr/local/bin/ - - - name: Get next version - id: svu - run: | - git fetch --tags - NEXT_VERSION=$(svu patch --tag.pattern "v*") - echo "version=${NEXT_VERSION#v}" >> $GITHUB_OUTPUT - echo "tag=$NEXT_VERSION" >> $GITHUB_OUTPUT - echo "Next version: $NEXT_VERSION" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 - - name: Create and push tag + - name: Create draft release + uses: codfish/semantic-release-action@6abd188d2458e2fd6c99073454f6cc49196362e8 # v5.0.0 + id: semantic env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git tag ${{ steps.svu.outputs.tag }} - git push origin ${{ steps.svu.outputs.tag }} - build: - name: Build - needs: version + + binary: + name: Build binaries + if: needs.semantic-release.outputs.new-release-published == 'true' + needs: semantic-release + permissions: + contents: write runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - include: - - goos: linux - goarch: amd64 - - goos: linux - goarch: arm64 - - goos: darwin - goarch: amd64 - - goos: darwin - goarch: arm64 - - goos: windows - goarch: amd64 steps: - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 with: go-version: ${{ env.GO_VERSION }} cache: true - - name: Build binary + - name: Build release assets + run: make release env: - CGO_ENABLED: 0 - run: | - VERSION="${{ needs.version.outputs.version }}" - GOOS="${{ matrix.goos }}" - GOARCH="${{ matrix.goarch }}" - - BINARY_NAME="deps-${GOOS}-${GOARCH}" - if [ "$GOOS" = "windows" ]; then - BINARY_NAME="$BINARY_NAME.exe" - fi - - GOOS="${{ matrix.goos }}" GOARCH="${{ matrix.goarch }}" go build -ldflags="-s -w -X main.version=$VERSION -X main.commit=${{ github.sha }} -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ - -o "$BINARY_NAME" ./cmd/deps/main.go - - - sha256sum "$BINARY_NAME" > "$BINARY_NAME".sha256 - - - name: Create archive - run: | - VERSION="${{ needs.version.outputs.version }}" - GOOS="${{ matrix.goos }}" - GOARCH="${{ matrix.goarch }}" - + VERSION: ${{ needs.semantic-release.outputs.release-version }} - ARCHIVE_NAME="deps-${GOOS}-${GOARCH}" - - BINARY_NAME="deps-${GOOS}-${GOARCH}" - if [ "$GOOS" = "windows" ]; then - BINARY_NAME="$BINARY_NAME.exe" - fi - - if [ "$GOOS" = "windows" ]; then - cp "$BINARY_NAME" deps.exe - zip "${ARCHIVE_NAME}.zip" deps.exe - rm deps.exe - sha256sum "${ARCHIVE_NAME}.zip" > "${ARCHIVE_NAME}.sha256" - else - cp "$BINARY_NAME" deps - tar czf "${ARCHIVE_NAME}.tar.gz" deps - rm deps - sha256sum "${ARCHIVE_NAME}.tar.gz" > "${ARCHIVE_NAME}.tar.gz.sha256" - fi - - - name: Upload binaries to release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file_glob: true - file: deps-*.{exe,tar.gz,zip,sha256} - tag: ${{ needs.version.outputs.tag }} - draft: true - - release: - name: Create Release - needs: [version, build] + - name: Upload binaries to draft release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: v${{ needs.semantic-release.outputs.release-version }} + run: gh release upload "$TAG" ./.release/* --clobber --repo "${{ github.repository }}" + + publish-release: + name: Publish Release + if: needs.semantic-release.outputs.new-release-published == 'true' + needs: [semantic-release, binary] + permissions: + contents: write runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Update GitHub Release Notes + - name: Publish draft release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TAG: ${{ needs.version.outputs.tag }} - run: | - NOTES=$(gh api repos/${{ github.repository }}/releases/generate-notes -f tag_name="$TAG" --jq '.body') - gh release edit "$TAG" --title "Release $TAG" --notes "$NOTES" --draft=false + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: v${{ needs.semantic-release.outputs.release-version }} + run: gh release edit "$TAG" --draft=false --repo "${{ github.repository }}" diff --git a/.gitignore b/.gitignore index 9198f44..efca1c4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ main *.test deps-test +.bin/ +.release/ # Generated directories bin/ diff --git a/.releaserc b/.releaserc new file mode 100644 index 0000000..f5934a8 --- /dev/null +++ b/.releaserc @@ -0,0 +1,25 @@ +branches: + - name: main +plugins: + - - "@semantic-release/commit-analyzer" + - releaseRules: + - { type: build, release: patch } + - { type: chore, release: patch } + - { type: ci, release: patch } + - { type: doc, release: patch } + - { type: docs, release: patch } + - { type: feat, release: patch } + - { type: fix, release: patch } + - { type: perf, release: patch } + - { type: refactor, release: patch } + - { type: revert, release: patch } + - { type: style, release: patch } + - { type: test, release: patch } + parserOpts: + noteKeywords: + - MAJOR RELEASE + - "@semantic-release/release-notes-generator" + - - "@semantic-release/github" + - draftRelease: true + successComment: false + failTitle: false diff --git a/Makefile b/Makefile index 19c33fa..7b26245 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,18 @@ # Automatically installs task if not present SHELL := /bin/bash +NAME := deps +DATE := $(shell date "+%Y-%m-%d %H:%M:%S") +ifeq ($(VERSION),) +VERSION_TAG := $(shell git describe --abbrev=0 --tags --exact-match 2>/dev/null || echo latest) +else +VERSION_TAG := $(VERSION) +endif + TASK_VERSION := v3.39.2 +UPX_VERSION := 3.96 TASK_BIN := ./bin/task +UPX := ./.bin/upx UNAME_S := $(shell uname -s) UNAME_M := $(shell uname -m) @@ -29,6 +39,7 @@ endif # Task binary URL TASK_URL := https://github.com/go-task/task/releases/download/$(TASK_VERSION)/task_$(TASK_PLATFORM)_$(TASK_ARCH).tar.gz +SHA256 := $(shell command -v sha256sum >/dev/null 2>&1 && echo "sha256sum" || echo "shasum -a 256") # Ensure task is installed $(TASK_BIN): @@ -55,6 +66,64 @@ build: $(TASK_BIN) build-all: $(TASK_BIN) @$(TASK_BIN) build-all +.PHONY: linux +linux: + mkdir -p .bin + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./.bin/$(NAME)-linux-amd64 -ldflags "-X main.version=$(VERSION_TAG)" ./cmd/deps/main.go + CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o ./.bin/$(NAME)-linux-arm64 -ldflags "-X main.version=$(VERSION_TAG)" ./cmd/deps/main.go + +.PHONY: darwin +darwin: + mkdir -p .bin + CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ./.bin/$(NAME)-darwin-amd64 -ldflags "-X main.version=$(VERSION_TAG)" ./cmd/deps/main.go + CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o ./.bin/$(NAME)-darwin-arm64 -ldflags "-X main.version=$(VERSION_TAG)" ./cmd/deps/main.go + +.PHONY: windows +windows: + mkdir -p .bin + CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ./.bin/$(NAME)-windows-amd64.exe -ldflags "-X main.version=$(VERSION_TAG)" ./cmd/deps/main.go + +.PHONY: compress +compress: +ifeq ($(TASK_PLATFORM),linux) + $(MAKE) $(UPX) + $(UPX) -5 ./.bin/$(NAME)-linux-amd64 ./.bin/$(NAME)-linux-arm64 +else + @echo "Skipping upx compression on $(TASK_PLATFORM)" +endif + +.PHONY: binaries +binaries: linux darwin windows compress + +$(UPX): .bin + wget -nv -O upx.tar.xz https://github.com/upx/upx/releases/download/v$(UPX_VERSION)/upx-$(UPX_VERSION)-$(TASK_ARCH)_$(TASK_PLATFORM).tar.xz + tar xf upx.tar.xz + mv upx-$(UPX_VERSION)-$(TASK_ARCH)_$(TASK_PLATFORM)/upx .bin + rm -rf upx.tar.xz upx-$(UPX_VERSION)-$(TASK_ARCH)_$(TASK_PLATFORM) + +.bin: + mkdir -p .bin + +.PHONY: release +release: binaries + mkdir -p .release + rm -f .release/deps-* .release/deps .release/deps.exe + @for binary in .bin/$(NAME)-*; do \ + artifact=$$(basename "$$binary"); \ + archive_base="$${artifact%.exe}"; \ + (cd .bin && $(SHA256) "$$artifact") > ".release/$$artifact.sha256"; \ + if [[ "$$artifact" == *.exe ]]; then \ + cp "$$binary" ".release/$$artifact"; \ + cp "$$binary" .release/$(NAME).exe; \ + (cd .release && zip -q "$$archive_base.zip" $(NAME).exe && $(SHA256) "$$archive_base.zip" > "$$archive_base.sha256"); \ + rm -f .release/$(NAME).exe; \ + else \ + cp "$$binary" .release/$(NAME); \ + (cd .release && tar czf "$$archive_base.tar.gz" $(NAME) && $(SHA256) "$$archive_base.tar.gz" > "$$archive_base.tar.gz.sha256"); \ + rm -f .release/$(NAME); \ + fi; \ + done + # Test targets .PHONY: test test: $(TASK_BIN)