Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 287 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
name: Build / check
on:
workflow_call:
env:
CHECK_DIR: ".checks"
jobs:
build:
name: Snapshot + Checks
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Bepaal branch voor terugschrijven
id: commit-target
if: ${{ github.event_name == 'push' || github.event_name == 'release' }}
shell: bash
run: |
set -euo pipefail

case "${{ github.event_name }}" in
push)
TARGET_BRANCH="${GITHUB_REF#refs/heads/}"
;;
release)
TARGET_BRANCH="${{ github.event.release.target_commitish }}"
;;
esac

TARGET_BRANCH="${TARGET_BRANCH#refs/heads/}"

if [[ -z "$TARGET_BRANCH" ]]; then
echo "::error title=Doelbranch ontbreekt::Kan geen branch bepalen om snapshot en checkresultaten naar terug te schrijven."
exit 1
fi

if ! git fetch --no-tags origin "refs/heads/$TARGET_BRANCH:refs/remotes/origin/$TARGET_BRANCH"; then
echo "::error title=Doelbranch niet gevonden::Kan branch '$TARGET_BRANCH' niet ophalen om snapshot en checkresultaten terug te schrijven."
exit 1
fi

TARGET_SHA="$(git rev-parse "refs/remotes/origin/$TARGET_BRANCH")"
if [[ "$TARGET_SHA" != "$GITHUB_SHA" ]]; then
echo "::error title=Doelbranch is gewijzigd::Branch '$TARGET_BRANCH' staat op $TARGET_SHA, maar deze workflow draait voor commit $GITHUB_SHA. Snapshot en checkresultaten worden daarom niet automatisch teruggeschreven."
exit 1
fi

git checkout -B "$TARGET_BRANCH" "refs/remotes/origin/$TARGET_BRANCH"
echo "should_commit=true" >> "$GITHUB_OUTPUT"
echo "target_branch=$TARGET_BRANCH" >> "$GITHUB_OUTPUT"

- name: Prepare directories
run: |
mkdir -p static $CHECK_DIR

- name: Blokkeer raw.githubusercontent.com-links in bronbestand
shell: bash
run: |
set -euo pipefail
MATCH_FILE="$(mktemp)"
trap 'rm -f "$MATCH_FILE"' EXIT

GREP_STATUS=0
grep -nE 'raw\.githubusercontent\.com' index.html > "$MATCH_FILE" || GREP_STATUS=$?

if [[ "$GREP_STATUS" -gt 1 ]]; then
echo "Zoeken naar raw.githubusercontent.com-links in index.html mislukte."
exit "$GREP_STATUS"
fi

if [[ -s "$MATCH_FILE" ]]; then
if [[ "${{ github.event_name }}" == "release" ]]; then
echo "::error title=Publicatie geblokkeerd::index.html bevat verwijzingen naar raw.githubusercontent.com. Vervang deze links door verwijzingen naar docs.geostandaarden.nl."
echo "Gevonden verwijzingen in index.html:"
cat "$MATCH_FILE"
exit 1
fi

echo "::warning title=Controlewaarschuwing::index.html bevat verwijzingen naar raw.githubusercontent.com. Vervang deze links door verwijzingen naar docs.geostandaarden.nl."
echo "Gevonden verwijzingen in index.html:"
cat "$MATCH_FILE"
fi

- name: Generate HTML snapshot
run: npx respec --localhost --src index.html --out snapshot.html

- name: Prepare HTML for validation
run: |
mkdir -p $CHECK_DIR/site
cp snapshot.html $CHECK_DIR/site/
if [ -d media ]; then
cp -R media $CHECK_DIR/site/
fi

- name: Validate HTML
uses: anishathalye/proof-html@a76b66427e600c6992e8937a741afffd2264a613 # v2.2.3
continue-on-error: true
with:
directory: ${{ env.CHECK_DIR }}/site
check_html: true
check_css: false
disable_external: true
check_external_hash: false
enforce_https: false

- name: Check for alternateFormats via Node
id: config
run: |
# Maak config require-baar
cp ./js/config.js config.js
echo "module.exports = { respecConfig };" >> config.js

# Laat Node bepalen of er een PDF entry is (en exitcode gebruiken)
if node -e "const {respecConfig}=require('./config.js');
const ok = Array.isArray(respecConfig.alternateFormats)
&& respecConfig.alternateFormats.some(f => f && f.label==='pdf' && f.uri);
if (!ok) process.exit(1);" ; then
echo "grep=true" >> $GITHUB_OUTPUT
else
echo "grep=false" >> $GITHUB_OUTPUT
fi

- name: Copy pdf.js if needed
if: ${{ steps.config.outputs.grep == 'true' }}
run: cp .github/workflows/pdf.js .

- name: Generate PDF(s)
if: ${{ steps.config.outputs.grep == 'true' }}
run: |
cp ./js/config.js config.js
echo "module.exports = { respecConfig };" >> config.js
echo "var window = {respecMermaid:{createFigures:null}};" | cat - config.js > temp && mv temp config.js
npm install puppeteer
python3 -m http.server 8081 >/dev/null 2>&1 &
# wacht tot de lokale server draait
for i in {1..30}; do
if curl -sf http://localhost:8081/snapshot.html > /dev/null; then
break
fi
sleep 1
done
curl -sf http://localhost:8081/snapshot.html > /dev/null || (echo "Local HTTP server on 8081 not reachable"; exit 1)
rm -f *.pdf
PDF_SNAPSHOT_URL=http://localhost:8081/snapshot.html node pdf.js
mv *.pdf static/

- name: Serve snapshot over HTTP
run: |
cd "${{ github.workspace }}"
python3 -m http.server 8080 >/dev/null 2>&1 &
echo "SNAPSHOT_SERVER_PID=$!" >> "$GITHUB_ENV"

- name: Ensure Chrome + matching ChromeDriver for WCAG check
id: browser
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y google-chrome-stable unzip

CHROME_BIN="$(command -v google-chrome || command -v google-chrome-stable)"
CHROME_VERSION="$("$CHROME_BIN" --version | grep -oE '[0-9]+(\.[0-9]+){1,3}' | head -1)"
CHROME_MAJOR="${CHROME_VERSION%%.*}"
echo "Detected Chrome version: $CHROME_VERSION"

CHROMEDRIVER_VERSION="$(curl -fsSL "https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_${CHROME_MAJOR}")"
echo "Using ChromeDriver version: $CHROMEDRIVER_VERSION"

curl -fsSL \
-o /tmp/chromedriver-linux64.zip \
"https://storage.googleapis.com/chrome-for-testing-public/${CHROMEDRIVER_VERSION}/linux64/chromedriver-linux64.zip"
rm -rf /tmp/chromedriver-linux64
unzip -qo /tmp/chromedriver-linux64.zip -d /tmp
sudo mv /tmp/chromedriver-linux64/chromedriver /usr/local/bin/chromedriver
sudo chmod +x /usr/local/bin/chromedriver

"$CHROME_BIN" --version
/usr/local/bin/chromedriver --version

echo "chrome_bin=$CHROME_BIN" >> "$GITHUB_OUTPUT"
echo "chromedriver_bin=/usr/local/bin/chromedriver" >> "$GITHUB_OUTPUT"

- name: Run WCAG 2.2 check
run: |
for i in {1..30}; do
if curl -sf http://localhost:8080/snapshot.html > /dev/null; then
break
fi
sleep 1
done
curl -sf http://localhost:8080/snapshot.html > /dev/null || (echo "Local HTTP server on 8080 not reachable"; exit 1)

set -o pipefail
RAW_WCAG="$CHECK_DIR/wcag-raw.json"
if npx --yes @axe-core/cli@latest --stdout \
--chrome-path "${{ steps.browser.outputs.chrome_bin }}" \
--chromedriver-path "${{ steps.browser.outputs.chromedriver_bin }}" \
--tags wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22a,wcag22aa \
http://localhost:8080/snapshot.html > "$RAW_WCAG"; then
if jq '
[
.[] as $page |
$page.violations[] |
{
url: $page.url,
id,
impact,
description,
helpUrl,
nodes: [
.nodes[] |
{
target,
html,
failureSummary
}
]
}
]
' "$RAW_WCAG" > $CHECK_DIR/wcag-report.json; then
echo "WCAG output saved to $CHECK_DIR/wcag-report.json"
else
echo "{\"error\":\"WCAG-check mislukt: axe-output was geen geldige JSON. Zie logs voor details.\"}" > $CHECK_DIR/wcag-report.json
echo "WCAG output saved to $CHECK_DIR/wcag-report.json (error)"
fi
else
echo "{\"error\":\"WCAG-check mislukt (axe-cli). Zie logs voor details.\"}" > $CHECK_DIR/wcag-report.json
echo "WCAG output saved to $CHECK_DIR/wcag-report.json (error)"
fi
rm -f "$RAW_WCAG"

- name: Run link check with Muffet
run: |
sudo apt-get install -y golang-go
go install github.com/raviqqe/muffet@latest
echo "${HOME}/go/bin" >> $GITHUB_PATH
muffet \
--exclude '\.pdf$' \
--exclude '^https://gitdocumentatie.*' \
--exclude '^https://docs.geostandaarden.*' \
--exclude '.*localhost.*' \
--header 'user-agent:Curl' \
--ignore-fragments \
--one-page-only \
http://localhost:8080/snapshot.html \
--buffer-size 8192 > $CHECK_DIR/link-check.txt 2>&1 || echo "Geen linkfouten gevonden." > $CHECK_DIR/link-check.txt

- name: Stop snapshot HTTP server
if: always()
run: |
if [[ -n "${SNAPSHOT_SERVER_PID:-}" ]]; then
kill "$SNAPSHOT_SERVER_PID" || true
fi

- name: Commit all results
if: ${{ steps.commit-target.outputs.should_commit == 'true' }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

if [[ "${{ steps.config.outputs.grep }}" == "true" ]] && ls static/*.pdf 1>/dev/null 2>&1; then
mv static/*.pdf .
fi

git add snapshot.html $CHECK_DIR/*.txt $CHECK_DIR/*.json

if compgen -G "*.pdf" > /dev/null; then
git add *.pdf
fi

git commit -m "Snapshot + checks gegenereerd" || echo "No changes to commit"

TARGET_BRANCH="${{ steps.commit-target.outputs.target_branch }}"
git push origin HEAD:"$TARGET_BRANCH"

- name: Upload snapshot artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: snapshot
path: |
snapshot.html
static/*.pdf
media/**/*
js/**/*
data/**/*
20 changes: 20 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Main Workflow
on:
push:
branches:
- '**'
pull_request:
release:
types: [published]

jobs:
build:
uses: ./.github/workflows/build.yml

publish:
if: github.event_name == 'release'
needs: build
uses: ./.github/workflows/publish.yml
secrets:
GH_APP_ID: ${{ secrets.GH_APP_ID }}
GH_APP_PRIVATE_KEY: ${{ secrets.GH_APP_PRIVATE_KEY }}
40 changes: 40 additions & 0 deletions .github/workflows/pdf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const config = require("./config.js");

const alternateFormats = config.respecConfig.alternateFormats;
if (alternateFormats === undefined) {
console.warn("'alternateFormats' not found.");
} else {
const found = alternateFormats.find((element) => element.label === "pdf");
if (found === undefined) {
console.warn("PDF not selected as alternate format.");
} else if (found.uri === undefined) {
console.warn("PDF file name ('uri') missing.");
} else {
const name = found.uri;
console.log("Printing PDF with name: " + name);

const puppeteer = require("puppeteer");

const website_url =
process.env.PDF_SNAPSHOT_URL || "http://localhost:8081/snapshot.html";

(async () => {
const browser = await puppeteer.launch({
args: ["--no-sandbox", "--disable-setuid-sandbox"],
});
const page = await browser.newPage();
console.log("Opening snapshot at:", website_url);
await page.goto(website_url, { waitUntil: "networkidle0" });
await page.emulateMediaType("print");
await page.addStyleTag({ content: ".sidelabel {position: absolute}" });
const pdf = await page.pdf({
path: name,
margin: { top: "100px", right: "50px", bottom: "100px", left: "50px" },
printBackground: true,
format: "A4",
});

await browser.close();
})();
}
}
Loading
Loading