mirror of
https://github.com/triqbit/mt5-ai-xauusd-trader.git
synced 2026-11-02 06:56:15 +00:00
feat: implement semantic versioning and automated release orchestration (#709)
- Added docs/VERSIONING_POLICY.md defining SemVer and Conventional Commit rules. - Implemented .github/workflows/changelog.yml for automated CHANGELOG.md updates. - Implemented .github/workflows/commit-check.yml to enforce PR title standards. - Updated .pre-commit-config.yaml with conventional-pre-commit hook. - Refined .github/workflows/release.yml with automated version bumping, file synchronization, and Docker tagging. - Updated CHANGELOG.md with proper template and [Unreleased] section. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: andonly1348 <279141437+andonly1348@users.noreply.github.com>
This commit is contained in:
co-authored by
google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
andonly1348
parent
9d1bf600e0
commit
d7a5ed25ea
@@ -4,10 +4,11 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
paths-ignore:
|
paths:
|
||||||
- 'CHANGELOG.md'
|
- 'src/**'
|
||||||
- 'docs/**'
|
- 'main.py'
|
||||||
- '*.md'
|
- 'pyproject.toml'
|
||||||
|
- 'requirements*.txt'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -27,8 +28,6 @@ jobs:
|
|||||||
uses: Conventional-Changelog/github-action-generate-changelog@v1
|
uses: Conventional-Changelog/github-action-generate-changelog@v1
|
||||||
with:
|
with:
|
||||||
path-to-changelog: CHANGELOG.md
|
path-to-changelog: CHANGELOG.md
|
||||||
# This action by default updates the Unreleased section if no tag is provided
|
|
||||||
# or appends to the top.
|
|
||||||
|
|
||||||
- name: Commit and Push Changelog
|
- name: Commit and Push Changelog
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
name: Commit Message Check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- edited
|
||||||
|
- synchronize
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
pull-requests: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
main:
|
||||||
|
name: Validate PR Title
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: amannn/action-semantic-pull-request@v5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
# Configure which types are allowed.
|
||||||
|
types: |
|
||||||
|
feat
|
||||||
|
fix
|
||||||
|
perf
|
||||||
|
docs
|
||||||
|
refactor
|
||||||
|
style
|
||||||
|
test
|
||||||
|
chore
|
||||||
|
ci
|
||||||
|
# Configure that a scope must be always lowercase.
|
||||||
|
subjectPattern: ^(?![A-Z]).+$
|
||||||
|
# If the PR title contains a breaking change (!), it must be at the end of the type.
|
||||||
|
# e.g. "feat!: breaking change"
|
||||||
@@ -4,7 +4,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: 'Version to release (e.g. 1.0.0). If empty, will be calculated from commits.'
|
description: 'Version to release (e.g. 1.2.0). If empty, will be calculated from commits.'
|
||||||
required: false
|
required: false
|
||||||
prerelease:
|
prerelease:
|
||||||
description: 'Is this a pre-release?'
|
description: 'Is this a pre-release?'
|
||||||
@@ -14,9 +14,6 @@ on:
|
|||||||
description: 'Dry run (do not tag or publish)'
|
description: 'Dry run (do not tag or publish)'
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -140,22 +137,26 @@ jobs:
|
|||||||
needs: validate
|
needs: validate
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Calculate Version (for Docker tagging)
|
||||||
|
id: tag_calc
|
||||||
|
if: github.event.inputs.version == ''
|
||||||
|
uses: mathieudutour/github-tag-action@v6.2
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
dry_run: true
|
||||||
|
|
||||||
- name: Determine Version
|
- name: Determine Version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
|
||||||
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
|
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
||||||
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
echo "TAG=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
||||||
echo "TAG=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "VERSION=0.0.0-draft" >> $GITHUB_OUTPUT
|
|
||||||
echo "TAG=v0.0.0-draft" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
TAG="${GITHUB_REF#refs/tags/}"
|
echo "VERSION=${{ steps.tag_calc.outputs.new_version }}" >> $GITHUB_OUTPUT
|
||||||
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
echo "TAG=${{ steps.tag_calc.outputs.new_tag }}" >> $GITHUB_OUTPUT
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
@@ -189,44 +190,38 @@ jobs:
|
|||||||
name: Create Release
|
name: Create Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
if: (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false') || startsWith(github.ref, 'refs/tags/v')
|
if: github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Calculate Next Version
|
- name: Calculate Next Version
|
||||||
id: tag_action
|
id: tag_action
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.version == ''
|
if: github.event.inputs.version == ''
|
||||||
uses: mathieudutour/github-tag-action@v6.2
|
uses: mathieudutour/github-tag-action@v6.2
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
dry_run: true
|
dry_run: true
|
||||||
|
create_tag: false
|
||||||
|
|
||||||
- name: Determine Version
|
- name: Determine Version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
|
||||||
if [[ "${{ github.event.inputs.version }}" != "" ]]; then
|
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
||||||
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
echo "TAG=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
||||||
echo "TAG=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "VERSION=${{ steps.tag_action.outputs.new_version }}" >> $GITHUB_OUTPUT
|
|
||||||
echo "TAG=${{ steps.tag_action.outputs.new_tag }}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
TAG="${GITHUB_REF#refs/tags/}"
|
echo "VERSION=${{ steps.tag_action.outputs.new_version }}" >> $GITHUB_OUTPUT
|
||||||
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
echo "TAG=${{ steps.tag_action.outputs.new_tag }}" >> $GITHUB_OUTPUT
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Update Version and Changelog
|
- name: Update Version and Changelog
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false'
|
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.VERSION }}"
|
VERSION="${{ steps.version.outputs.VERSION }}"
|
||||||
DATE=$(date +%Y-%m-%d)
|
DATE=$(date +%Y-%m-%d)
|
||||||
|
|
||||||
# Update version strings using a shared variable
|
|
||||||
echo "Updating version to ${VERSION} in pyproject.toml and src/__init__.py"
|
echo "Updating version to ${VERSION} in pyproject.toml and src/__init__.py"
|
||||||
sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
|
sed -i "s/^version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
|
||||||
|
|
||||||
@@ -247,8 +242,7 @@ jobs:
|
|||||||
git push origin main
|
git push origin main
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create Git Tag (if manual)
|
- name: Create Git Tag
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false'
|
|
||||||
run: |
|
run: |
|
||||||
TAG="${{ steps.version.outputs.TAG }}"
|
TAG="${{ steps.version.outputs.TAG }}"
|
||||||
git config user.name "github-actions[bot]"
|
git config user.name "github-actions[bot]"
|
||||||
|
|||||||
@@ -51,3 +51,13 @@ repos:
|
|||||||
name: pip-audit (dependency safety)
|
name: pip-audit (dependency safety)
|
||||||
args:
|
args:
|
||||||
- --requirement=requirements-ci.txt
|
- --requirement=requirements-ci.txt
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
# 4. Conventional Commits — enforce commit message format
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
- repo: https://github.com/compilerla/conventional-pre-commit
|
||||||
|
rev: v3.2.0
|
||||||
|
hooks:
|
||||||
|
- id: conventional-pre-commit
|
||||||
|
stages: [commit-msg]
|
||||||
|
args: [feat, fix, perf, docs, refactor, style, test, chore, ci]
|
||||||
|
|||||||
@@ -45,7 +45,13 @@ To enable automated changelog generation and version bumping, all commits to the
|
|||||||
Indicate a breaking change by adding a `!` after the type/scope or by adding `BREAKING CHANGE:` in the footer of the commit message. This triggers a **MAJOR** version bump.
|
Indicate a breaking change by adding a `!` after the type/scope or by adding `BREAKING CHANGE:` in the footer of the commit message. This triggers a **MAJOR** version bump.
|
||||||
*Example*: `feat!: overhaul risk management engine`
|
*Example*: `feat!: overhaul risk management engine`
|
||||||
|
|
||||||
## 3. Tagging & Release Strategy
|
## 3. Pull Request Labels (Optional)
|
||||||
|
While Conventional Commits are the primary driver, PR labels can be used to override or supplement automation:
|
||||||
|
- `release:major`: Forces a MAJOR version bump.
|
||||||
|
- `release:minor`: Forces a MINOR version bump.
|
||||||
|
- `release:patch`: Forces a PATCH version bump.
|
||||||
|
|
||||||
|
## 4. Tagging & Release Strategy
|
||||||
|
|
||||||
### Stable Releases
|
### Stable Releases
|
||||||
- **Branch**: `main`
|
- **Branch**: `main`
|
||||||
@@ -61,16 +67,18 @@ Indicate a breaking change by adding a `!` after the type/scope or by adding `BR
|
|||||||
- **Tag Format**: `vMAJOR.MINOR.PATCH-alpha.N` or `vMAJOR.MINOR.PATCH-beta.N`
|
- **Tag Format**: `vMAJOR.MINOR.PATCH-alpha.N` or `vMAJOR.MINOR.PATCH-beta.N`
|
||||||
- **Use Case**: Early testing of experimental features.
|
- **Use Case**: Early testing of experimental features.
|
||||||
|
|
||||||
## 4. Automated Workflow
|
## 5. Automated Workflow
|
||||||
|
|
||||||
1. **Automated Changelog**: Every push to `main` triggers the `changelog.yml` workflow, which appends new conventional commits to the `CHANGELOG.md` file under the `[Unreleased]` section.
|
1. **Automated Changelog**: Every push to `main` triggers the `changelog.yml` workflow, which appends new conventional commits to the `CHANGELOG.md` file under the `[Unreleased]` section.
|
||||||
2. **Version Bump Automation**: The `Release Orchestration` (`release.yml`) workflow:
|
2. **Commit Validation**: Every Pull Request is checked by the `commit-check.yml` workflow to ensure it meets Conventional Commit standards.
|
||||||
- Calculates the next version based on commit history if not manually provided.
|
3. **Local Enforcement**: A pre-commit hook ensures that local commits adhere to the standard before they are even pushed.
|
||||||
|
4. **Version Bump Automation**: The `Release Orchestration` (`release.yml`) workflow:
|
||||||
|
- Calculates the next version based on commit history.
|
||||||
- Updates `pyproject.toml` and `src/__init__.py`.
|
- Updates `pyproject.toml` and `src/__init__.py`.
|
||||||
- Transitions `[Unreleased]` content in `CHANGELOG.md` to a new versioned header.
|
- Transitions `[Unreleased]` content in `CHANGELOG.md` to a new versioned header.
|
||||||
- Creates a new Git tag and GitHub Release.
|
- Creates a new Git tag and GitHub Release.
|
||||||
|
|
||||||
## 5. Guidance for Version Bumping
|
## 6. Guidance for Version Bumping
|
||||||
|
|
||||||
| Change Type | Version Component | Example Commit |
|
| Change Type | Version Component | Example Commit |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
|
|||||||
Reference in New Issue
Block a user