diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index baf7c703..e5c56438 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,18 @@ name: CI + +on: + pull_request: + types: + - opened + - synchronize + push: + branches: + - main + concurrency: cancel-in-progress: true group: ${{ github.workflow }}-${{ github.ref }} + jobs: ci: if: ${{ !cancelled() && ! failure() }} @@ -36,24 +47,24 @@ jobs: # renovate: github-runner - windows-2022 python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" + - '3.8' + - '3.9' + - '3.10' + - '3.11' + - '3.12' # Python 3.8 and 3.9 do not run on macos-14 which is using arm64 hardware. exclude: # renovate: github-runner - os: macos-14 - python-version: "3.8" + python-version: '3.8' # renovate: github-runner - os: macos-14 - python-version: "3.9" + python-version: '3.9' include: - os: macos-13 - python-version: "3.8" + python-version: '3.8' - os: macos-13 - python-version: "3.9" + python-version: '3.9' consistency: if: ${{ !cancelled() && ! failure() }} runs-on: ubuntu-22.04 @@ -69,11 +80,45 @@ jobs: - run: git diff - run: git status --porcelain - run: test -z "$(git status --porcelain)" -on: - pull_request: - types: - - opened - - synchronize - push: - branches: - - main + semantic-release: + name: Semantic Release + runs-on: ubuntu-22.04 + # Avoid semantic release for forked repository + if: github.event_name != 'pull_request' && github.repository == 'serious-scaffold/ss-python' + permissions: + contents: write + id-token: write + issues: write + pull-requests: write + needs: + - ci + - consistency + steps: + - id: generate-token + name: Generate a token with GitHub App if App ID exists + if: vars.BOT_APP_ID + uses: actions/create-github-app-token@a0de6af83968303c8c955486bf9739a57d23c7f1 # v1.10.0 + with: + app-id: ${{ vars.BOT_APP_ID }} + private-key: ${{ secrets.BOT_PRIVATE_KEY }} + - name: Warn if use GITHUB_TOKEN + run: | + if [ -z "${{ steps.generate-token.outputs.token || secrets.PAT }}" ]; then + echo "# :warning: GITHUB_TOKEN is used for semantic-release" >> $GITHUB_STEP_SUMMARY + echo "The GITHUB_TOKEN is used instead of a bot token or PAT and will not emit the released publish event for the released workflow." >> $GITHUB_STEP_SUMMARY + fi + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + with: + fetch-depth: 0 + - name: Setup Node.js + uses: actions/setup-node@v4.0.2 + with: + node-version: 'lts/*' + - name: Semantic Release + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token || secrets.PAT || secrets.GITHUB_TOKEN }} + run: > + npx + -p conventional-changelog-conventionalcommits@7 + -p semantic-release@23 + semantic-release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6072c6a2..560a2228 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,14 @@ name: Release + +on: + release: + types: + - published + +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + jobs: pages-build: runs-on: ubuntu-22.04 @@ -9,7 +19,7 @@ jobs: - uses: pdm-project/setup-pdm@568ddd69406b30de1774ec0044b73ae06e716aa4 # v4 with: cache: true - python-version: "3.12" + python-version: '3.12' version: 2.15.2 - id: pages name: Setup pages @@ -19,42 +29,22 @@ jobs: - run: make doc env: CI_PAGES_URL: ${{ steps.pages.outputs.base_url }} - - name: Generate release notes - run: make release-notes > release-notes.md - - name: Upload release notes - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - with: - name: release-notes - path: release-notes.md - name: Upload pages artifact uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: public - release-publish: - needs: pages-build + pages: + needs: + - pages-build permissions: - contents: write + id-token: write + pages: write runs-on: ubuntu-22.04 steps: - - name: Download release notes - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 - with: - name: release-notes - - id: prerelease - name: Determine prerelease - run: | - if [[ "${{ github.ref }}" =~ (a|b|rc)(0|[1-9][0-9]*)?$ ]]; then - echo "is_prerelease=true" > $GITHUB_OUTPUT - else - echo "is_prerelease=false" > $GITHUB_OUTPUT - fi - - name: Create GitHub release - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5 - with: - body_path: release-notes.md - prerelease: ${{ steps.prerelease.outputs.is_prerelease }} + - id: deployment + name: Deploy to GitHub Pages + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 container-publish: - needs: release-publish permissions: packages: write runs-on: ubuntu-22.04 @@ -90,40 +80,22 @@ jobs: strategy: matrix: python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" + - '3.8' + - '3.9' + - '3.10' + - '3.11' + - '3.12' package-publish: - needs: release-publish runs-on: ubuntu-22.04 steps: - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: pdm-project/setup-pdm@568ddd69406b30de1774ec0044b73ae06e716aa4 # v4 with: cache: true - python-version: "3.12" + python-version: '3.12' version: 2.15.2 - run: env | sort - env: PDM_PUBLISH_PASSWORD: ${{ secrets.PDM_PUBLISH_PASSWORD }} PDM_PUBLISH_USERNAME: ${{ vars.PDM_PUBLISH_USERNAME || '__token__' }} run: make publish - pages: - needs: release-publish - permissions: - id-token: write - pages: write - runs-on: ubuntu-22.04 - steps: - - id: deployment - name: Deploy to GitHub Pages - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 -on: - push: - tags: - - v?[0-9]+.[0-9]+.[0-9]+ - - v?[0-9]+.[0-9]+.[0-9]+-?a[0-9]* - - v?[0-9]+.[0-9]+.[0-9]+-?b[0-9]* - - v?[0-9]+.[0-9]+.[0-9]+-?rc[0-9]* diff --git a/.vscode/settings.json b/.vscode/settings.json index ea1ce1ad..628a3537 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,7 @@ "automodule", "cobertura", "commitlint", + "conventionalcommits", "datasource", "deepclean", "deflist", diff --git a/package.json b/package.json index 6e542715..71a24212 100644 --- a/package.json +++ b/package.json @@ -3,5 +3,123 @@ "extends": [ "@commitlint/config-conventional" ] + }, + "release": { + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "type": "build", + "release": false + }, + { + "type": "chore", + "release": false + }, + { + "type": "ci", + "release": false + }, + { + "type": "docs", + "release": false + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "perf", + "release": "patch" + }, + { + "type": "refactor", + "release": "patch" + }, + { + "type": "revert", + "release": "patch" + }, + { + "type": "style", + "release": false + }, + { + "type": "test", + "release": false + }, + { + "scope": "*no-release*", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "presetConfig": { + "types": [ + { + "type": "build", + "section": "Build" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "ci", + "section": "Continuous Integration" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance" + }, + { + "type": "refactor", + "section": "Refactor" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/github" + ], + "preset": "conventionalcommits" } } diff --git a/template/.vscode/settings.json b/template/.vscode/settings.json index ea1ce1ad..628a3537 100644 --- a/template/.vscode/settings.json +++ b/template/.vscode/settings.json @@ -18,6 +18,7 @@ "automodule", "cobertura", "commitlint", + "conventionalcommits", "datasource", "deepclean", "deflist", diff --git a/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/ci.yml.jinja b/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/ci.yml.jinja index 2b93a31b..023c55a8 100644 --- a/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/ci.yml.jinja +++ b/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/ci.yml.jinja @@ -1,8 +1,19 @@ [% from pathjoin("includes", "version_compare.jinja") import version_between -%] name: CI + +on: + pull_request: + types: + - opened + - synchronize + push: + branches: + - main + concurrency: cancel-in-progress: true group: {{ '${{ github.workflow }}-${{ github.ref }}' }} + jobs: ci: if: {{ '${{ !cancelled() && ! failure() }}' }} @@ -44,44 +55,44 @@ jobs: [%- endif %] python-version: [%- if version_between("3.8", min_py, max_py) %] - - "3.8" + - '3.8' [%- endif %] [%- if version_between("3.9", min_py, max_py) %] - - "3.9" + - '3.9' [%- endif %] [%- if version_between("3.10", min_py, max_py) %] - - "3.10" + - '3.10' [%- endif %] [%- if version_between("3.11", min_py, max_py) %] - - "3.11" + - '3.11' [%- endif %] [%- if version_between("3.12", min_py, max_py) %] - - "3.12" + - '3.12' [%- endif %] -[%- if project_name == "Serious Scaffold Python" %] [%- if "macos" in platforms and (version_between("3.8", min_py, max_py) or version_between("3.9", min_py, max_py)) %] # Python 3.8 and 3.9 do not run on macos-14 which is using arm64 hardware. exclude: [%- if version_between("3.8", min_py, max_py) %] # renovate: github-runner - os: macos-14 - python-version: "3.8" + python-version: '3.8' [%- endif %] [%- if version_between("3.9", min_py, max_py) %] # renovate: github-runner - os: macos-14 - python-version: "3.9" + python-version: '3.9' include: [%- endif %] [%- if version_between("3.8", min_py, max_py) %] - os: macos-13 - python-version: "3.8" + python-version: '3.8' [%- endif %] [%- if version_between("3.9", min_py, max_py) %] - os: macos-13 - python-version: "3.9" + python-version: '3.9' [%- endif %] [%- endif %] +[%- if project_name == "Serious Scaffold Python" %] consistency: if: {{ '${{ !cancelled() && ! failure() }}' }} runs-on: ubuntu-22.04 @@ -98,11 +109,47 @@ jobs: - run: git status --porcelain - run: test -z "$(git status --porcelain)" [%- endif %] -on: - pull_request: - types: - - opened - - synchronize - push: - branches: - - main + semantic-release: + name: Semantic Release + runs-on: ubuntu-22.04 + # Avoid semantic release for forked repository + if: github.event_name != 'pull_request' && github.repository == 'serious-scaffold/ss-python' + permissions: + contents: write + id-token: write + issues: write + pull-requests: write + needs: + - ci +[%- if project_name == "Serious Scaffold Python" %] + - consistency +[%- endif %] + steps: + - id: generate-token + name: Generate a token with GitHub App if App ID exists + if: vars.BOT_APP_ID + uses: actions/create-github-app-token@a0de6af83968303c8c955486bf9739a57d23c7f1 # v1.10.0 + with: + app-id: {{ '${{ vars.BOT_APP_ID }}' }} + private-key: {{ '${{ secrets.BOT_PRIVATE_KEY }}' }} + - name: Warn if use GITHUB_TOKEN + run: | + if [ -z "{{ '${{ steps.generate-token.outputs.token || secrets.PAT }}' }}" ]; then + echo "# :warning: GITHUB_TOKEN is used for semantic-release" >> $GITHUB_STEP_SUMMARY + echo "The GITHUB_TOKEN is used instead of a bot token or PAT and will not emit the released publish event for the released workflow." >> $GITHUB_STEP_SUMMARY + fi + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + with: + fetch-depth: 0 + - name: Setup Node.js + uses: actions/setup-node@v4.0.2 + with: + node-version: 'lts/*' + - name: Semantic Release + env: + GITHUB_TOKEN: {{ '${{ steps.generate-token.outputs.token || secrets.PAT || secrets.GITHUB_TOKEN }}' }} + run: > + npx + -p conventional-changelog-conventionalcommits@7 + -p semantic-release@23 + semantic-release diff --git a/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/release.yml.jinja b/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/release.yml.jinja index 10bc7f6e..d4dccaf6 100644 --- a/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/release.yml.jinja +++ b/template/[% if repo_platform == 'github' %].github[% endif %]/workflows/release.yml.jinja @@ -1,5 +1,15 @@ [% from pathjoin("includes", "version_compare.jinja") import version_between -%] name: Release + +on: + release: + types: + - published + +concurrency: + cancel-in-progress: true + group: {{ '${{ github.workflow }}-${{ github.ref }}' }} + jobs: pages-build: runs-on: ubuntu-22.04 @@ -10,7 +20,7 @@ jobs: - uses: pdm-project/setup-pdm@568ddd69406b30de1774ec0044b73ae06e716aa4 # v4 with: cache: true - python-version: "{{ default_py }}" + python-version: '{{ default_py }}' version: 2.15.2 - id: pages name: Setup pages @@ -20,42 +30,22 @@ jobs: - run: make doc env: CI_PAGES_URL: {{ '${{ steps.pages.outputs.base_url }}' }} - - name: Generate release notes - run: make release-notes > release-notes.md - - name: Upload release notes - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 - with: - name: release-notes - path: release-notes.md - name: Upload pages artifact uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: public - release-publish: - needs: pages-build + pages: + needs: + - pages-build permissions: - contents: write + id-token: write + pages: write runs-on: ubuntu-22.04 steps: - - name: Download release notes - uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 - with: - name: release-notes - - id: prerelease - name: Determine prerelease - run: | - if [[ {{ '"${{ github.ref }}"' }} =~ (a|b|rc)(0|[1-9][0-9]*)?$ ]]; then - echo "is_prerelease=true" > $GITHUB_OUTPUT - else - echo "is_prerelease=false" > $GITHUB_OUTPUT - fi - - name: Create GitHub release - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5 - with: - body_path: release-notes.md - prerelease: {{ '${{ steps.prerelease.outputs.is_prerelease }}' }} + - id: deployment + name: Deploy to GitHub Pages + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 container-publish: - needs: release-publish permissions: packages: write runs-on: ubuntu-22.04 @@ -92,49 +82,31 @@ jobs: matrix: python-version: [%- if version_between("3.8", min_py, max_py) %] - - "3.8" + - '3.8' [%- endif %] [%- if version_between("3.9", min_py, max_py) %] - - "3.9" + - '3.9' [%- endif %] [%- if version_between("3.10", min_py, max_py) %] - - "3.10" + - '3.10' [%- endif %] [%- if version_between("3.11", min_py, max_py) %] - - "3.11" + - '3.11' [%- endif %] [%- if version_between("3.12", min_py, max_py) %] - - "3.12" + - '3.12' [%- endif %] package-publish: - needs: release-publish runs-on: ubuntu-22.04 steps: - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: pdm-project/setup-pdm@568ddd69406b30de1774ec0044b73ae06e716aa4 # v4 with: cache: true - python-version: "{{ default_py }}" + python-version: '{{ default_py }}' version: 2.15.2 - run: env | sort - env: PDM_PUBLISH_PASSWORD: {{ '${{ secrets.PDM_PUBLISH_PASSWORD }}' }} PDM_PUBLISH_USERNAME: {{ '${{ vars.PDM_PUBLISH_USERNAME || \'__token__\' }}' }} run: make publish - pages: - needs: release-publish - permissions: - id-token: write - pages: write - runs-on: ubuntu-22.04 - steps: - - id: deployment - name: Deploy to GitHub Pages - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 -on: - push: - tags: - - v?[0-9]+.[0-9]+.[0-9]+ - - v?[0-9]+.[0-9]+.[0-9]+-?a[0-9]* - - v?[0-9]+.[0-9]+.[0-9]+-?b[0-9]* - - v?[0-9]+.[0-9]+.[0-9]+-?rc[0-9]* diff --git a/template/package.json b/template/package.json index 6e542715..71a24212 100644 --- a/template/package.json +++ b/template/package.json @@ -3,5 +3,123 @@ "extends": [ "@commitlint/config-conventional" ] + }, + "release": { + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "type": "build", + "release": false + }, + { + "type": "chore", + "release": false + }, + { + "type": "ci", + "release": false + }, + { + "type": "docs", + "release": false + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "perf", + "release": "patch" + }, + { + "type": "refactor", + "release": "patch" + }, + { + "type": "revert", + "release": "patch" + }, + { + "type": "style", + "release": false + }, + { + "type": "test", + "release": false + }, + { + "scope": "*no-release*", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "presetConfig": { + "types": [ + { + "type": "build", + "section": "Build" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "ci", + "section": "Continuous Integration" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance" + }, + { + "type": "refactor", + "section": "Refactor" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/github" + ], + "preset": "conventionalcommits" } }