diff --git a/.github/workflows/new-release.yaml b/.github/workflows/new-release.yaml new file mode 100644 index 0000000..ffe3bf7 --- /dev/null +++ b/.github/workflows/new-release.yaml @@ -0,0 +1,234 @@ +name: TagRelease + +on: + workflow_dispatch: + inputs: + tagType: + description: 'TagType' + required: true + default: 'pre-tag' + type: choice + options: + - normal + - pre-tag + tag: + description: 'Tag version number (Eg: v0.1.0)' + required: true + type: string + message: + description: 'Tag message' + required: true + +permissions: + contents: write + packages: write + +jobs: + # * Step 0: Pre-Check + pre-check: + runs-on: ubuntu-latest + outputs: + TAG_NAME: ${{ steps.set-tag.outputs.TAG_NAME }} + PRERELEASE: ${{ steps.set-tag.outputs.PRERELEASE }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + # ! TODO add check if tag format is valid (semver) + - name: Check if tag is valid + run : | + # Check if the tag start with 'v', if not, add it + if [[ ! ${{ github.event.inputs.tag }} =~ ^v.* ]]; then + echo "Error tag format is invalid. The format is vx.x.x" >> "$GITHUB_OUTPUT" + exit 1 + fi + - name: Construct Tag for Pre-Release + id: set-tag + run: | + # Construct the tag name + if [ "${{ github.event.inputs.tagType }}" == "pre-tag" ]; then + echo "TAG_NAME=$(echo ${{ github.event.inputs.tag }}-alpha$(date +%Y%m%d%H%M))" >> "$GITHUB_OUTPUT" + echo "PRERELEASE=true" >> "$GITHUB_OUTPUT" + else + echo "TAG_NAME=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT" + fi + # * Step 1: Check if everything is ok + tag-already-exist: + needs: [pre-check] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + - name: Check if tag not already exists + run: | + if git rev-parse ${{ needs.pre-check.outputs.TAG_NAME }} >/dev/null 2>&1; then + echo "Tag ${{ needs.pre-check.outputs.TAG_NAME }} already exists" >> "$GITHUB_OUTPUT" + exit 1 + fi + golangci-lint: + needs: [pre-check] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - run: go mod download + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: latest + # TODO add tests + + # * Step 2: Create a new tag + tag: + needs: [golangci-lint, pre-check, tag-already-exist] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + - uses: rickstaa/action-create-tag@v1 + id: "tag_create" + with: + tag: ${{ needs.pre-check.outputs.TAG_NAME }} + tag_exists_error: true + message: ${{ github.event.inputs.message }} + + release-notes: + runs-on: ubuntu-latest + needs: [tag, pre-check] + steps: + - uses: actions/checkout@v4 # v3.5.3 + with: + fetch-depth: 0 + ref: ${{ needs.pre-check.outputs.TAG_NAME }} + - name: Generate Release Notes + run: | + echo "" > release-notes.txt + + if [ ${{ needs.pre-check.outputs.PRERELEASE }} == "true" ]; then + echo "## :construction: Prerelease" >> release-notes.txt + export PREV_TAG=$(git tag --list 'v*' --sort=-version:refname | grep -E "v[0-9]+\.[0-9]+\.[0-9]+$" | head -n 1) + export PREV_VERSION=${PREV_TAG//v} + else + export PREV_TAG=$(git tag --list 'v*' --sort=-version:refname | grep -E "v[0-9]+\.[0-9]+\.[0-9]+$" | head -n 2 | tail -n 1) + export PREV_VERSION=${PREV_TAG//v} + fi + + sed -n -e "1{/# /d;}" -e "2{/^$/d;}" -e "/# $PREV_VERSION/q;p" CHANGELOG.md >> release-notes.txt + - uses: actions/upload-artifact@v4 + with: + name: release-notes + path: release-notes.txt + retention-days: 1 + release-app: + runs-on: ubuntu-latest + needs: [release-notes, golangci-lint, pre-check] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ needs.pre-check.outputs.TAG_NAME }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - id: release-notes-download + name: Release Notes Download + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + name: release-notes + path: /tmp + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + if: success() + with: + distribution: goreleaser + version: latest + args: release --clean -f .goreleaser.yaml --release-notes=${{ steps.release-notes-download.outputs.download-path }}/release-notes.txt + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + trigger-doc-update: + needs: [release-app, pre-check] + runs-on: ubuntu-latest + if: needs.pre-check.outputs.PRERELEASE == 'false' + steps: + - name: Repository Dispatch + uses: peter-evans/repository-dispatch@v3 + with: + event-type: update-doc + highest-version-tag: + needs: [pre-check,release-app] + runs-on: ubuntu-latest + if: needs.pre-check.outputs.PRERELEASE == 'false' + outputs: + tag: ${{ steps.highest-version-tag.outputs.tag }} + steps: + - uses: actions/checkout@v4 # v3.5.3 + with: + ref: ${{ needs.pre-check.outputs.TAG_NAME }} + fetch-depth: 0 + - name: Output highest version tag + id: highest-version-tag + run: | + HIGHEST=$(git tag | sort -V | tail -1) + echo "tag=$HIGHEST" >> "$GITHUB_OUTPUT" + changelog-newversion: + needs: [release-app, highest-version-tag, pre-check] + # write new changelog header only if release tag is the $HIGHEST i.e. exists on main + # and not a backport release branch (e.g. release/3.x). This results in + # manually updating the CHANGELOG header if releasing from the non-default branch. + # TODO: find a more deterministic way to determine release branch from tag commit + if: github.ref_name == needs.highest-version-tag.outputs.tag && needs.pre-check.outputs.PRERELEASE == 'false' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 # v3.5.3 + with: + token: ${{ secrets.PAT }} + fetch-depth: 0 + ref: main + - name: Update Changelog Header + run: | + CHANGELOG_FILE_NAME="CHANGELOG.md" + PREVIOUS_RELEASE_TAG=${{ github.ref_name }} + + # Add Release Date + RELEASE_DATE=`date +%B' '%e', '%Y` + sed -i -e "1 s/.*Unreleased.*/## ${PREVIOUS_RELEASE_TAG#v} ($RELEASE_DATE)/" $CHANGELOG_FILE_NAME + + # Prepend next release line + echo Previous release is: $PREVIOUS_RELEASE_TAG + + NEW_RELEASE_LINE=$(echo $PREVIOUS_RELEASE_TAG | awk -F. '{ + $1 = substr($1,2) + $2 += 1 + printf("%s.%01d.0\n\n", $1, $2); + }') + + echo New minor version is: v$NEW_RELEASE_LINE + + echo -e "## $NEW_RELEASE_LINE (Unreleased)\n$(cat $CHANGELOG_FILE_NAME)" > $CHANGELOG_FILE_NAME + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "chore: Update CHANGELOG.md after ${{ github.ref_name }}" + commit_options: '--no-verify --signoff' + file_pattern: CHANGELOG.md + commit_user_name: Changelog[bot] + commit_user_email: changelog-bot@azrod.me + commit_author: Changelog Bot + diff --git a/.github/workflows/pre-release.yaml b/.github/workflows/pre-release.yaml new file mode 100644 index 0000000..0540b32 --- /dev/null +++ b/.github/workflows/pre-release.yaml @@ -0,0 +1,81 @@ +name: Pre-Release + +on: + repository_dispatch: + types: [prerelease] + + +permissions: + contents: write + packages: write + +jobs: + GolangCI-Lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.client_payload.tag }} + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - run: go mod download + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: latest + release-notes: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 # v3.5.3 + with: + fetch-depth: 0 + ref: ${{ github.event.client_payload.tag }} + - name: Generate Release Notes + run: | + export PREV_TAG=$(git tag --list 'v*' --sort=-version:refname | head -n 2 | tail -n 1) + export PREV_VERSION=${PREV_TAG//v} + echo "# :construction: Prerelease" > prerelease-notes.txt + sed -n -e "1{/# /d;}" -e "2{/^$/d;}" -e "/# $PREV_VERSION/q;p" CHANGELOG.md >> prerelease-notes.txt + - uses: actions/upload-artifact@v4 + with: + name: prerelease-notes + path: prerelease-notes.txt + retention-days: 1 + release-app: + runs-on: ubuntu-latest + needs: [release-notes, GolangCI-Lint] + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.event.client_payload.tag }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - id: release-notes-download + name: Release Notes Download + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + name: prerelease-notes + path: /tmp + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v5 + if: success() + with: + distribution: goreleaser + version: latest + args: release --snapshot --clean -f .goreleaser-prerelease.yaml --release-notes=${{ steps.release-notes-download.outputs.download-path }}/prerelease-notes.txt + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3975813..89b6309 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,9 +1,8 @@ name: Release on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+$' + repository_dispatch: + types: [release] permissions: contents: write @@ -14,6 +13,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + ref: ${{ github.event.client_payload.tag }} - uses: actions/setup-go@v5 with: go-version-file: 'go.mod' @@ -28,6 +29,7 @@ jobs: - uses: actions/checkout@v4 # v3.5.3 with: fetch-depth: 0 + ref: ${{ github.event.client_payload.tag }} - name: Generate Release Notes run: | export PREV_TAG=$(git tag --list 'v*' --sort=-version:refname | head -n 2 | tail -n 1) @@ -46,6 +48,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + ref: ${{ github.event.client_payload.tag }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Go @@ -85,7 +88,7 @@ jobs: steps: - uses: actions/checkout@v4 # v3.5.3 with: - # Allow tag to be fetched when ref is a commit + ref: ${{ github.event.client_payload.tag }} fetch-depth: 0 - name: Output highest version tag id: highest-version-tag diff --git a/.github/workflows/tag.yaml b/.github/workflows/tag.yaml index 30d811b..9944c1d 100644 --- a/.github/workflows/tag.yaml +++ b/.github/workflows/tag.yaml @@ -18,8 +18,11 @@ on: description: 'Tag message' required: true +permissions: + contents: write + jobs: - pre-tag: + tag: runs-on: ubuntu-latest env: TAG_NAME: ${{ github.event.inputs.tag }} @@ -30,7 +33,7 @@ jobs: - run: | # Construct the tag name if [ "${{ github.event.inputs.tagType }}" == "pre-tag" ]; then - echo "TAG_NAME=$(echo ${{ github.event.inputs.tag }}-alpha.$(date +%Y%m%d%H%M))" >> "$GITHUB_ENV" + echo "TAG_NAME=$(echo ${{ github.event.inputs.tag }}-alpha+$(date +%Y%m%d%H%M))" >> "$GITHUB_ENV" else echo "TAG_NAME=$(echo ${{ github.event.inputs.tag }})" >> "$GITHUB_ENV" fi @@ -49,3 +52,15 @@ jobs: tag: ${{ env.TAG_NAME }} tag_exists_error: true message: ${{ github.event.inputs.message }} + - name: Repository Dispatch Release + if: ${{ github.event.inputs.tagType == 'normal' }} + uses: peter-evans/repository-dispatch@v3 + with: + event-type: release + client-payload: '{"tag": "${{ env.TAG_NAME }}"}' + - name: Repository Dispatch Pre-Release + if: ${{ github.event.inputs.tagType == 'pre-tag' }} + uses: peter-evans/repository-dispatch@v3 + with: + event-type: prerelease + client-payload: '{"tag": "${{ env.TAG_NAME }}"}' \ No newline at end of file diff --git a/.goreleaser-prerelease.yaml b/.goreleaser-prerelease.yaml new file mode 100644 index 0000000..caa4f71 --- /dev/null +++ b/.goreleaser-prerelease.yaml @@ -0,0 +1,129 @@ +project_name: golink + +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy + +snapshot: + name_template: "{{ .Tag }}" + +checksum: + name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt' + +builds: + - id: "golink" + binary: golink + ldflags: + - '-s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}' + goos: + - freebsd + - windows + - linux + - darwin + goarch: + - amd64 + - arm + - arm64 + env: + - CGO_ENABLED=0 + - id: "glctl" + binary: glctl + main: ./cmd/glctl + ldflags: + - '-s -w -X github.com/azrod/golink/cmd/glctl/cmd.version={{.Version}} -X github.com/azrod/golink/cmd/glctl/cmd.commit={{.Commit}} -X github.com/azrod/golink/cmd/glctl/cmd.date={{.Date}}' + goos: + - freebsd + - windows + - linux + - darwin + goarch: + - amd64 + - arm + - arm64 + env: + - CGO_ENABLED=0 + +dockers: + - goarch: amd64 + image_templates: + - "ghcr.io/azrod/{{.ProjectName}}:v{{ .Version }}-amd64" + extra_files: + - ui/ + dockerfile: Dockerfile + use: buildx + ids: + - golink + - glctl + build_flag_templates: + - --platform=linux/amd64 + - --pull + - --label=org.opencontainers.image.title={{ .ProjectName }} + - --label=org.opencontainers.image.description={{ .ProjectName }} + - --label=org.opencontainers.image.url=https://github.com/azrod/{{ .ProjectName }} + - --label=org.opencontainers.image.source=https://github.com/azrod/{{.ProjectName}} + - --label=org.opencontainers.image.version={{ .Version }} + - --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }} + - --label=org.opencontainers.image.revision={{ .FullCommit }} + + - goarch: arm64 + image_templates: + - "ghcr.io/azrod/{{ .ProjectName }}:v{{ .Version }}-arm64v8" + extra_files: + - ui/ + dockerfile: Dockerfile + use: buildx + ids: + - golink + - glctl + build_flag_templates: + - --platform=linux/arm64/v8 + - --pull + - --label=org.opencontainers.image.title={{ .ProjectName }} + - --label=org.opencontainers.image.description={{ .ProjectName }} + - --label=org.opencontainers.image.url=https://github.com/azrod/{{ .ProjectName }} + - --label=org.opencontainers.image.source=https://github.com/azrod/{{ .ProjectName }} + - --label=org.opencontainers.image.version={{ .Version }} + - --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }} + - --label=org.opencontainers.image.revision={{ .FullCommit }} + +docker_manifests: +- name_template: "ghcr.io/azrod/{{ .ProjectName }}:v{{ .Version }}" + image_templates: + - "ghcr.io/azrod/{{ .ProjectName }}:v{{ .Version }}-amd64" + - "ghcr.io/azrod/{{ .ProjectName }}:v{{ .Version }}-arm64v8" +- name_template: "ghcr.io/azrod/{{ .ProjectName }}:latest" + image_templates: + - "ghcr.io/azrod/{{ .ProjectName }}:v{{ .Version }}-amd64" + - "ghcr.io/azrod/{{ .ProjectName }}:v{{ .Version }}-arm64v8" + +archives: + # Golink + - id: "golink" + builds: + - golink + format: tar.gz + wrap_in_directory: true + format_overrides: + - goos: windows + format: zip + name_template: 'golink-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}' + files: + - LICENSE + - README.md + # glctl + - id: "glctl" + builds: + - glctl + format: tar.gz + wrap_in_directory: true + format_overrides: + - goos: windows + format: zip + name_template: 'glctl-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}' + files: + - LICENSE + - ./cmd/glctl/README.md + +release: + prerelease: true \ No newline at end of file diff --git a/.goreleaser.yaml b/.goreleaser.yaml index c524147..e39c78a 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -5,8 +5,12 @@ before: # You may remove this if you don't use go modules. - go mod tidy +release: + prerelease: auto + + snapshot: - name_template: SNAPSHOT-{{ .Commit }} + name_template: "{{ .Tag }}" checksum: name_template: '{{ .ProjectName }}-{{ .Version }}-checksums.txt'