name: CodeQL

# Stub workflow — CodeQL Action is structurally incompatible with Gitea
# Actions (post-2026-05-06 SCM migration off GitHub).
#
# Why this is a stub, not a real CodeQL run:
#
# 1. github/codeql-action/init@v4 hits api.github.com endpoints
#    (CodeQL CLI bundle download + query-pack registry + telemetry)
#    that Gitea 1.22.x does NOT proxy. The act_runner has
#    GITHUB_SERVER_URL=https://git.moleculesai.app correctly set
#    (per saved memory feedback_act_runner_github_server_url and
#    /config.yaml on the operator host), but the Gitea API surface
#    simply does not implement the codeql-action bundle endpoints.
#    Observed in run 1d/3101 (2026-05-07): "::error::404 page not
#    found" inside the Initialize CodeQL step, before any analysis.
#
# 2. PR #35 attempted to mark `continue-on-error: true` at the JOB
#    level (correct YAML structure). Gitea 1.22.6 does NOT propagate
#    job-level continue-on-error to the commit-status API — every
#    matrix leg still posts `failure` to the status surface, which
#    keeps OVERALL=failure on every push to main + staging and
#    blocks visual auto-promote signals (#156).
#
# 3. Hongming policy decision (2026-05-07, task #156): CodeQL is
#    ADVISORY, not blocking, on Gitea Actions. We do not block PR
#    merge or staging→main promotion on CodeQL findings until we
#    have a Gitea-compatible static-analysis pipeline.
#
# What this stub preserves:
#
# - Workflow name `CodeQL` (referenced by auto-promote-staging.yml
#   line 67 as a workflow_run gate — must stay stable).
# - Job name template `Analyze (${{ matrix.language }})` and the
#   3-leg matrix (go, javascript-typescript, python). Branch
#   protection / required-check parity (#144) keys on these
#   exact context names.
# - merge_group + push + pull_request + schedule triggers, so the
#   merge-queue check name still resolves (per saved memory
#   feedback_branch_protection_check_name_parity).
#
# Re-enabling real analysis (future work):
#
# - Option A: self-hosted Semgrep / OpenGrep via a custom action
#   that doesn't hit api.github.com. Tracked behind #156 follow-up.
# - Option B: Sonatype Nexus IQ or similar, called from a step
#   that uses the Gitea-issued token only.
# - Option C: re-host this workflow on a small GitHub mirror used
#   ONLY for SAST (push-mirrored from Gitea). Acceptable trade-off
#   if/when payment is restored on a non-suspended GitHub org —
#   but per saved memory feedback_no_single_source_of_truth, we
#   should design for multi-vendor backup, not GitHub-only SAST.
#
# Until one of those lands, this stub keeps commit-status green so
# the auto-promote chain isn't permanently red on a tool we cannot
# actually run.
#
# Security policy: ADVISORY. We accept the residual risk of un-scanned
# pushes during this window. Compensating controls in place:
#   - secret-scan.yml runs on every push (active, blocks on hits)
#   - block-internal-paths.yml blocks forbidden file paths
#   - lint-curl-status-capture.yml catches one specific class of bug
#   - branch-protection-drift.yml + the merge_group required-checks
#     parity keep the gate surface stable
# These are not equivalent to CodeQL coverage. Status of the
# replacement plan is tracked in #156.

on:
  push:
    branches: [main, staging]
  pull_request:
    branches: [main, staging]
  # Required so the matrix legs emit a real result on the queued
  # commit instead of a false-green when merge queue is enabled.
  # Per saved memory feedback_branch_protection_check_name_parity:
  # path-filtered / matrix workflows MUST emit the protected name
  # via a job that always runs.
  merge_group:
    types: [checks_requested]
  schedule:
    # Weekly heartbeat. Cheap on a stub (the no-op job is ~5s) but
    # keeps the workflow visible in Gitea's Actions UI so the next
    # operator notices it's a stub instead of a missing surface.
    - cron: '30 1 * * 0'

# Workflow-level concurrency: only one stub run per branch/PR at a
# time. cancel-in-progress: false because a quick follow-up push
# shouldn't kill an in-flight run — even though the stub is fast,
# the contract should match a real CodeQL run for when we re-enable.
concurrency:
  group: codeql-${{ github.ref }}
  cancel-in-progress: false

permissions:
  actions: read
  contents: read
  # No security-events: write — we don't call the upload API anyway,
  # GHAS isn't on Gitea.

jobs:
  analyze:
    # Job NAME shape is load-bearing — auto-promote-staging.yml +
    # branch protection both key on `Analyze (${{ matrix.language }})`.
    # Do NOT rename without coordinating both surfaces.
    name: Analyze (${{ matrix.language }})
    runs-on: ubuntu-latest
    timeout-minutes: 5

    strategy:
      fail-fast: false
      matrix:
        language: [go, javascript-typescript, python]

    steps:
      # Single-step stub: log the policy decision + emit success.
      # Exit 0 explicitly so the commit-status API records `success`
      # for each of the three matrix legs.
      - name: CodeQL stub (advisory, non-blocking on Gitea)
        shell: bash
        run: |
          set -euo pipefail
          cat <<EOF
          CodeQL is currently ADVISORY on Gitea Actions (post-2026-05-06).
          Language matrix leg: ${{ matrix.language }}
          Reason: github/codeql-action/init@v4 calls api.github.com
                  bundle endpoints that Gitea 1.22.x does not implement.
                  Observed: "::error::404 page not found" in the Init
                  CodeQL step on every prior run.
          Policy: per Hongming decision 2026-05-07 (#156), CodeQL is
                  non-blocking until a Gitea-compatible SAST pipeline
                  lands. See workflow file header for replacement
                  options + compensating controls.
          Status: emitting success so auto-promote isn't permanently
                  red on a tool we cannot actually run today.
          EOF
          echo "::notice::CodeQL ${{ matrix.language }} — advisory stub, success."
