-
Notifications
You must be signed in to change notification settings - Fork 3
137 lines (116 loc) · 5.01 KB
/
Copy pathqa.yml
File metadata and controls
137 lines (116 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
name: QA
# Server-side quality gate. The local git hooks (scripts/git-hooks) are
# bypassable with --no-verify and run only on the contributor's clone; this
# workflow is the non-bypassable layer. It runs the same suite as
# ./scripts/qa-all.bash plus a gitleaks secret scan over the full history.
#
# See CLAUDE/QA.md for what each stage checks.
on:
push:
branches: ["**"]
pull_request:
permissions:
contents: read
concurrency:
group: qa-${{ github.ref }}
cancel-in-progress: true
jobs:
qa-all:
name: qa-all.bash (8 gates)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
# shellcheck is preinstalled on ubuntu-latest runners; the rest are not.
- name: Install QA tooling
run: |
set -euo pipefail
python -m pip install --upgrade pip
# ruff is pinned from the single source of truth (.ruff-version, Plan 00071):
# its enabled ruleset IS its default set, which grows every release, so an
# unpinned ruff reddens main with no commit behind it.
pip install "ruff==$(cat .ruff-version)" semgrep ansible
shellcheck --version
ruff --version
semgrep --version
ansible-playbook --version
# Install the project's pinned role + collections (requirements.yml) so
# `ansible-playbook --syntax-check` can resolve every module/role the
# playbooks reference.
- name: Install Ansible requirements
run: ansible-galaxy install -r requirements.yml
- name: Install extension JS deps (for ESLint stage)
working-directory: extensions
run: npm ci
# ansible.cfg sets `vault_password_file = ./vault-pass.secret`, which is
# gitignored (a real secret) and absent on a clean checkout. `--syntax-check`
# is parse-only and never decrypts, but Ansible still needs the password
# file to EXIST at startup — provide a throwaway placeholder. It is gitignored
# so it can never be committed, and is never used to decrypt anything.
- name: Provide placeholder vault password (parse-only, never decrypts)
run: echo "ci-syntax-check-placeholder" > vault-pass.secret
- name: Run full QA suite
run: ./scripts/qa-all.bash
- name: Upload QA results
if: always()
uses: actions/upload-artifact@v4
with:
name: qa-results
path: /tmp/qa-results.json
if-no-files-found: ignore
helpers:
name: helper unit tests + extension version compat
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
# Helpers and their tests are stdlib-only by rule (helpers/CLAUDE.md), so no
# pip install step is needed — this job runs on the bare interpreter.
- name: Run helper unit tests
run: ./scripts/qa-helper-tests.bash
# ccy's rootless-engine guard (Plan 00072). The decision under test is a pure
# function of the engine's report, so this needs no podman, no docker and no
# daemon — which is the point: a rootful engine cannot be conjured on demand
# just to prove the guard notices one.
- name: Run ccy rootless-guard unit tests
run: ./scripts/test-ccy-rootless-guard.bash
# Static gate: every extensions/<uuid>/metadata.json must declare support for
# the GNOME Shell major that this branch's Fedora release (vars/fedora-version.yml)
# ships. Catches "metadata stale vs branch Fedora version" at PR time, before
# it reaches a desktop and GNOME flags the extension out of date.
- name: Check extension GNOME-Shell version compatibility
run: python3 -m helpers.gnome.check_extension_compat
gitleaks:
name: gitleaks secret scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# The gitleaks GitHub Action requires a paid GITLEAKS_LICENSE for
# organisation-owned repos. The gitleaks BINARY is free/OSS, so we run it
# directly. We scan the working tree (`gitleaks dir`), not full history:
# the historical PII is a known, accepted state (see Decision Gate 1), so a
# history scan would red-fail every run; a tree scan still blocks any NEW
# secret from being merged.
- name: Install gitleaks
run: |
set -euo pipefail
VER=8.30.1
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${VER}/gitleaks_${VER}_linux_x64.tar.gz" -o /tmp/gitleaks.tgz
tar -xzf /tmp/gitleaks.tgz -C /tmp gitleaks
sudo install /tmp/gitleaks /usr/local/bin/gitleaks
gitleaks version
- name: Scan working tree
run: gitleaks dir . --redact --no-banner --verbose