# KEYSTONE CI: gate every pull request and keep a signed in-toto attestation of the verdict.
# The PR diff is sent to https://cainstudio.online/api/v1/keystone-ci/check (it is not stored; the signed verdict and findings are).
# FAIL_ON: BLOCK (default) fails the check only on CRITICAL findings; set it to REVIEW to also fail on HIGH ones.
name: KEYSTONE CI
on:
  pull_request:
permissions:
  contents: read
  pull-requests: read
jobs:
  keystone-ci:
    runs-on: ubuntu-latest
    steps:
      - name: Gate and attest the pull request
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          PR: ${{ github.event.pull_request.number }}
          HEAD_SHA: ${{ github.event.pull_request.head.sha }}
          FAIL_ON: BLOCK
        run: |
          gh api "repos/$REPO/pulls/$PR" -H "Accept: application/vnd.github.diff" > pr.diff
          python3 - <<'PY'
          import json, os, sys, urllib.request
          BASE = "https://cainstudio.online/api/v1/keystone-ci"
          def esc(s, prop=False):
              s = str(s).replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")
              return s.replace(":", "%3A").replace(",", "%2C") if prop else s
          body = {"diff": open("pr.diff", encoding="utf-8", errors="replace").read(), "repo": os.environ["REPO"],
                  "pr": int(os.environ["PR"]), "head_sha": os.environ["HEAD_SHA"]}
          req = urllib.request.Request(BASE + "/check", data=json.dumps(body).encode(),
                                       headers={"content-type": "application/json"})
          r = json.load(urllib.request.urlopen(req, timeout=90))
          json.dump(r["attestation"], open("keystone-ci.intoto.json", "w"))
          for f in r["findings"]:
              level = "error" if f["severity"] in ("CRITICAL", "HIGH") else "warning"
              loc = ""
              if f.get("file"):
                  loc = " file=" + esc(f["file"], True) + (",line=%d" % f["line"] if f.get("line") else "")
              print("::%s%s::%s" % (level, loc, esc("[%s] %s: %s" % (f["severity"], f["check"], f["detail"]))))
          with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as s:
              s.write("### KEYSTONE CI: %s\n\n![KEYSTONE CI](%s/badge/%s.svg)\n\n" % (r["verdict"], BASE, r["run_id"]))
              s.write("[Signed attestation](%s/attestations/%s) | %d findings\n" % (BASE, r["run_id"], len(r["findings"])))
          order = ["PASS", "REVIEW", "BLOCK"]
          sys.exit(1 if order.index(r["verdict"]) >= order.index(os.environ.get("FAIL_ON", "BLOCK")) else 0)
          PY
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: keystone-ci-attestation
          path: keystone-ci.intoto.json
