From 21008037172223ac6b9cf5459208c817342192ad Mon Sep 17 00:00:00 2001 From: Michael Beutler <35310806+michaelbeutler@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:12:38 +0200 Subject: [PATCH 1/4] ci: added new ci steps and conventional commit messages --- .github/dependabot.yml | 35 ++++ .github/workflows/ci.yaml | 124 ------------ .github/workflows/ci.yml | 247 ++++++++++++++++++++++++ .github/workflows/release-candidate.yml | 106 ++++++++++ .github/workflows/release.yaml | 51 ----- .github/workflows/release.yml | 109 +++++++++++ .pre-commit-config.yaml | 10 + cliff.toml | 108 +++++++++++ commitlint.config.js | 6 + 9 files changed, 621 insertions(+), 175 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release-candidate.yml delete mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/release.yml create mode 100644 cliff.toml create mode 100644 commitlint.config.js diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..877d0f7f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,35 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" # Path containing go.mod + schedule: + interval: "weekly" + # Conventional Commits for Dependabot PRs + commit-message: + prefix: "chore" + prefix-development: "chore" + include: "scope" + # Keep visible but not overwhelming + open-pull-requests-limit: 10 + # Label PRs so they’re easy to filter + labels: + - "dependencies" + assignees: + - michaelbeutler + + # Grouping rules + groups: + # Single weekly rollup for all safe (minor/patch) updates + minor-and-patch: + patterns: + - "*" # match all deps + update-types: + - "minor" + - "patch" + + # Keep majors separate so breaking changes get proper review + each-major-separately: + patterns: + - "*" # (tip: Dependabot will still open 1 PR per dep for majors) + update-types: + - "major" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml deleted file mode 100644 index 5c9f405f..00000000 --- a/.github/workflows/ci.yaml +++ /dev/null @@ -1,124 +0,0 @@ -name: CI 🚧 - -on: - push: - paths: - - "**.go" - - "**.md" - - "**.mod" - - ".github/workflows/**.yaml" - -jobs: - lint-and-format: - name: Lint & Format 🧹 - runs-on: ubuntu-latest - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: 1.24 - cache: true - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - - - name: Install dependencies - run: | - pip install detect-secrets yamllint - - - name: go mod tidy check - run: | - cp go.mod go.mod.prev - cp go.sum go.sum.prev - go mod tidy - diff -u go.mod.prev go.mod || (echo "::error file=go.mod::Run 'go mod tidy' and commit changes."; exit 1) - diff -u go.sum.prev go.sum || (echo "::error file=go.sum::Run 'go mod tidy' and commit changes."; exit 1) - - - name: go fmt (no diffs allowed) - run: | - CHANGED=$(gofmt -s -l . || true) - if [ -n "$CHANGED" ]; then - echo "::error ::Run 'gofmt -s -w .' to format:" - echo "$CHANGED" - exit 1 - fi - - - name: go vet - run: go vet ./... - - - name: Install staticcheck - run: go install honnef.co/go/tools/cmd/staticcheck@latest - - - name: staticcheck - run: $(go env GOPATH)/bin/staticcheck ./... - - - name: Lint - uses: golangci/golangci-lint-action@v6 - with: - version: v1.58 - - - name: Run JSON tags camelCase check - run: make check-json-tags - - - name: Check Prometheus metrics - run: make check-metrics - - - name: Run yamllint - run: yamllint . - - - name: Check for uncommitted changes - run: | - git diff --exit-code || (echo "::error::Generated code is not up to date. Run 'make generate' and commit changes."; exit 1) - - - name: Detect secrets - run: | - echo "πŸ” Scanning for secrets..." - if command -v detect-secrets >/dev/null 2>&1; then - detect-secrets scan --baseline .secrets.baseline --all-files || echo "Secret detection completed with findings" - if [ -f ".secrets.baseline" ]; then - detect-secrets audit .secrets.baseline --statistics || echo "Baseline audit completed" - fi - else - echo "detect-secrets not available, skipping secret scan (basic validation will still run)" - fi - - test-coverage: - name: Test & Coverage πŸ§ͺ - runs-on: ubuntu-latest - env: - ENV: test - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }} - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: 1.24 - cache: true - - - name: Generate test coverage - run: go test ./... -coverprofile=./cover.out -covermode=atomic -coverpkg=./... - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v4.0.1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - - - name: Check test coverage - uses: vladopajic/go-test-coverage@v2 - with: - config: ./.testcoverage.yml - profile: cover.out - local-prefix: github.com/truvami/decoder - threshold-file: 75 - threshold-package: 80 - threshold-total: 80 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..8e64cfad --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,247 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +# Cancel older runs of the same branch/PR to save minutes +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Default to least privilege; Codecov only needs these for OIDC upload & (optionally) PR comments +permissions: + contents: read + id-token: write + pull-requests: write + attestations: write + +env: + GOFLAGS: -mod=readonly + +jobs: + commitlint: + name: Commit message lint (conventional commits) + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install commitlint dependencies + run: npm i --no-save --no-package-lock @commitlint/cli @commitlint/config-conventional + + - name: Validate current commit (last commit) with commitlint + if: github.event_name == 'push' + run: npx commitlint --last --verbose + + - name: Validate PR commits with commitlint + if: github.event_name == 'pull_request' + run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose + + lint: + name: Lint (fmt + vet [+ staticcheck]) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ">=1.24.0" + cache: true + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + pip install yamllint + + - name: go mod tidy check + run: | + cp go.mod go.mod.prev + cp go.sum go.sum.prev + go mod tidy + diff -u go.mod.prev go.mod || (echo "::error file=go.mod::Run 'go mod tidy' and commit changes."; exit 1) + diff -u go.sum.prev go.sum || (echo "::error file=go.sum::Run 'go mod tidy' and commit changes."; exit 1) + + - name: go fmt (no diffs allowed) + run: | + # Lists files that would change if formatted; fail if any are returned + CHANGED=$(gofmt -s -l . || true) + if [ -n "$CHANGED" ]; then + echo "::error ::Run 'gofmt -s -w .' to format:" + echo "$CHANGED" + exit 1 + fi + + - name: go vet + run: go vet ./... + + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: staticcheck + run: $(go env GOPATH)/bin/staticcheck ./... + + - name: Run JSON tags camelCase check + run: make check-json-tags + + - name: Check Prometheus metrics + run: make check-metrics + + - name: Run yamllint + run: yamllint . + + detect-secrets: + name: Detect secrets (baseline check) + needs: lint + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install detect-secrets + run: | + pip install detect-secrets + + - name: Detect secrets + run: | + echo "πŸ” Scanning for secrets..." + if command -v detect-secrets >/dev/null 2>&1; then + detect-secrets scan --baseline .secrets.baseline --all-files || echo "Secret detection completed with findings" + if [ -f ".secrets.baseline" ]; then + detect-secrets audit .secrets.baseline --statistics || echo "Baseline audit completed" + fi + else + echo "detect-secrets not available, skipping secret scan (basic validation will still run)" + fi + + test: + name: Test (matrix) + needs: lint + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + go: ["1.24.x", "1.25.x"] + include: + # Run race+coverage once on Linux with the newest Go + - os: ubuntu-latest + go: "1.24.x" + coverage: true + runs-on: ${{ matrix.os }} + env: + ENV: test + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ${{ vars.AWS_DEFAULT_REGION }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go }} + cache: true + + - name: Verify modules + run: | + go mod verify + + - name: Build + run: go build ./... + + # Regular tests (fast) on all OS/Go combos without race/coverage to keep CI time down + - name: Test (no race/coverage) + if: ${{ !matrix.coverage }} + run: go test ./... + + # Single canonical run with race + coverage profile (Linux, newest Go) + - name: Test (race + coverage) + if: ${{ matrix.coverage }} + run: | + # Use atomic mode for consistent results under -race + go test -race -covermode=atomic -coverpkg=./... -coverprofile=cover.out ./... + + - name: Upload coverage artifact + if: ${{ matrix.coverage }} + uses: actions/upload-artifact@v4 + with: + name: coverage + path: cover.out + retention-days: 7 + + codecov: + name: Upload coverage to Codecov + needs: test + + # still attempt upload even if some matrix legs fail + if: ${{ always() }} + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download coverage artifact + uses: actions/download-artifact@v5 + with: + name: coverage + path: . + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + + goreleaser-snapshot: + name: GoReleaser (snapshot check) + needs: test + if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/main' }} + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ">=1.24.0" + cache: true + + - uses: docker/setup-buildx-action@v3 + with: + install: true + + - name: GoReleaser (snapshot) + uses: goreleaser/goreleaser-action@v6 + with: + version: "~> v2" + args: release --snapshot --skip=publish --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml new file mode 100644 index 00000000..8e017527 --- /dev/null +++ b/.github/workflows/release-candidate.yml @@ -0,0 +1,106 @@ +name: Release Candidate + +on: + push: + tags: + - 'v*.*.*-rc*' + workflow_dispatch: + +permissions: + contents: write + packages: write + id-token: write + attestations: write + +concurrency: + group: rc-${{ github.ref }} + cancel-in-progress: false + +jobs: + goreleaser-rc: + name: GoReleaser (RC publish) + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.24.x' + cache: true + + - name: Install git-cliff + uses: taiki-e/install-action@v2 + with: + tool: git-cliff + + - name: Compute last stable tag (exclude RCs) + id: base + shell: bash + run: | + BASE_TAG=$(git tag --list 'v*' --sort=-v:refname | grep -v -- '-rc' | head -n1 || true) + if [ -z "$BASE_TAG" ]; then + echo "tag=" >> $GITHUB_OUTPUT + else + echo "tag=$BASE_TAG" >> $GITHUB_OUTPUT + fi + + - name: Generate release notes (temp file to keep repo clean) + id: notes + shell: bash + run: | + NOTES_FILE="${RUNNER_TEMP}/RELEASE_NOTES.md" + TARGET_TAG="${GITHUB_REF_NAME}" + BASE_TAG="${{ steps.base.outputs.tag }}" + if [ -n "$BASE_TAG" ]; then + git-cliff --tag "$TARGET_TAG" --since-tag "$BASE_TAG" > "$NOTES_FILE" + else + git-cliff --tag "$TARGET_TAG" > "$NOTES_FILE" + fi + echo "file=$NOTES_FILE" >> "$GITHUB_OUTPUT" + echo "==== RELEASE NOTES PREVIEW ====" + head -n 60 "$NOTES_FILE" || true + + - name: Ensure go.mod/go.sum are tidy + shell: bash + run: | + go mod tidy + if ! git diff --quiet -- go.mod go.sum; then + echo "::error ::go.mod/go.sum changed after 'go mod tidy'. Commit these changes." + git --no-pager diff -- go.mod go.sum + exit 1 + fi + + - name: Fail if git tree is dirty (pre-release) + shell: bash + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "::error ::Working tree is dirty just before GoReleaser:" + git status --porcelain + exit 1 + fi + + - uses: docker/setup-buildx-action@v3 + with: + install: true + + - name: Log into GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: GoReleaser (publish RC) + uses: goreleaser/goreleaser-action@v6 + with: + version: "~> v2" + args: release --clean --release-notes="${{ steps.notes.outputs.file }}" + env: + # Prevent Go from modifying go.mod/go.sum during the build + GOFLAGS: -mod=readonly + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml deleted file mode 100644 index 8a3259ae..00000000 --- a/.github/workflows/release.yaml +++ /dev/null @@ -1,51 +0,0 @@ -name: Release πŸš€ - -on: - push: - tags: - - "*" - -jobs: - release: - name: Release - runs-on: ubuntu-latest - env: - GO_VERSION: "1.22" - timeout-minutes: 15 - permissions: - contents: write - packages: write - # Necessary if GoReleaser is configured to generate SLSA attestations - # attestations: write - - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Setup Go and Cache Modules - uses: actions/setup-go@v5 - with: - go-version: ${{ env.GO_VERSION }} - cache: true # Enable caching for Go modules - # cache-dependency-path: go.sum # Uncomment if your go.mod/go.sum are not at the repo root - - - name: Log in to GitHub Container Registry - # Check https://github.com/docker/login-action for the latest recommended version. - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Run GoReleaser - # It's good practice to pin GoReleaser to a specific version for stability, - # rather than 'latest', especially for a release workflow. - # You can find versions at https://github.com/goreleaser/goreleaser-action/releases - uses: goreleaser/goreleaser-action@v6 - with: - # Consider pinning to a specific version, e.g., 'v1.24.0' - version: latest - args: release --clean --timeout=15m - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a9cbdd84 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,109 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + - '!**-rc*' # exclude pre-releases + workflow_dispatch: + +permissions: + contents: write + packages: write + id-token: write + attestations: write + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +jobs: + goreleaser: + name: GoReleaser (final publish) + runs-on: ubuntu-latest + if: contains(github.ref_name, '-') == false + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.24.x' + cache: true + + - name: Install git-cliff + uses: taiki-e/install-action@v2 + with: + tool: git-cliff + + - name: Compute previous stable (exclude RCs) + id: base + shell: bash + run: | + # Current tag is the newest stable that triggered this workflow. + # Get the previous stable (no "-rc") by taking the 2nd most recent stable tag. + PREV_STABLE=$(git tag --list 'v*' --sort=-v:refname | grep -v -- '-rc' | sed -n '2p' || true) + if [ -z "$PREV_STABLE" ]; then + echo "tag=" >> $GITHUB_OUTPUT + else + echo "tag=$PREV_STABLE" >> $GITHUB_OUTPUT + fi + + - name: Generate release notes (since previous stable) to temp + id: notes + shell: bash + run: | + NOTES_FILE="${RUNNER_TEMP}/RELEASE_NOTES.md" + TARGET_TAG="${GITHUB_REF_NAME}" + BASE_TAG="${{ steps.base.outputs.tag }}" + if [ -n "$BASE_TAG" ]; then + git-cliff --tag "$TARGET_TAG" --since-tag "$BASE_TAG" > "$NOTES_FILE" + else + git-cliff --tag "$TARGET_TAG" > "$NOTES_FILE" + fi + echo "file=$NOTES_FILE" >> "$GITHUB_OUTPUT" + echo "==== RELEASE NOTES PREVIEW ====" + head -n 60 "$NOTES_FILE" || true + + - name: Ensure go.mod/go.sum are tidy + shell: bash + run: | + go mod tidy + if ! git diff --quiet -- go.mod go.sum; then + echo "::error ::go.mod/go.sum changed after 'go mod tidy'. Commit these changes." + git --no-pager diff -- go.mod go.sum + exit 1 + fi + + - name: Fail if git tree is dirty (pre-release) + shell: bash + run: | + if [ -n "$(git status --porcelain)" ]; then + echo "::error ::Working tree is dirty just before GoReleaser:" + git status --porcelain + exit 1 + fi + + - uses: docker/setup-buildx-action@v3 + with: + install: true + + - name: Log into GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: GoReleaser (publish) + uses: goreleaser/goreleaser-action@v6 + with: + version: "~> v2" + args: release --clean --release-notes="${{ steps.notes.outputs.file }}" + env: + GOFLAGS: -mod=readonly + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3f2b240e..4dc35e85 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,3 +27,13 @@ repos: hooks: - id: detect-secrets args: ["--baseline", ".secrets.baseline"] + + - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook + rev: v9.18.0 + hooks: + - id: commitlint + name: commitlint (conventional commits) + stages: [commit-msg] + additional_dependencies: + - '@commitlint/cli' + - '@commitlint/config-conventional' diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 00000000..5079a12b --- /dev/null +++ b/cliff.toml @@ -0,0 +1,108 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + +[changelog] +# A Tera template to be rendered as the changelog's header. +# See https://keats.github.io/tera/docs/#introduction +header = """ +# Changelog\n +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n +""" +# A Tera template to be rendered for each release in the changelog. +# See https://keats.github.io/tera/docs/#introduction +body = """ +{%- macro remote_url() -%} + https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} +{%- endmacro -%} + +{% if version -%} + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else -%} + ## [Unreleased] +{% endif -%} + +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {%- for commit in commits %} + - {{ commit.message | split(pat="\n") | first | upper_first | trim }}\ + {% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%} + {% if commit.remote.pr_number %} in \ + [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \ + {%- endif -%} + {% endfor %} +{% endfor %} + +{%- if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} + ### New Contributors +{%- endif -%} + +{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %} + * @{{ contributor.username }} made their first contribution + {%- if contributor.pr_number %} in \ + [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ + {%- endif %} +{%- endfor %}\n + +{%- if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}{% raw %}\n{% endraw -%}{% endif %} + +""" +# A Tera template to be rendered as the changelog's footer. +# See https://keats.github.io/tera/docs/#introduction +footer = """ +{%- macro remote_url() -%} + https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }} +{%- endmacro -%} + +{% for release in releases -%} + {% if release.version -%} + {% if release.previous.version -%} + [{{ release.version | trim_start_matches(pat="v") }}]: \ + {{ self::remote_url() }}/compare/{{ release.previous.version }}...{{ release.version }} + {% endif -%} + {% else -%} + [unreleased]: {{ self::remote_url() }}/compare/{{ release.previous.version }}...HEAD + {% endif -%} +{% endfor %} + +""" +# Remove leading and trailing whitespaces from the changelog's body. +trim = true + +[git] +conventional_commits = true +filter_unconventional = true +require_conventional = false + +# If true, any commit not matched by commit_parsers is dropped. +# This helps keep out noise while still letting us explicitly skip some types below. +filter_commits = true + +# Match semver + RC tags +tag_pattern = "v[0-9]+\\.[0-9]+\\.[0-9]+(-rc\\.[0-9]+)?" + +# Do not allow BREAKING CHANGE commits to be skipped by parsers +protect_breaking_commits = true + +# Parsers: group desired types, and explicitly skip noise like chore/style. +commit_parsers = [ + # Skip noise first + { message = "^chore", skip = true }, + { message = "^style", skip = true }, + { message = "^revert", skip = true }, # optional + + # Core groups + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Fixes" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactors" }, + { message = "^docs", group = "Documentation" }, + { message = "^ci", group = "CI" }, + { message = "^test", group = "Tests" }, + + # Surface BREAKING CHANGE wherever it appears (message/body/footer) + { body = "BREAKING CHANGE", group = "Breaking Changes" }, + { footer = "BREAKING CHANGE", group = "Breaking Changes" }, +] diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..b8e7f589 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + "body-max-line-length": [2, "always", 500], + }, +}; From 3fdef6c11ac18d015116685e386fe32b23888cf4 Mon Sep 17 00:00:00 2001 From: Michael Beutler <35310806+michaelbeutler@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:15:29 +0200 Subject: [PATCH 2/4] refactor: simplify git-cliff command for generating release notes --- .github/workflows/release-candidate.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index 8e017527..7fadce29 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -57,7 +57,7 @@ jobs: TARGET_TAG="${GITHUB_REF_NAME}" BASE_TAG="${{ steps.base.outputs.tag }}" if [ -n "$BASE_TAG" ]; then - git-cliff --tag "$TARGET_TAG" --since-tag "$BASE_TAG" > "$NOTES_FILE" + git-cliff $BASE_TAG..$TARGET_TAG > "$NOTES_FILE" else git-cliff --tag "$TARGET_TAG" > "$NOTES_FILE" fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9cbdd84..260b39b1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,7 @@ jobs: TARGET_TAG="${GITHUB_REF_NAME}" BASE_TAG="${{ steps.base.outputs.tag }}" if [ -n "$BASE_TAG" ]; then - git-cliff --tag "$TARGET_TAG" --since-tag "$BASE_TAG" > "$NOTES_FILE" + git-cliff $BASE_TAG..$TARGET_TAG > "$NOTES_FILE" else git-cliff --tag "$TARGET_TAG" > "$NOTES_FILE" fi From c23ee887505fb8eb80a7e0d43f46b42d53fd1a54 Mon Sep 17 00:00:00 2001 From: Michael Beutler <35310806+michaelbeutler@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:31:04 +0200 Subject: [PATCH 3/4] feat: add winget configuration for Truvami decoder package --- .goreleaser.yaml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 43c6ebf2..32323015 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -145,3 +145,43 @@ dockers: changelog: sort: asc + +winget: + - name: decoder + publisher: Truvami + short_description: "Truvami decoder reference implementation." + license: "MIT" + publisher_url: https://truvami.com + publisher_support_url: "https://github.com/truvami/decoder/issues" + # Explicit for clarity; default would be Publisher.ProjectName + package_identifier: Truvami.Decoder + + # URL to your GitHub release assets (Windows ZIPs) + url_template: "https://github.com/truvami/decoder/releases/download/{{ .Tag }}/{{ .ArtifactName }}" + + # Commit message used if/when uploads/PRs are enabled + commit_msg_template: "{{ .PackageIdentifier }}: {{ .Tag }}" + + repository: + owner: truvami + name: winget-pkgs + branch: master + pull_request: + enabled: false + + homepage: "https://github.com/truvami/decoder" + description: "Reference implementation of the Truvami decoder CLI for decoding and encoding payloads." + license_url: "https://github.com/truvami/decoder/blob/main/LICENSE" + + # Generate manifests locally only (no commits/PRs). Change to 'auto' or configure repository to enable PRs. + skip_upload: auto + + # Release notes + release_notes: "{{ .Changelog }}" + release_notes_url: "https://github.com/truvami/decoder/releases/tag/{{ .Tag }}" + + # Optional tags for winget + tags: + - golang + - cli + - decoder From eff7a4301b5956da3fba81c70fce56947b11db4c Mon Sep 17 00:00:00 2001 From: Michael Beutler <35310806+michaelbeutler@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:34:18 +0200 Subject: [PATCH 4/4] refactor: update winget configuration for decoder package --- .goreleaser.yaml | 78 ++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 32323015..ae948c93 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -146,42 +146,42 @@ dockers: changelog: sort: asc -winget: - - name: decoder - publisher: Truvami - short_description: "Truvami decoder reference implementation." - license: "MIT" - publisher_url: https://truvami.com - publisher_support_url: "https://github.com/truvami/decoder/issues" - # Explicit for clarity; default would be Publisher.ProjectName - package_identifier: Truvami.Decoder - - # URL to your GitHub release assets (Windows ZIPs) - url_template: "https://github.com/truvami/decoder/releases/download/{{ .Tag }}/{{ .ArtifactName }}" - - # Commit message used if/when uploads/PRs are enabled - commit_msg_template: "{{ .PackageIdentifier }}: {{ .Tag }}" - - repository: - owner: truvami - name: winget-pkgs - branch: master - pull_request: - enabled: false - - homepage: "https://github.com/truvami/decoder" - description: "Reference implementation of the Truvami decoder CLI for decoding and encoding payloads." - license_url: "https://github.com/truvami/decoder/blob/main/LICENSE" - - # Generate manifests locally only (no commits/PRs). Change to 'auto' or configure repository to enable PRs. - skip_upload: auto - - # Release notes - release_notes: "{{ .Changelog }}" - release_notes_url: "https://github.com/truvami/decoder/releases/tag/{{ .Tag }}" - - # Optional tags for winget - tags: - - golang - - cli - - decoder +# winget: +# - name: decoder +# publisher: Truvami +# short_description: "Truvami decoder reference implementation." +# license: "MIT" +# publisher_url: https://truvami.com +# publisher_support_url: "https://github.com/truvami/decoder/issues" +# # Explicit for clarity; default would be Publisher.ProjectName +# package_identifier: Truvami.Decoder + +# # URL to your GitHub release assets (Windows ZIPs) +# url_template: "https://github.com/truvami/decoder/releases/download/{{ .Tag }}/{{ .ArtifactName }}" + +# # Commit message used if/when uploads/PRs are enabled +# commit_msg_template: "{{ .PackageIdentifier }}: {{ .Tag }}" + +# repository: +# owner: microsoft +# name: wiinget-pkgs +# branch: master +# pull_request: +# enabled: true + +# homepage: "https://github.com/truvami/decoder" +# description: "Reference implementation of the Truvami decoder CLI for decoding and encoding payloads." +# license_url: "https://github.com/truvami/decoder/blob/main/LICENSE" + +# # Generate manifests locally only (no commits/PRs). Change to 'auto' or configure repository to enable PRs. +# skip_upload: auto + +# # Release notes +# release_notes: "{{ .Changelog }}" +# release_notes_url: "https://github.com/truvami/decoder/releases/tag/{{ .Tag }}" + +# # Optional tags for winget +# tags: +# - golang +# - cli +# - decoder