Skip to content
Merged
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
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: MPL-2.0-or-later
# Dependabot configuration for poly-ssg
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates

Expand All @@ -6,6 +7,8 @@ updates:
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
cooldown:
default-days: 7
schedule:
interval: "weekly"
day: "monday"
Expand All @@ -19,6 +22,8 @@ updates:
# OCaml/opam dependencies (rescript-wasm)
- package-ecosystem: "npm"
directory: "/engines/rescript-wasm"
cooldown:
default-days: 7
schedule:
interval: "weekly"
day: "monday"
Expand All @@ -34,6 +39,8 @@ updates:
# Forth Estate (if any npm deps added)
- package-ecosystem: "npm"
directory: "/engines/forth-estate"
cooldown:
default-days: 7
schedule:
interval: "weekly"
commit-message:
Expand All @@ -45,6 +52,8 @@ updates:
# Root project dependencies
- package-ecosystem: "npm"
directory: "/"
cooldown:
default-days: 7
schedule:
interval: "weekly"
commit-message:
Expand Down
303 changes: 35 additions & 268 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,275 +1,42 @@
# SPDX-License-Identifier: MPL-2.0-or-later
# Continuous Integration - Strict Mode
# All warnings treated as errors, all tests must pass
name: CI

# Preservation gates for the extracted, unqualified source archive.
name: Preservation CI
on:
push:
branches: [main, develop]
pull_request:
push:
branches: [main]

permissions: read-all

env:
OCAML_VERSION: "4.14.x"
# Treat warnings as errors
OCAML_COLOR: always

workflow_dispatch:
permissions:
contents: read
concurrency:
group: preservation-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# OCaml/ReScript-WASM build and test - STRICT MODE
rescript-wasm:
name: ReScript WASM-GC Backend
runs-on: ${{ matrix.os }}
permissions:
contents: read

strategy:
fail-fast: true # Fail immediately on first error
matrix:
os: [ubuntu-latest, macos-latest]
ocaml-version: ["4.14.x", "5.1.x"]

preservation:
name: Source history and preservation controls
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Set up OCaml ${{ matrix.ocaml-version }}
uses: ocaml/setup-ocaml@7c185f622998a008ba1b296d2d7c64e235629c23 # v3.6.1
with:
ocaml-compiler: ${{ matrix.ocaml-version }}
dune-cache: true

- name: Install dependencies
run: opam install . --deps-only --with-test -y
working-directory: engines/rescript-wasm

- name: Build with strict warnings
run: |
opam exec -- dune build --force
working-directory: engines/rescript-wasm

- name: Run all tests (must pass)
run: |
opam exec -- dune test
echo "All tests passed successfully"
working-directory: engines/rescript-wasm

- name: Generate sample WAT
run: |
opam exec -- dune exec rescript_wasm -- add > add.wat
opam exec -- dune exec rescript_wasm -- max > max.wat
opam exec -- dune exec rescript_wasm -- square > square.wat
opam exec -- dune exec rescript_wasm -- combined > combined.wat
echo "=== add.wat ==="
cat add.wat
working-directory: engines/rescript-wasm

- name: Install wasm-tools
if: runner.os == 'Linux'
run: |
curl -L https://github.com/bytecodealliance/wasm-tools/releases/download/v1.219.1/wasm-tools-1.219.1-x86_64-linux.tar.gz | tar xz
sudo mv wasm-tools-1.219.1-x86_64-linux/wasm-tools /usr/local/bin/

- name: Validate WAT output (strict)
if: runner.os == 'Linux'
run: |
# Validate all generated WAT files
for wat in add.wat max.wat square.wat combined.wat; do
echo "Validating $wat..."
wasm-tools validate --features gc "$wat" || echo "Note: WAT validation requires WASM-GC support"
done
working-directory: engines/rescript-wasm

- name: Upload WAT artifacts
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
name: wat-output-${{ matrix.os }}-${{ matrix.ocaml-version }}
path: engines/rescript-wasm/*.wat

# Forth Estate build
forth-estate:
name: Forth Estate SSG
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Install Gforth
run: sudo apt-get update && sudo apt-get install -y gforth

- name: Check Forth syntax
run: |
if [ -f forth-estate.fs ]; then
gforth forth-estate.fs -e bye
fi
working-directory: engines/forth-estate

# Ddraig (Idris 2) build and test
ddraig-ssg:
name: Ddraig SSG
runs-on: ubuntu-latest
container: ghcr.io/idris-community/idris2:latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Build Ddraig executable
run: |
cd engines/ddraig-ssg
idris2 Ddraig.idr -o ddraig

- name: Run Ddraig parser tests
run: |
cd engines/ddraig-ssg
./build/exec/ddraig test-markdown
./build/exec/ddraig test-frontmatter
./build/exec/ddraig test-full

- name: Build site with Ddraig
run: |
cd engines/ddraig-ssg
./build/exec/ddraig build ../../content ../../_site

# Strict lint and format checks - ALL MUST PASS
lint:
name: Lint & Format (Strict)
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Set up OCaml
uses: ocaml/setup-ocaml@7c185f622998a008ba1b296d2d7c64e235629c23 # v3.6.1
with:
ocaml-compiler: "4.14.x"

- name: Check for unsafe patterns (MUST PASS)
run: |
echo "=== Checking for unsafe patterns ==="
ERRORS=0

# Check for Obj.magic (type safety violation)
if grep -rn "Obj\.magic" engines/rescript-wasm/lib/; then
echo "ERROR: Obj.magic found - this violates type safety"
ERRORS=$((ERRORS + 1))
fi

# Check for Marshal (code execution risk)
if grep -rn "Marshal\." engines/rescript-wasm/lib/; then
echo "ERROR: Marshal found - this is a code execution risk"
ERRORS=$((ERRORS + 1))
fi

# Check for shell execution
if grep -rn "Unix\.system\|Unix\.open_process\|Sys\.command" engines/rescript-wasm/lib/; then
echo "ERROR: Shell execution found - security risk"
ERRORS=$((ERRORS + 1))
fi

if [ $ERRORS -gt 0 ]; then
echo "Found $ERRORS security issues"
exit 1
fi
echo "No unsafe patterns found"

- name: Check for catch-all patterns (MUST PASS)
run: |
echo "=== Checking for dangerous catch-all patterns ==="
# Look for standalone _ patterns in match statements (potential bug hiding)
# This is a heuristic check - not perfect but catches common issues
if grep -En "^\s*\|\s*_\s*->" engines/rescript-wasm/lib/*.ml | grep -v "failwith\|error\|assert\|raise"; then
echo "WARNING: Found catch-all patterns without explicit error handling"
echo "Consider using explicit pattern matching to avoid hiding bugs"
fi
echo "Pattern check complete"

- name: Report TODOs/FIXMEs
run: |
echo "=== TODOs and FIXMEs (informational) ==="
grep -rn "TODO\|FIXME\|XXX\|HACK" engines/rescript-wasm/lib/ || echo "None found"

- name: Check line lengths (soft limit 100)
run: |
echo "=== Lines over 100 characters (warnings) ==="
LONG_LINES=$(find engines/rescript-wasm/lib -name "*.ml" -exec awk 'length > 100 {count++} END {print count+0}' {} \; | awk '{s+=$1} END {print s}')
echo "Found $LONG_LINES lines over 100 characters"
if [ "$LONG_LINES" -gt 50 ]; then
echo "WARNING: Many long lines found, consider refactoring"
fi

# Security scanning job
security:
name: Security Checks
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read

steps:
- name: Checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Set up OCaml
uses: ocaml/setup-ocaml@7c185f622998a008ba1b296d2d7c64e235629c23 # v3.6.1
with:
ocaml-compiler: "4.14.x"

- name: Check dependencies for known vulnerabilities
run: |
echo "=== Checking for vulnerable dependencies ==="
opam list --installed --safe 2>/dev/null || true

- name: Scan for hardcoded secrets
run: |
echo "=== Scanning for hardcoded secrets ==="
# Check for common secret patterns
if grep -rEn "(password|secret|api_key|apikey|auth_token|private_key)\s*=\s*['\"][^'\"]+['\"]" engines/rescript-wasm/; then
echo "ERROR: Potential hardcoded secrets found"
exit 1
fi
echo "No hardcoded secrets found"

- name: Check .gitignore coverage
run: |
echo "=== Checking .gitignore coverage ==="
# Verify important patterns are ignored
if [ -f engines/rescript-wasm/.gitignore ]; then
for pattern in "_build/" "*.cmo" "*.cmi" ".env"; do
if grep -q "$pattern" engines/rescript-wasm/.gitignore; then
echo "OK: $pattern is ignored"
else
echo "WARNING: $pattern should be in .gitignore"
fi
done
fi

# Final validation job - runs after all others
validate:
name: Final Validation
runs-on: ubuntu-latest
permissions:
contents: read
needs: [rescript-wasm, forth-estate, ddraig-ssg, lint, security]

steps:
- name: All checks passed
run: |
echo "========================================="
echo "All CI checks passed successfully!"
echo "========================================="
echo "- ReScript-WASM: Build & Tests PASSED"
echo "- Forth Estate: Syntax PASSED"
echo "- Ddraig SSG: Build & Tests PASSED"
echo "- Lint & Format: PASSED"
echo "- Security Checks: PASSED"
echo "========================================="
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Verify preserved source identity and ancestry
run: bash scripts/verify-preservation.sh
- name: Reject corrupt provenance and unrelated history
run: bash tests/preservation-controls.sh
- name: Verify retired workflow bytes and reject changed archives
run: |
bash scripts/verify-archived-workflows.sh
bash tests/archived-workflow-controls.sh
- name: Validate output checker with independent positive and negative inputs
run: bash tests/output-validation-controls.sh
- name: Record qualification scope
run: |
printf '%s\n' \
'## Preservation receipt' \
"Subject: $(git rev-parse HEAD)" \
'Source history and output-checker regressions were exercised.' \
'Generator builds, BoJ parity, deployment and overall security qualification remain open in issue #2.' \
>> "$GITHUB_STEP_SUMMARY"
Loading
Loading