name: Post-merge # Runs on every push to master (after CI workflow merges a PR). # Consolidated into 2 jobs (from 7) to reduce runner overhead: # detect-and-configure ──→ release-and-maintain # # Job 1: detect release commit, validate commit msg, configure repo # (branch protection, labels). # Job 2: release + publish + sync-wiki + vikunja + badges. # Individual steps are conditional on job 1 outputs. # # The badges step always runs (even on release commits) so version # badge picks up the new __version__. It runs last so it sees the # new version if release created one. # # When release creates a "release: vX.Y.Z" commit and tag, the publish # step builds and publishes the package to the Gitea PyPI registry. # The release commit's post-merge run still updates badges. Other # steps (sync-wiki, vikunja) skip on release commits. on: push: branches: [master] concurrency: group: post-merge-${{ github.ref }} cancel-in-progress: true env: PIP_BREAK_SYSTEM_PACKAGES: "1" PYTHONPATH: src CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} CI_GITEA_USERNAME: ${{ vars.CI_GITEA_USERNAME }} jobs: detect-and-configure: runs-on: docker container: image: git.oblachno.oblachno.fyi/oblachno-oss/runner-images/ci-base:latest credentials: username: ${{ vars.CI_GITEA_USERNAME }} password: ${{ secrets.CI_GITEA_API_TOKEN }} timeout-minutes: 10 defaults: run: shell: bash outputs: is-release: ${{ steps.check.outputs.is-release }} is-automated: ${{ steps.check.outputs.is-automated }} user-facing-changed: ${{ steps.detect.outputs.user-facing-changed }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up environment env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: make setup-image - name: Ensure branch protection and labels env: DEVX_REPO_NAME: devx DEVX_REPO_OWNER: oblachno-oss DEVX_STATUS_CHECKS: "CI / validate (pull_request)" run: | . .venv/bin/activate 2>/dev/null || true python3 -m devx.tools.configure_repo - name: Check if this is a release commit id: check run: | . .venv/bin/activate 2>/dev/null || true python3 -m devx.ci.detect_release_commit - name: Validate latest commit message if: steps.check.outputs.is-automated == 'false' run: | . .venv/bin/activate 2>/dev/null || true git log -1 --format=%B > commit-msg.txt python3 -m devx.ci.validate_commit_msg commit-msg.txt --branch master rm -f commit-msg.txt - name: Detect changed paths id: detect if: steps.check.outputs.is-release == 'false' run: | . .venv/bin/activate 2>/dev/null || true python3 -m devx.ci.classify_changes \ --base "HEAD~1" \ --head "HEAD" \ --github-output - name: Notify on failure if: failure() env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: | . .venv/bin/activate 2>/dev/null || true export PATH="$HOME/.local/bin:$PATH" python3 -m devx.ci.notify_failure \ --repo "${{ github.repository }}" \ --run-id "${{ github.run_id }}" \ --workflow "post-merge/detect-and-configure" \ --commit "${{ github.sha }}" \ --auto-login release-and-maintain: needs: [detect-and-configure] if: always() && needs.detect-and-configure.result == 'success' runs-on: docker container: image: git.oblachno.oblachno.fyi/oblachno-oss/runner-images/ci-full:latest credentials: username: ${{ vars.CI_GITEA_USERNAME }} password: ${{ secrets.CI_GITEA_API_TOKEN }} timeout-minutes: 15 outputs: tag: ${{ steps.release-tag.outputs.tag }} defaults: run: shell: bash steps: - uses: actions/checkout@v4 with: fetch-depth: 0 ref: master token: ${{ secrets.CI_GITEA_API_TOKEN }} - name: Set up environment env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: make setup-image EXTRAS=release - name: Configure git run: | git config user.name "devx-ci-bot" git config user.email "devx-ci-bot@oblachno.fyi" # --- release + publish (only if user-facing changes, not a release commit) --- - name: Run release id: release-tag if: needs.detect-and-configure.outputs.is-release == 'false' && needs.detect-and-configure.outputs.user-facing-changed == 'true' env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: | . .venv/bin/activate 2>/dev/null || true export PATH="$HOME/.local/bin:$PATH" python3 -m devx.ci.release - name: Build and publish release if: steps.release-tag.outputs.tag != '' env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: | . .venv/bin/activate 2>/dev/null || true export PATH="$HOME/.local/bin:$PATH" git fetch --tags git checkout "${{ steps.release-tag.outputs.tag }}" python3 -m devx.ci.publish "${{ steps.release-tag.outputs.tag }}" "${{ github.repository }}" --auto-login # --- sync-wiki + vikunja (skip on automated/release commits) --- - name: Sync documentation to wiki if: needs.detect-and-configure.outputs.is-automated == 'false' env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: | . .venv/bin/activate 2>/dev/null || true python3 -m devx.ci.sync_wiki --repo "${{ github.repository }}" --verify - name: Update Vikunja task if: needs.detect-and-configure.outputs.is-automated == 'false' env: VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }} DEVX_VIKUNJA_PROJECT_ID: "8" run: | . .venv/bin/activate 2>/dev/null || true python3 -m devx.ci.post_merge --git-sha "${{ github.sha }}" # --- badges (always run — even on release commits) --- - name: Generate and push badges env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} PRE_COMMIT_ALLOW_NO_CONFIG: "1" run: | . .venv/bin/activate 2>/dev/null || true export PATH="$HOME/.local/bin:$PATH" # Fetch latest master to pick up any release commit that was pushed git fetch origin master git reset --hard origin/master python3 -m devx.ci.push_badges - name: Notify on failure if: failure() env: CI_GITEA_API_TOKEN: ${{ secrets.CI_GITEA_API_TOKEN }} run: | . .venv/bin/activate 2>/dev/null || true export PATH="$HOME/.local/bin:$PATH" python3 -m devx.ci.notify_failure \ --repo "${{ github.repository }}" \ --run-id "${{ github.run_id }}" \ --workflow "post-merge/release-and-maintain" \ --commit "${{ github.sha }}" \ --auto-login