|
| 1 | +name: "♿ RGAA Daily Audit" |
| 2 | + |
| 3 | +on: |
| 4 | + schedule: |
| 5 | + # Every weekday at 06:00 UTC (08:00 Paris time) |
| 6 | + - cron: "0 6 * * 1-5" |
| 7 | + workflow_dispatch: |
| 8 | + inputs: |
| 9 | + site_url: |
| 10 | + description: "URL to audit (leave empty for alpha deployment)" |
| 11 | + required: false |
| 12 | + type: string |
| 13 | + |
| 14 | +concurrency: |
| 15 | + group: rgaa-audit |
| 16 | + cancel-in-progress: true |
| 17 | + |
| 18 | +jobs: |
| 19 | + scan: |
| 20 | + name: "axe-core scan" |
| 21 | + runs-on: ubuntu-latest |
| 22 | + outputs: |
| 23 | + site_url: ${{ steps.url.outputs.site_url }} |
| 24 | + audit_date: ${{ steps.date.outputs.today }} |
| 25 | + steps: |
| 26 | + - name: Checkout repository |
| 27 | + uses: actions/checkout@v4 |
| 28 | + with: |
| 29 | + ref: alpha |
| 30 | + |
| 31 | + - name: Get current date |
| 32 | + id: date |
| 33 | + run: echo "today=$(date -u +%Y-%m-%d)" >> "$GITHUB_OUTPUT" |
| 34 | + |
| 35 | + - name: Setup pnpm |
| 36 | + uses: pnpm/action-setup@v4 |
| 37 | + |
| 38 | + - name: Setup Node |
| 39 | + uses: actions/setup-node@v4 |
| 40 | + with: |
| 41 | + node-version-file: ".nvmrc" |
| 42 | + cache: pnpm |
| 43 | + |
| 44 | + - name: Install dependencies |
| 45 | + run: pnpm install --frozen-lockfile |
| 46 | + |
| 47 | + - name: Install Playwright browsers |
| 48 | + run: pnpm playwright:install |
| 49 | + |
| 50 | + - name: Compute alpha deployment URL |
| 51 | + if: ${{ !inputs.site_url }} |
| 52 | + id: env |
| 53 | + uses: socialgouv/kontinuous/.github/actions/env@v1 |
| 54 | + with: |
| 55 | + branch: alpha |
| 56 | + |
| 57 | + - name: Set site URL |
| 58 | + id: url |
| 59 | + env: |
| 60 | + INPUT_SITE_URL: ${{ inputs.site_url }} |
| 61 | + SUBDOMAIN: ${{ steps.env.outputs.subdomain }} |
| 62 | + run: | |
| 63 | + if [ -n "$INPUT_SITE_URL" ]; then |
| 64 | + echo "site_url=$INPUT_SITE_URL" >> "$GITHUB_OUTPUT" |
| 65 | + else |
| 66 | + echo "site_url=https://${SUBDOMAIN}.ovh.fabrique.social.gouv.fr" >> "$GITHUB_OUTPUT" |
| 67 | + fi |
| 68 | +
|
| 69 | + - name: Wait for app to be ready |
| 70 | + env: |
| 71 | + SITE_URL: ${{ steps.url.outputs.site_url }} |
| 72 | + run: | |
| 73 | + for i in $(seq 1 10); do |
| 74 | + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$SITE_URL" 2>/dev/null || echo "000") |
| 75 | + if [ "$HTTP_CODE" = "200" ]; then |
| 76 | + echo "App is ready!" |
| 77 | + exit 0 |
| 78 | + fi |
| 79 | + echo "Health check returned $HTTP_CODE (attempt $i/10). Waiting 10s..." |
| 80 | + sleep 10 |
| 81 | + done |
| 82 | + echo "::error::App not ready after 100 seconds" |
| 83 | + exit 1 |
| 84 | +
|
| 85 | + - name: Run RGAA audit |
| 86 | + run: pnpm test:rgaa |
| 87 | + env: |
| 88 | + SITE_URL: ${{ steps.url.outputs.site_url }} |
| 89 | + PLAYWRIGHT_BASE_URL: ${{ steps.url.outputs.site_url }} |
| 90 | + CI: "true" |
| 91 | + |
| 92 | + - name: Upload axe-core results |
| 93 | + uses: actions/upload-artifact@v4 |
| 94 | + if: always() |
| 95 | + with: |
| 96 | + name: rgaa-results |
| 97 | + path: packages/app/rgaa-results.json |
| 98 | + retention-days: 30 |
| 99 | + |
| 100 | + report: |
| 101 | + name: "Claude report & wiki publish" |
| 102 | + needs: scan |
| 103 | + if: always() && needs.scan.result != 'cancelled' |
| 104 | + runs-on: ubuntu-latest |
| 105 | + permissions: |
| 106 | + contents: write |
| 107 | + id-token: write |
| 108 | + steps: |
| 109 | + - name: Checkout repository |
| 110 | + uses: actions/checkout@v4 |
| 111 | + with: |
| 112 | + ref: alpha |
| 113 | + |
| 114 | + - name: Download axe-core results |
| 115 | + uses: actions/download-artifact@v4 |
| 116 | + with: |
| 117 | + name: rgaa-results |
| 118 | + path: . |
| 119 | + |
| 120 | + - name: Run Claude Code — Generate report & publish to wiki |
| 121 | + id: claude |
| 122 | + uses: anthropics/claude-code-action@9d86c9b0c946914e9c71ac5ee1c008959cbfa9af # v1 |
| 123 | + with: |
| 124 | + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} |
| 125 | + show_full_output: true |
| 126 | + direct_prompt: | |
| 127 | + Tu es un expert accessibilité RGAA. Tu dois rédiger un rapport d'audit RGAA à partir des résultats axe-core ci-dessous, puis le publier sur le wiki GitHub. |
| 128 | +
|
| 129 | + ## Données |
| 130 | +
|
| 131 | + - URL auditée : ${{ needs.scan.outputs.site_url }} |
| 132 | + - Commit : ${{ github.sha }} |
| 133 | + - Date : ${{ needs.scan.outputs.audit_date }} |
| 134 | + - Fichier de résultats : `rgaa-results.json` (à la racine du repo) |
| 135 | +
|
| 136 | + ## Instructions |
| 137 | +
|
| 138 | + 1. **Lis le fichier `rgaa-results.json`** qui contient les résultats axe-core pour chaque page auditée. |
| 139 | +
|
| 140 | + 2. **Rédige un rapport Markdown** avec cette structure : |
| 141 | +
|
| 142 | + ``` |
| 143 | + # Rapport RGAA — Egapro |
| 144 | +
|
| 145 | + > Dernier audit : YYYY-MM-DD | Commit : SHA | URL : ... | Pages : N |
| 146 | +
|
| 147 | + ## Résumé |
| 148 | +
|
| 149 | + | Sévérité | Violations | |
| 150 | + |----------|-----------| |
| 151 | + | 🔴 Critique | N | |
| 152 | + | 🟠 Sérieuse | N | |
| 153 | + | 🟡 Modérée | N | |
| 154 | + | 🔵 Mineure | N | |
| 155 | + | **Total** | **N** | |
| 156 | +
|
| 157 | + ## Actions prioritaires |
| 158 | +
|
| 159 | + Liste numérotée des violations les plus impactantes, regroupées quand la même violation apparaît sur plusieurs pages. Pour chaque action : |
| 160 | + - Sévérité et règle axe-core |
| 161 | + - Pages concernées |
| 162 | + - Éléments CSS ciblés |
| 163 | + - **Suggestion de correction concrète** en utilisant les composants et classes DSFR (utilise le MCP dsfr pour vérifier) |
| 164 | +
|
| 165 | + ## Détail par page |
| 166 | +
|
| 167 | + ### Nom de la page (chemin) |
| 168 | + ✅ N règles passées | ⚠️ N incomplètes | ❌ N violations |
| 169 | +
|
| 170 | + | Règle | Sévérité | WCAG | Élément | Description | Correction suggérée | |
| 171 | + |-------|----------|------|---------|-------------|-------------------| |
| 172 | + ``` |
| 173 | +
|
| 174 | + 3. Pour le mapping WCAG → RGAA, utilise ces correspondances principales : |
| 175 | + - WCAG 1.1.1 → RGAA 1 (Images) |
| 176 | + - WCAG 1.3.x → RGAA 9 (Structure) |
| 177 | + - WCAG 1.4.x → RGAA 3 (Couleurs) et 10 (Présentation) |
| 178 | + - WCAG 2.1.x → RGAA 7 (Scripts) et 12 (Navigation) |
| 179 | + - WCAG 2.4.x → RGAA 12 (Navigation) |
| 180 | + - WCAG 3.1.x → RGAA 8 (Éléments obligatoires) |
| 181 | + - WCAG 4.1.x → RGAA 7 (Scripts) |
| 182 | +
|
| 183 | + 4. **Utilise le MCP `dsfr`** pour chercher les composants et classes appropriés dans tes suggestions de correction. |
| 184 | +
|
| 185 | + 5. **Publie le rapport sur le wiki GitHub** : |
| 186 | + ```bash |
| 187 | + git config --global user.name "github-actions[bot]" |
| 188 | + git config --global user.email "github-actions[bot]@users.noreply.github.com" |
| 189 | + git clone "https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }}.wiki.git" /tmp/wiki |
| 190 | + # Écris le rapport dans /tmp/wiki/RGAA-Audit-Report.md |
| 191 | + cd /tmp/wiki |
| 192 | + git add RGAA-Audit-Report.md |
| 193 | + git diff --cached --quiet || git commit -m "Update RGAA audit report — ${{ needs.scan.outputs.audit_date }}" |
| 194 | + git push |
| 195 | + ``` |
| 196 | +
|
| 197 | + 6. Ta réponse finale doit confirmer la publication et inclure un résumé des violations trouvées. |
| 198 | + claude_args: >- |
| 199 | + --max-turns 15 |
| 200 | + --mcp-config '{"mcpServers":{"dsfr":{"command":"npx","args":["-y","dsfr-mcp"]}}}' |
| 201 | + --allowedTools "Read,Bash(git *),Bash(cat *),mcp__dsfr__list_components,mcp__dsfr__get_component_doc,mcp__dsfr__search_components,mcp__dsfr__search_icons,mcp__dsfr__get_color_tokens" |
| 202 | + env: |
| 203 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
0 commit comments