diff options
| author | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-04 19:47:58 +0300 |
|---|---|---|
| committer | Mehmet Samet Duman <yongdohyun@projecttick.org> | 2026-04-04 19:47:58 +0300 |
| commit | 8d0d919fbf43230148da7533519ed0ffdfaa4197 (patch) | |
| tree | 27e352d6ca09910e577ec27a10659814e88b15b9 /.github/workflows/ci.yml | |
| parent | fce202465d4fede9e19d4d057eebbaa702291652 (diff) | |
| download | Project-Tick-8d0d919fbf43230148da7533519ed0ffdfaa4197.tar.gz Project-Tick-8d0d919fbf43230148da7533519ed0ffdfaa4197.zip | |
NOISSUE add GitHub Actions scripts for PR preparation and review management
- Introduced `prepare.js` to validate PR mergeability and branch targeting.
- Added `reviews.js` for automated review dismissal and posting.
- Created `run` script to execute actions with GitHub context.
- Implemented rate limiting in `withRateLimit.js` to manage API requests.
- Added `supportedBranches.js` for branch classification logic.
- Created `update-pinned.sh` for updating pinned dependencies.
- Added `pinned.json` to manage pinned Nix dependencies.
- Updated `libnbtplusplus` version from 2.3 to 3.0 and adjusted README accordingly.
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to '.github/workflows/ci.yml')
| -rw-r--r-- | .github/workflows/ci.yml | 717 |
1 files changed, 717 insertions, 0 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..c0dde03ab0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,717 @@ +# Copyright (C) Project Tick Contributors +# SPDX-License-Identifier: MIT +# +# ╔══════════════════════════════════════════════════════════════════╗ +# ║ Project Tick — Monolithic CI Orchestrator ║ +# ║ ║ +# ║ Every push, pull request, merge queue entry, tag push, and ║ +# ║ manual dispatch flows through this single gate. Nothing runs ║ +# ║ unless this file says so. ║ +# ╚══════════════════════════════════════════════════════════════════╝ + +name: CI + +on: + push: + branches: ["**"] + tags: ["*"] + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + pull_request_target: + types: [closed, labeled] + merge_group: + types: [checks_requested] + workflow_dispatch: + inputs: + force-all: + description: "Force run all project CI pipelines" + type: boolean + default: false + build-type: + description: "Build configuration for meshmc/forgewrapper" + type: choice + options: [Debug, Release] + default: Debug + +permissions: + contents: read + +concurrency: + group: >- + ci-${{ + github.event_name == 'merge_group' && github.event.merge_group.head_ref || + github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || + github.ref + }} + cancel-in-progress: ${{ github.event_name != 'merge_group' }} + +# ════════════════════════════════════════════════════════════════════ +# Environment — shared across all jobs +# ════════════════════════════════════════════════════════════════════ +env: + CI: true + FORCE_ALL: ${{ github.event.inputs.force-all == 'true' || github.event_name == 'merge_group' }} + +jobs: + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 0 — Gate & Triage ║ + # ╚════════════════════════════════════════════════════════════════╝ + + gate: + name: "Gate" + runs-on: ubuntu-latest + if: >- + !(github.event_name == 'pull_request_target' && !github.event.pull_request.merged) && + !(github.event_name == 'pull_request' && github.event.pull_request.draft) + outputs: + # ── Event classification ──────────────────────────────────── + is_push: ${{ steps.classify.outputs.is_push }} + is_pr: ${{ steps.classify.outputs.is_pr }} + is_merge_queue: ${{ steps.classify.outputs.is_merge_queue }} + is_tag: ${{ steps.classify.outputs.is_tag }} + is_release_tag: ${{ steps.classify.outputs.is_release_tag }} + is_backport: ${{ steps.classify.outputs.is_backport }} + is_dependabot: ${{ steps.classify.outputs.is_dependabot }} + is_master: ${{ steps.classify.outputs.is_master }} + is_scheduled: ${{ steps.classify.outputs.is_scheduled }} + run_level: ${{ steps.classify.outputs.run_level }} + # ── Per-project change flags ──────────────────────────────── + archived_changed: ${{ steps.changes.outputs.archived_changed }} + cgit_changed: ${{ steps.changes.outputs.cgit_changed }} + ci_changed: ${{ steps.changes.outputs.ci_changed }} + cmark_changed: ${{ steps.changes.outputs.cmark_changed }} + corebinutils_changed: ${{ steps.changes.outputs.corebinutils_changed }} + forgewrapper_changed: ${{ steps.changes.outputs.forgewrapper_changed }} + genqrcode_changed: ${{ steps.changes.outputs.genqrcode_changed }} + hooks_changed: ${{ steps.changes.outputs.hooks_changed }} + images4docker_changed: ${{ steps.changes.outputs.images4docker_changed }} + json4cpp_changed: ${{ steps.changes.outputs.json4cpp_changed }} + libnbtplusplus_changed: ${{ steps.changes.outputs.libnbtplusplus_changed }} + meshmc_changed: ${{ steps.changes.outputs.meshmc_changed }} + meta_changed: ${{ steps.changes.outputs.meta_changed }} + mnv_changed: ${{ steps.changes.outputs.mnv_changed }} + neozip_changed: ${{ steps.changes.outputs.neozip_changed }} + tomlplusplus_changed: ${{ steps.changes.outputs.tomlplusplus_changed }} + github_changed: ${{ steps.changes.outputs.github_changed }} + root_changed: ${{ steps.changes.outputs.root_changed }} + changed_projects: ${{ steps.changes.outputs.changed_projects }} + changed_count: ${{ steps.changes.outputs.changed_count }} + # ── Commit parsing ────────────────────────────────────────── + commit_type: ${{ steps.changes.outputs.commit_type }} + commit_scope: ${{ steps.changes.outputs.commit_scope }} + commit_subject: ${{ steps.changes.outputs.commit_subject }} + commit_breaking: ${{ steps.changes.outputs.commit_breaking }} + commit_message: ${{ steps.changes.outputs.commit_message }} + # ── Build config ──────────────────────────────────────────── + build_type: ${{ steps.classify.outputs.build_type }} + + steps: + - name: Harden runner + uses: step-security/harden-runner@v2 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Classify event + id: classify + run: | + set -euo pipefail + + REF="${GITHUB_REF:-}" + EVENT="${{ github.event_name }}" + ACTOR="${{ github.actor }}" + HEAD_REF="${{ github.head_ref || '' }}" + BASE_REF="${{ github.base_ref || '' }}" + + # ── Booleans ────────────────────────────────────────── + echo "is_push=$([[ "$EVENT" == "push" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_pr=$([[ "$EVENT" == "pull_request" || "$EVENT" == "pull_request_target" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_merge_queue=$([[ "$EVENT" == "merge_group" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_tag=$([[ "$REF" == refs/tags/* ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_release_tag=$([[ "$REF" =~ ^refs/tags/(meshmc|neozip|mnv|cmark|forgewrapper)- ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_backport=$([[ "$HEAD_REF" == backport-* || "$HEAD_REF" == backport/* ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_dependabot=$([[ "$ACTOR" == "dependabot[bot]" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_master=$([[ "$REF" == "refs/heads/master" || "$REF" == "refs/heads/main" ]] && echo true || echo false)" >> "$GITHUB_OUTPUT" + echo "is_scheduled=false" >> "$GITHUB_OUTPUT" + + # ── Run level ───────────────────────────────────────── + # full = merge queue, tags, master push, manual force-all + # standard = normal PR, branch push + # minimal = dependabot, backport, draft + if [[ "$EVENT" == "merge_group" ]] || \ + [[ "$REF" == refs/tags/* ]] || \ + [[ "$REF" == "refs/heads/master" ]] || \ + [[ "${{ env.FORCE_ALL }}" == "true" ]]; then + echo "run_level=full" >> "$GITHUB_OUTPUT" + elif [[ "$ACTOR" == "dependabot[bot]" ]]; then + echo "run_level=minimal" >> "$GITHUB_OUTPUT" + elif [[ "$HEAD_REF" == backport-* ]]; then + echo "run_level=standard" >> "$GITHUB_OUTPUT" + else + echo "run_level=standard" >> "$GITHUB_OUTPUT" + fi + + # ── Build type ──────────────────────────────────────── + if [[ "$REF" == refs/tags/* ]]; then + echo "build_type=Release" >> "$GITHUB_OUTPUT" + elif [[ -n "${{ github.event.inputs.build-type || '' }}" ]]; then + echo "build_type=${{ github.event.inputs.build-type }}" >> "$GITHUB_OUTPUT" + else + echo "build_type=Debug" >> "$GITHUB_OUTPUT" + fi + + - name: Detect changes + id: changes + if: github.event_name != 'pull_request_target' + uses: ./.github/actions/change-analysis + with: + event-name: ${{ github.event_name }} + base-sha: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || '' }} + head-sha: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha || '' }} + before-sha: ${{ github.event.before || '' }} + current-sha: ${{ github.sha }} + pr-title: ${{ github.event.pull_request.title || '' }} + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 1 — Lint & Commit Checks (fast, blocks everything) ║ + # ╚════════════════════════════════════════════════════════════════╝ + + lint: + name: "Lint" + needs: gate + if: needs.gate.outputs.is_pr == 'true' + uses: ./.github/workflows/ci-lint.yml + with: + run-level: ${{ needs.gate.outputs.run_level }} + changed-projects: ${{ needs.gate.outputs.changed_projects }} + secrets: inherit + + dependency-review: + name: "Dependency Review" + needs: gate + if: needs.gate.outputs.is_pr == 'true' + uses: ./.github/workflows/repo-dependency-review.yml + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 2 — Per-Project Build & Test Matrices ║ + # ║ ║ + # ║ Each project runs only when its directory changed, or when ║ + # ║ force-all / merge-queue / master push triggers them all. ║ + # ║ Inner reusable workflows handle their own matrices. ║ + # ╚════════════════════════════════════════════════════════════════╝ + + # ── C / System Projects ───────────────────────────────────────── + mnv: + name: "MNV" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.mnv_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/mnv-ci.yml + permissions: + contents: read + secrets: inherit + + cgit: + name: "CGit" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.cgit_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/cgit-ci.yml + permissions: + contents: read + secrets: inherit + + cmark: + name: "CMark" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.cmark_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/cmark-ci.yml + permissions: + contents: read + secrets: inherit + + corebinutils: + name: "CoreBinutils" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.corebinutils_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/corebinutils-ci.yml + permissions: + contents: read + secrets: inherit + + genqrcode: + name: "GenQRCode" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.genqrcode_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/genqrcode-ci.yml + permissions: + contents: read + secrets: inherit + + neozip: + name: "NeoZip" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.neozip_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/neozip-ci.yml + permissions: + contents: read + secrets: inherit + + # ── C++ / Library Projects ────────────────────────────────────── + json4cpp: + name: "JSON4CPP" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.json4cpp_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/json4cpp-ci.yml + permissions: + contents: read + security-events: write + secrets: inherit + + libnbtplusplus: + name: "libNBT++" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.libnbtplusplus_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/libnbtplusplus-ci.yml + permissions: + contents: read + secrets: inherit + + tomlplusplus: + name: "TOML++" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.tomlplusplus_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/tomlplusplus-ci.yml + permissions: + contents: read + secrets: inherit + + # ── Java / Minecraft Projects ─────────────────────────────────── + meshmc: + name: "MeshMC" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.meshmc_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/meshmc-build.yml + with: + build-type: ${{ needs.gate.outputs.build_type }} + permissions: + contents: read + id-token: write + packages: write + secrets: inherit + + forgewrapper: + name: "ForgeWrapper" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.forgewrapper_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/forgewrapper-build.yml + permissions: + contents: read + secrets: inherit + + # ── Container & Docker ────────────────────────────────────────── + images4docker: + name: "Docker Images" + needs: [gate, lint] + if: >- + always() && + !cancelled() && + (needs.lint.result == 'success' || needs.lint.result == 'skipped') && + (needs.gate.outputs.images4docker_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/images4docker-build.yml + permissions: + contents: read + packages: write + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 3 — Extended Analysis (only on full runs) ║ + # ║ ║ + # ║ Fuzz testing, CodeQL, static analysis — expensive jobs that ║ + # ║ run on merge queue, master, or manual dispatch only. ║ + # ╚════════════════════════════════════════════════════════════════╝ + + cmark-fuzz: + name: "CMark Fuzz" + needs: [gate, cmark] + if: >- + always() && + !cancelled() && + needs.cmark.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.cmark_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/cmark-fuzz.yml + permissions: + contents: read + secrets: inherit + + json4cpp-fuzz: + name: "JSON4CPP Fuzz" + needs: [gate, json4cpp] + if: >- + always() && + !cancelled() && + needs.json4cpp.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.json4cpp_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/json4cpp-fuzz.yml + permissions: + contents: read + secrets: inherit + + json4cpp-amalgam: + name: "JSON4CPP Amalgamation" + needs: [gate, json4cpp] + if: >- + always() && + !cancelled() && + needs.json4cpp.result == 'success' && + (needs.gate.outputs.json4cpp_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/json4cpp-amalgam.yml + permissions: + contents: read + secrets: inherit + + tomlplusplus-fuzz: + name: "TOML++ Fuzz" + needs: [gate, tomlplusplus] + if: >- + always() && + !cancelled() && + needs.tomlplusplus.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.tomlplusplus_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/tomlplusplus-fuzz.yml + permissions: + contents: read + security-events: write + secrets: inherit + + neozip-fuzz: + name: "NeoZip Fuzz" + needs: [gate, neozip] + if: >- + always() && + !cancelled() && + needs.neozip.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.neozip_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/neozip-fuzz.yml + permissions: + contents: read + secrets: inherit + + meshmc-codeql: + name: "MeshMC CodeQL" + needs: [gate, meshmc] + if: >- + always() && + !cancelled() && + needs.meshmc.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.meshmc_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/meshmc-codeql.yml + permissions: + contents: read + security-events: write + secrets: inherit + + mnv-codeql: + name: "MNV CodeQL" + needs: [gate, mnv] + if: >- + always() && + !cancelled() && + needs.mnv.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.mnv_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/mnv-codeql.yml + permissions: + contents: read + security-events: write + secrets: inherit + + neozip-codeql: + name: "NeoZip CodeQL" + needs: [gate, neozip] + if: >- + always() && + !cancelled() && + needs.neozip.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.neozip_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/neozip-codeql.yml + permissions: + contents: read + security-events: write + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 4 — Containers & Nix (only on full + meshmc changes) ║ + # ╚════════════════════════════════════════════════════════════════╝ + + meshmc-container: + name: "MeshMC Container" + needs: [gate, meshmc] + if: >- + always() && + !cancelled() && + needs.meshmc.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.meshmc_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/meshmc-container.yml + permissions: + contents: read + packages: write + secrets: inherit + + meshmc-nix: + name: "MeshMC Nix" + needs: [gate, meshmc] + if: >- + always() && + !cancelled() && + needs.meshmc.result == 'success' && + needs.gate.outputs.run_level == 'full' && + (needs.gate.outputs.meshmc_changed == 'true' || needs.gate.outputs.run_level == 'full') + uses: ./.github/workflows/meshmc-nix.yml + permissions: + contents: read + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 5 — Documentation (master push only) ║ + # ╚════════════════════════════════════════════════════════════════╝ + + json4cpp-docs: + name: "JSON4CPP Docs" + needs: [gate, json4cpp] + if: >- + always() && + !cancelled() && + needs.json4cpp.result == 'success' && + needs.gate.outputs.is_master == 'true' && + needs.gate.outputs.is_push == 'true' && + needs.gate.outputs.json4cpp_changed == 'true' + uses: ./.github/workflows/json4cpp-publish-docs.yml + permissions: + contents: write + secrets: inherit + + tomlplusplus-docs: + name: "TOML++ Docs" + needs: [gate, tomlplusplus] + if: >- + always() && + !cancelled() && + needs.tomlplusplus.result == 'success' && + needs.gate.outputs.is_master == 'true' && + needs.gate.outputs.is_push == 'true' && + needs.gate.outputs.tomlplusplus_changed == 'true' + uses: ./.github/workflows/tomlplusplus-gh-pages.yml + permissions: + contents: write + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 6 — Backport Automation (PR merge events) ║ + # ╚════════════════════════════════════════════════════════════════╝ + + backport: + name: "Backport" + needs: gate + if: >- + github.event_name == 'pull_request_target' && + github.event.pull_request.merged == true && + contains(toJSON(github.event.pull_request.labels.*.name), 'backport') + uses: ./.github/workflows/meshmc-backport.yml + permissions: + contents: write + pull-requests: write + actions: write + secrets: inherit + + merge-blocking: + name: "Merge Blocking PR" + needs: gate + if: >- + github.event_name == 'pull_request_target' && + github.event.pull_request.merged == true && + contains(toJSON(github.event.pull_request.labels.*.name), 'status: blocking') + uses: ./.github/workflows/meshmc-merge-blocking-pr.yml + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 7 — Release (tag pushes only) ║ + # ╚════════════════════════════════════════════════════════════════╝ + + meshmc-release: + name: "MeshMC Release" + needs: [gate, meshmc] + if: >- + always() && + !cancelled() && + needs.gate.outputs.is_tag == 'true' && + startsWith(github.ref, 'refs/tags/meshmc-') + uses: ./.github/workflows/meshmc-build.yml + with: + build-type: Release + environment: Release + permissions: + contents: read + id-token: write + packages: write + secrets: inherit + + neozip-release: + name: "NeoZip Release" + needs: gate + if: >- + needs.gate.outputs.is_tag == 'true' && + startsWith(github.ref, 'refs/tags/neozip-') + uses: ./.github/workflows/neozip-release.yml + permissions: + contents: read + secrets: inherit + + # ╔════════════════════════════════════════════════════════════════╗ + # ║ STAGE 8 — Final Verdicts ║ + # ║ ║ + # ║ Merge queue and branch protection rules check this job. ║ + # ║ It collects results from all stages and reports pass/fail. ║ + # ╚════════════════════════════════════════════════════════════════╝ + + verdict: + name: "CI Verdict" + if: always() + needs: + - gate + - lint + - mnv + - cgit + - cmark + - corebinutils + - genqrcode + - neozip + - json4cpp + - libnbtplusplus + - tomlplusplus + - meshmc + - forgewrapper + - images4docker + - cmark-fuzz + - json4cpp-fuzz + - json4cpp-amalgam + - tomlplusplus-fuzz + - neozip-fuzz + - meshmc-codeql + - mnv-codeql + - neozip-codeql + - meshmc-container + - meshmc-nix + runs-on: ubuntu-latest + steps: + - name: Evaluate results + run: | + set -euo pipefail + + echo "## CI Verdict" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "| Job | Result |" >> "$GITHUB_STEP_SUMMARY" + echo "|-----|--------|" >> "$GITHUB_STEP_SUMMARY" + + FAILED=false + + check_job() { + local name="$1" + local result="$2" + local icon="⬜" + case "$result" in + success) icon="✅" ;; + failure) icon="❌"; FAILED=true ;; + cancelled) icon="⏹️" ;; + skipped) icon="⏭️" ;; + esac + echo "| $name | $icon $result |" >> "$GITHUB_STEP_SUMMARY" + } + + check_job "Gate" "${{ needs.gate.result }}" + check_job "Lint" "${{ needs.lint.result }}" + check_job "MNV" "${{ needs.mnv.result }}" + check_job "CGit" "${{ needs.cgit.result }}" + check_job "CMark" "${{ needs.cmark.result }}" + check_job "CoreBinutils" "${{ needs.corebinutils.result }}" + check_job "GenQRCode" "${{ needs.genqrcode.result }}" + check_job "NeoZip" "${{ needs.neozip.result }}" + check_job "JSON4CPP" "${{ needs.json4cpp.result }}" + check_job "libNBT++" "${{ needs.libnbtplusplus.result }}" + check_job "TOML++" "${{ needs.tomlplusplus.result }}" + check_job "MeshMC" "${{ needs.meshmc.result }}" + check_job "ForgeWrapper" "${{ needs.forgewrapper.result }}" + check_job "Docker Images" "${{ needs.images4docker.result }}" + check_job "CMark Fuzz" "${{ needs.cmark-fuzz.result }}" + check_job "JSON4CPP Fuzz" "${{ needs.json4cpp-fuzz.result }}" + check_job "JSON4CPP Amalg" "${{ needs.json4cpp-amalgam.result }}" + check_job "TOML++ Fuzz" "${{ needs.tomlplusplus-fuzz.result }}" + check_job "NeoZip Fuzz" "${{ needs.neozip-fuzz.result }}" + check_job "MeshMC CodeQL" "${{ needs.meshmc-codeql.result }}" + check_job "MNV CodeQL" "${{ needs.mnv-codeql.result }}" + check_job "NeoZip CodeQL" "${{ needs.neozip-codeql.result }}" + check_job "MeshMC Docker" "${{ needs.meshmc-container.result }}" + check_job "MeshMC Nix" "${{ needs.meshmc-nix.result }}" + + echo "" >> "$GITHUB_STEP_SUMMARY" + + if [[ "$FAILED" == "true" ]]; then + echo "**Result: FAILED** — one or more required jobs failed." >> "$GITHUB_STEP_SUMMARY" + exit 1 + else + echo "**Result: PASSED** — all executed jobs succeeded." >> "$GITHUB_STEP_SUMMARY" + fi |
