diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml index 567cc05f40..c834bf5f8b 100644 --- a/.mokogitea/workflows/pr-check.yml +++ b/.mokogitea/workflows/pr-check.yml @@ -508,27 +508,14 @@ jobs: # ── Issue Reporter ────────────────────────────────────────────────────── report-issues: name: Report Issues - runs-on: ubuntu-latest needs: [branch-policy, validate] if: >- always() && needs.validate.result == 'failure' - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - sparse-checkout: automation/ci-issue-reporter.sh - sparse-checkout-cone-mode: false - - - name: "File issue for PR validation failure" - env: - MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - run: | - chmod +x automation/ci-issue-reporter.sh - ./automation/ci-issue-reporter.sh \ - --gate "PR Validation" \ - --workflow "PR Check" \ - --severity error \ - --details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed." + uses: ./.mokogitea/workflows/ci-issue-reporter.yml + with: + gate: "PR Validation" + workflow: "PR Check" + severity: error + details: "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed." + secrets: inherit diff --git a/.mokogitea/workflows/repo-health.yml b/.mokogitea/workflows/repo-health.yml index 9ef4cf6f26..092b60e549 100644 --- a/.mokogitea/workflows/repo-health.yml +++ b/.mokogitea/workflows/repo-health.yml @@ -671,42 +671,30 @@ jobs: # ═══════════════════════════════════════════════════════════════════════ # Issue Reporter — file issues for failed gates # ═══════════════════════════════════════════════════════════════════════ - report-issues: - name: "Report Issues" - runs-on: ubuntu-latest - needs: [access_check, scripts_governance, repo_health] + report-scripts: + name: "Report: Scripts Governance" + needs: [access_check, scripts_governance] if: >- always() && - (needs.scripts_governance.result == 'failure' || - needs.repo_health.result == 'failure') + needs.scripts_governance.result == 'failure' + uses: ./.mokogitea/workflows/ci-issue-reporter.yml + with: + gate: "Scripts Governance" + workflow: "Repo Health" + severity: error + details: "Scripts directory policy violations detected. Review required and allowed directories." + secrets: inherit - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - sparse-checkout: automation/ci-issue-reporter.sh - sparse-checkout-cone-mode: false - - - name: "File issues for failed gates" - env: - MOKOGITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }} - MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }} - run: | - chmod +x automation/ci-issue-reporter.sh - REPORTER="./automation/ci-issue-reporter.sh" - WF="Repo Health" - - report_gate() { - local gate="$1" result="$2" details="$3" - if [ "$result" = "failure" ]; then - "$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error - fi - } - - report_gate "Scripts Governance" \ - "${{ needs.scripts_governance.result }}" \ - "Scripts directory policy violations detected. Review required and allowed directories." - - report_gate "Repository Health" \ - "${{ needs.repo_health.result }}" \ - "Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary." + report-health: + name: "Report: Repository Health" + needs: [access_check, repo_health] + if: >- + always() && + needs.repo_health.result == 'failure' + uses: ./.mokogitea/workflows/ci-issue-reporter.yml + with: + gate: "Repository Health" + workflow: "Repo Health" + severity: error + details: "Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary." + secrets: inherit diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dae359bbd..59578248c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,9 @@ ### Fixed - API token edit: reject empty scope update requests with 400 instead of silently succeeding - Workflow token auth: pr-check.yml pre-release dispatch was silently failing due to env var / curl reference mismatch -- Workflow tokens: standardize all GA_TOKEN references to MOKOGITEA_TOKEN across pr-check, branch-protection, cleanup, deploy-manual, issue-branch, repo-health, version-set workflows +- Workflow tokens: standardize all GA_TOKEN/GITEA_TOKEN/GITEA_URL env vars to MOKOGITEA_TOKEN/MOKOGITEA_URL across all workflow files in 5 template repos + MokoCLI (65+ files) +- CI issue reporter: rename GITEA_TOKEN/GITEA_URL to MOKOGITEA_TOKEN/MOKOGITEA_URL in automation/ci-issue-reporter.sh +- Workflow sync trigger: add workflow_dispatch event, fix if-condition to allow manual dispatch, add PHP install step for non-PHP runners - Licensing API: handle DB write errors in UpdateLicense, UpdateTier, DeleteTier instead of silently discarding - Wiki API: fix findEntryForFile URL-decode fallback for non-ASCII page names - Metadata settings template 500 error: removed reference to deleted Version field @@ -47,9 +49,11 @@ ### Changed - Issue status seed defaults: Open, In Progress, Waiting, In Review, Closed, Won't Fix - Pre-release workflow: auto-bump skipped for non-Joomla repos (platform check) +- CI issue reporter: moved to MokoCLI (cli/ci_issue_reporter.sh), pr-check and repo-health now use ci-issue-reporter.yml reusable workflow ### Removed - Workflows: gitleaks.yml, npm-publish.yml, notify.yml, workflow-sync-trigger.yml, composer-publish.yml, deploy-manual.yml, security-audit.yml (not applicable to Go repo) +- automation/ci-issue-reporter.sh: moved to MokoCLI as centralized CLI tool ## [06.19.00] --- 2026-06-20 diff --git a/README.md b/README.md index b5855c10e3..a78ed1923c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Custom Gitea fork with enhanced wiki system, DLID licensing, issue statuses, org - **Wiki System** -- wikilinks, categories, backlinks, template transclusion, revision diffs, rename redirects, folder ACL, enhanced ToC, print view, ZIP export ([details](https://git.mokoconsulting.tech/MokoConsulting/.mokogitea/wiki/standards/Wiki-Features)) - **DLID Licensing** -- license management, entitlements, domain activations, ed25519-signed downloads +- **API Token Scope Editing** -- edit token scopes via API (PATCH) or web UI after creation - **Issue Statuses** -- custom workflow statuses per org with required baseline protection - **Org Metadata** -- per-repo metadata API (public GET, admin PUT), platform detection for versioning - **Project Board API** -- REST endpoints for project columns and cards diff --git a/automation/ci-issue-reporter.sh b/automation/ci-issue-reporter.sh deleted file mode 100644 index 65c47bafca..0000000000 --- a/automation/ci-issue-reporter.sh +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/env bash -# ============================================================================ -# Copyright (C) 2026 Moko Consulting -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Automation.CI -# INGROUP: moko-platform.Automation -# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform -# PATH: /automation/ci-issue-reporter.sh -# VERSION: 09.23.00 -# BRIEF: Creates or updates a Gitea issue when a CI gate fails. -# Deduplicates by searching open issues with the "ci-auto" label -# whose title matches the gate. If a matching issue exists, a comment -# is appended instead of opening a duplicate. -# ============================================================================ - -set -euo pipefail - -# ── Defaults ──────────────────────────────────────────────────────────────── -GITEA_URL="${GITEA_URL:-https://git.mokoconsulting.tech}" -GITEA_TOKEN="${GITEA_TOKEN:-}" -REPO="${GITHUB_REPOSITORY:-}" -RUN_URL="${GITHUB_SERVER_URL:-${GITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}" -LABEL_NAME="ci-auto" -LABEL_COLOR="#e11d48" - -GATE="" -DETAILS="" -SEVERITY="error" -WORKFLOW="" - -# ── Parse arguments ───────────────────────────────────────────────────────── -usage() { - cat </dev/null || echo "000") - - if [[ "$exists" == "200" ]]; then - # Check if label already exists - local found - found=$(curl -sf \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "${API}/labels" 2>/dev/null \ - | grep -o "\"name\":\"${LABEL_NAME}\"" || true) - - if [[ -z "$found" ]]; then - curl -sf -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - "${API}/labels" \ - -d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \ - > /dev/null 2>&1 || true - fi - fi -} - -# ── Search for existing open issue ────────────────────────────────────────── -find_existing_issue() { - # URL-encode the gate name for the query - local query - query=$(printf '%s' "[CI] ${GATE}" | sed 's/ /%20/g; s/\[/%5B/g; s/\]/%5D/g') - - local response - response=$(curl -sf \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \ - 2>/dev/null || echo "[]") - - # Extract the first matching issue number - echo "$response" \ - | grep -oP '"number":\s*\K[0-9]+' \ - | head -1 -} - -# ── Build issue body ──────────────────────────────────────────────────────── -build_body() { - local severity_badge - if [[ "$SEVERITY" == "error" ]]; then - severity_badge="**Severity:** Error" - else - severity_badge="**Severity:** Warning" - fi - - cat </dev/null) - - HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - "${API}/issues/${EXISTING}/comments" \ - -d "${COMMENT_JSON}" 2>/dev/null || echo "000") - - if [[ "$HTTP" == "201" ]]; then - echo "Commented on existing issue #${EXISTING}" - else - echo "WARNING: Failed to comment on issue #${EXISTING} (HTTP ${HTTP})" - fi -else - # Create new issue - ISSUE_BODY=$(build_body) - ISSUE_JSON=$(python3 -c " -import sys, json -body = sys.stdin.read() -print(json.dumps({ - 'title': sys.argv[1], - 'body': body, - 'labels': [] -}))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null) - - # Create the issue - RESPONSE=$(curl -sf -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - "${API}/issues" \ - -d "${ISSUE_JSON}" 2>/dev/null || echo "{}") - - ISSUE_NUM=$(echo "$RESPONSE" | grep -oP '"number":\s*\K[0-9]+' | head -1) - - if [[ -n "$ISSUE_NUM" ]]; then - # Apply label (separate call — more reliable across Gitea versions) - LABEL_ID=$(curl -sf \ - -H "Authorization: token ${GITEA_TOKEN}" \ - "${API}/labels" 2>/dev/null \ - | grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \ - | head -1 || true) - - if [[ -n "$LABEL_ID" ]]; then - curl -sf -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -H "Content-Type: application/json" \ - "${API}/issues/${ISSUE_NUM}/labels" \ - -d "{\"labels\":[${LABEL_ID}]}" \ - > /dev/null 2>&1 || true - fi - - echo "Created issue #${ISSUE_NUM}: ${TITLE}" - else - echo "WARNING: Failed to create issue" - echo "Response: ${RESPONSE}" - fi -fi