From 2d528308d013abff1a7f1ed58256888d22ef0775 Mon Sep 17 00:00:00 2001
From: Dmitriy Safronov <zimniy@cyberbrain.pw>
Date: Tue, 3 Sep 2024 11:14:25 +0400
Subject: [PATCH] feat: semver (#3)

Signed-off-by: Dmitriy Safronov <zimniy@cyberbrain.pw>
---
 .cliff.git.toml                        | 65 ++++++++++++++++++++++++++
 .cliff.release.toml                    | 51 ++++++++++++++++++++
 .github/dependabot.yml                 | 13 ++++--
 .github/workflows/lint.yaml            |  6 +--
 .github/workflows/push-create_tag.yaml | 49 +++++++++++++++++++
 .github/workflows/push-rebase.yaml     | 22 +++++++++
 .github/workflows/tag-release.yaml     | 34 ++++++++++++++
 .requirements/{2.16.txt => 9.txt}      |  2 +-
 8 files changed, 235 insertions(+), 7 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
 create mode 100644 .github/workflows/tag-release.yaml
 rename .requirements/{2.16.txt => 9.txt} (71%)

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/dependabot.yml b/.github/dependabot.yml
index fd0f210..82b398e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,5 +1,4 @@
 ---
-
 # To get started with Dependabot version updates, you'll need to specify which
 # package ecosystems to update and where the package manifests are located.
 # Please see the documentation for all configuration options:
@@ -7,7 +6,15 @@
 
 version: 2
 updates:
-  - package-ecosystem: "pip"      # See documentation for possible values
-    directory: "/.requirements"   # Location of package manifests
+  - package-ecosystem: "pip"
+    directory: "/.requirements"
+    schedule:
+      interval: "weekly"
+    labels:
+      - "dependencies"
+  - package-ecosystem: "github-actions"
+    directory: "/.github/workflows"
     schedule:
       interval: "weekly"
+    labels:
+      - "dependencies"
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index 2538fcb..9267c72 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -24,14 +24,14 @@ jobs:
     strategy:
       max-parallel: 2
       matrix:
-        ansible: ["2.16", "latest"]
+        ansible: ["9", "latest"]
 
     steps:
       - name: Check out the codebase
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Set up Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: "3.10"
           cache: "pip"
diff --git a/.github/workflows/push-create_tag.yaml b/.github/workflows/push-create_tag.yaml
new file mode 100644
index 0000000..965a7d7
--- /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@v4
+        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/tag-release.yaml b/.github/workflows/tag-release.yaml
new file mode 100644
index 0000000..10ce4c6
--- /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@v4
+        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 }}
diff --git a/.requirements/2.16.txt b/.requirements/9.txt
similarity index 71%
rename from .requirements/2.16.txt
rename to .requirements/9.txt
index fe23d3b..893a015 100644
--- a/.requirements/2.16.txt
+++ b/.requirements/9.txt
@@ -1,3 +1,3 @@
 # Requirements for ansible stable
-ansible>=2.16<2.17
+ansible >=9, <10
 ansible-lint
-- 
GitLab