From a322f93949668e9fc42f4187f8b075a7dce52be3 Mon Sep 17 00:00:00 2001
From: Dmitriy Safronov <zimniy@cyberbrain.pw>
Date: Tue, 6 Aug 2024 21:11:17 +0400
Subject: [PATCH] ci: workflows (#88)

Signed-off-by: Dmitriy Safronov <zimniy@cyberbrain.pw>
---
 .cliff.git.toml                               | 65 +++++++++++++++++++
 .cliff.release.toml                           | 51 +++++++++++++++
 .github/workflows/push-create_tag.yaml        | 49 ++++++++++++++
 .github/workflows/push-rebase.yaml            | 22 +++++++
 .../rebase-on-push-to-main-branch.yaml        | 17 -----
 .github/workflows/tag-release.yaml            | 34 ++++++++++
 6 files changed, 221 insertions(+), 17 deletions(-)
 create mode 100644 .cliff.git.toml
 create mode 100644 .cliff.release.toml
 create mode 100644 .github/workflows/push-create_tag.yaml
 create mode 100644 .github/workflows/push-rebase.yaml
 delete mode 100644 .github/workflows/rebase-on-push-to-main-branch.yaml
 create mode 100644 .github/workflows/tag-release.yaml

diff --git a/.cliff.git.toml b/.cliff.git.toml
new file mode 100644
index 0000000..ec61efe
--- /dev/null
+++ b/.cliff.git.toml
@@ -0,0 +1,65 @@
+[changelog]
+# changelog header
+header = """
+# Changelog\n
+All notable changes to this project will be documented in this file.\n
+"""
+# template for the changelog body
+# https://keats.github.io/tera/docs/#introduction
+body = """
+{% 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 | striptags | trim | upper_first }}
+    {% for commit in commits %}
+        - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
+            {% if commit.breaking %}[**breaking**] {% endif %}\
+            {{ commit.message | upper_first }}\
+    {% endfor %}
+{% endfor %}\n
+"""
+# template for the changelog footer
+footer = """
+<!-- generated by git-cliff -->
+"""
+# remove the leading and trailing s
+trim = true
+
+[git]
+# parse the commits based on https://www.conventionalcommits.org
+conventional_commits = true
+# filter out the commits that are not conventional
+filter_unconventional = true
+# process each line of a commit as an individual commit
+split_commits = false
+# regex for parsing and grouping commits
+commit_parsers = [
+  { message = "^feat",                                group = "<!-- 0 -->๐Ÿš€ Features" },
+  { message = "^fix|^bugfix|^hotfix",                 group = "<!-- 1 -->๐Ÿ› Bug Fixes" },
+  { message = "^refactor",                            group = "<!-- 2 -->๐Ÿšœ Refactor" },
+  { message = "^doc.*update changelog.*",             group = "<!-- 3 -->๐Ÿ“š Documentation", skip = true },
+  { message = "^doc",                                 group = "<!-- 3 -->๐Ÿ“š Documentation" },
+  { message = "^perf",                                group = "<!-- 4 -->โšก Performance" },
+  { message = "^style",                               group = "<!-- 5 -->๐ŸŽจ Styling" },
+  { message = "^test",                                group = "<!-- 6 -->๐Ÿงช Testing" },
+  { message = "^chore|^ci",                           group = "<!-- 7 -->โš™๏ธ Miscellaneous Tasks", skip = true },
+  { body = ".*security",                              group = "<!-- 8 -->๐Ÿ›ก๏ธ Security" },
+  { message = "^revert",                              group = "<!-- 9 -->โ—€๏ธ Revert" },
+  { message = "^chore\\(release\\): prepare for", skip = true },
+  { message = "^chore\\(deps.*\\)",               skip = true },
+  { message = "^chore\\(pr\\)",                   skip = true },
+  { message = "^chore\\(pull\\)",                 skip = true },
+]
+# protect breaking changes from being skipped due to matching a skipping commit_parser
+protect_breaking_commits = true
+# filter out the commits that are not matched by commit parsers
+filter_commits = true
+# sort the tags topologically
+topo_order = false
+# sort the commits inside sections by oldest/newest order
+sort_commits = "newest"
+# limit the number of commits included in the changelog.
+limit_commits = 100000
diff --git a/.cliff.release.toml b/.cliff.release.toml
new file mode 100644
index 0000000..574a899
--- /dev/null
+++ b/.cliff.release.toml
@@ -0,0 +1,51 @@
+[changelog]
+# template for the changelog body
+# https://keats.github.io/tera/docs/#introduction
+body = """
+{% for group, commits in commits | group_by(attribute="group") %}
+  ## {{ group | striptags | trim | upper_first }}
+  {% for commit in commits %}
+    - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
+        {% if commit.breaking %}[**breaking**] {% endif %}\
+        {{ commit.message | upper_first }}\
+  {% endfor %}
+{% endfor %}
+"""
+# remove the leading and trailing s
+trim = true
+
+[git]
+# parse the commits based on https://www.conventionalcommits.org
+conventional_commits = true
+# filter out the commits that are not conventional
+filter_unconventional = true
+# process each line of a commit as an individual commit
+split_commits = false
+# regex for parsing and grouping commits
+commit_parsers = [
+  { message = "^feat",                                group = "<!-- 0 -->๐Ÿš€ Features" },
+  { message = "^fix|^bugfix|^hotfix",                 group = "<!-- 1 -->๐Ÿ› Bug Fixes" },
+  { message = "^refactor",                            group = "<!-- 2 -->๐Ÿšœ Refactor" },
+  { message = "^doc.*update changelog.*",             group = "<!-- 3 -->๐Ÿ“š Documentation", skip = true },
+  { message = "^doc",                                 group = "<!-- 3 -->๐Ÿ“š Documentation" },
+  { message = "^perf",                                group = "<!-- 4 -->โšก Performance" },
+  { message = "^style",                               group = "<!-- 5 -->๐ŸŽจ Styling" },
+  { message = "^test",                                group = "<!-- 6 -->๐Ÿงช Testing" },
+  { message = "^chore|^ci",                           group = "<!-- 7 -->โš™๏ธ Miscellaneous Tasks", skip = true },
+  { body = ".*security",                              group = "<!-- 8 -->๐Ÿ›ก๏ธ Security" },
+  { message = "^revert",                              group = "<!-- 9 -->โ—€๏ธ Revert" },
+  { message = "^chore\\(release\\): prepare for", skip = true },
+  { message = "^chore\\(deps.*\\)",               skip = true },
+  { message = "^chore\\(pr\\)",                   skip = true },
+  { message = "^chore\\(pull\\)",                 skip = true },
+]
+# protect breaking changes from being skipped due to matching a skipping commit_parser
+protect_breaking_commits = true
+# filter out the commits that are not matched by commit parsers
+filter_commits = true
+# sort the tags topologically
+topo_order = false
+# sort the commits inside sections by oldest/newest order
+sort_commits = "newest"
+# limit the number of commits included in the changelog.
+limit_commits = 100000
diff --git a/.github/workflows/push-create_tag.yaml b/.github/workflows/push-create_tag.yaml
new file mode 100644
index 0000000..effb650
--- /dev/null
+++ b/.github/workflows/push-create_tag.yaml
@@ -0,0 +1,49 @@
+name: Push [create tag]
+"on":
+  push:
+    branches:
+      - main
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: false
+jobs:
+  merge:
+    name: Push [create tag]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        if: "${{ ! startsWith(github.event.head_commit.message, 'docs: update changelog for ') }}"
+        uses: actions/checkout@v4.1.6
+        with:
+          token: ${{ secrets.PAT }}
+          fetch-depth: 0
+
+      - name: Get Next Version
+        if: "${{ ! startsWith(github.event.head_commit.message, 'docs: update changelog for ') }}"
+        id: semver
+        uses: ietf-tools/semver-action@v1.8.0
+        with:
+          token: ${{ github.token }}
+          branch: main
+          noVersionBumpBehavior: silent
+          noNewCommitBehavior: silent
+
+      - name: Update CHANGELOG.md
+        if: "${{ ! startsWith(github.event.head_commit.message, 'docs: update changelog for ') && steps.semver.outputs.next != '' }}"
+        uses: orhun/git-cliff-action@v3
+        with:
+          config: .cliff.git.toml
+          args: --tag ${{ steps.semver.outputs.next }}
+        env:
+          OUTPUT: CHANGELOG.md
+
+      - uses: EndBug/add-and-commit@v9.1.4
+        if: "${{ ! startsWith(github.event.head_commit.message, 'docs: update changelog for ') && steps.semver.outputs.next != '' }}"
+        with:
+          add: 'CHANGELOG.md'
+          commit: --signoff
+          default_author: github_actor
+          fetch: true
+          message: 'docs: update changelog for ${{ steps.semver.outputs.next }}'
+          tag: '${{ steps.semver.outputs.next }} --force'
+          tag_push: '--force'
diff --git a/.github/workflows/push-rebase.yaml b/.github/workflows/push-rebase.yaml
new file mode 100644
index 0000000..4b4049a
--- /dev/null
+++ b/.github/workflows/push-rebase.yaml
@@ -0,0 +1,22 @@
+name: Push [rebase]
+"on":
+  push:
+    branches:
+      - main
+concurrency:
+  group: push-rebase-main
+  cancel-in-progress: true
+jobs:
+  rebase:
+    name: Push [rebase]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Rebase all pull requests on push to the main branch
+        uses: peter-evans/rebase@v3.0.0
+        with:
+          base: main
+          exclude-drafts: true
+          exclude-labels: |
+            no-rebase
+            dependencies
+        if: "${{ startsWith(github.event.head_commit.message, 'docs: update changelog for ') }}"
diff --git a/.github/workflows/rebase-on-push-to-main-branch.yaml b/.github/workflows/rebase-on-push-to-main-branch.yaml
deleted file mode 100644
index 4c4d228..0000000
--- a/.github/workflows/rebase-on-push-to-main-branch.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
----
-name: Rebase on push to main branch
-"on":
-  push:
-    branches: [main]
-jobs:
-  rebase:
-    name: Rebase on push to main branch
-    runs-on: ubuntu-latest
-    steps:
-      - name: Rebase all pull requests on push to the main branch
-        uses: peter-evans/rebase@v3
-        with:
-          base: main
-          exclude-drafts: true
-          exclude-labels: |
-            dependencies
diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml
new file mode 100644
index 0000000..6838a31
--- /dev/null
+++ b/.github/workflows/tag-release.yaml
@@ -0,0 +1,34 @@
+name: Tag [release]
+"on":
+  push:
+    tags:
+      - v[0-9]+.[0-9]+.[0-9]+
+jobs:
+  tag_release:
+    name: Tag [release]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.1.6
+        with:
+          token: ${{ secrets.PAT }}
+          fetch-depth: 0
+
+      - name: Update release description .CHANGELOG.md
+        uses: orhun/git-cliff-action@v3.2.0
+        id: changelog-release
+        with:
+          config: .cliff.release.toml
+          args: --current --strip all
+        env:
+          OUTPUT: .CHANGELOG.md
+
+      - name: Create Release
+        uses: ncipollo/release-action@v1.14.0
+        with:
+          allowUpdates: true
+          draft: false
+          makeLatest: true
+          name: ${{ github.ref_name }}
+          body: ${{ steps.changelog-release.outputs.content }}
+          token: ${{ secrets.PAT }}
-- 
GitLab