Skip to content

Latest commit

 

History

History
319 lines (254 loc) · 14.6 KB

File metadata and controls

319 lines (254 loc) · 14.6 KB

CI

Hosted CI is split by concern in .github/workflows/ci.yml. Local verification remains the fastest pre-handoff gate.

Hosted Jobs

Required pull-request lanes:

  • Go tests (ubuntu-latest): root dependency check and all Go module tests.
  • Go tests (macos-14): OS signal for Go tests on Darwin/arm64.
  • Reachable vulnerabilities: scripts/vulncheck-go-modules.sh.
  • Runtime race detector: scripts/test-runtime-race.sh on Linux for the explicit shared-state runtime package list.
  • CLI build: go build ./cmd/gowdk.
  • Dead code: scripts/check-dead-code.sh runs pinned Staticcheck U1000 and x/tools deadcode analyzers over the focused compiler, CLI, and runtime-contract package sets documented below.
  • VS Code extension: extension version sync, Node syntax checks, and unit tests.
  • Documentation links: scripts/check-docs-links.sh.
  • Documentation style: scripts/check-docs-style.sh checks heading order and language-tagged fenced code blocks. Long prose paragraphs are warnings.
  • Removed source syntax: scripts/check-removed-syntax.sh (runs in the Documentation links job) flags pre-v0.6.0 source forms that the script lists but that linger in docs as if still active. They are allowed only in changelog, migration, and diagnostics references, in test fixtures, and on lines carrying a removed-syntax-ok marker.
  • Example reports: scripts/check-example-reports.sh.
  • Parser fuzz smoke: scripts/test-parser-fuzz.sh with GOWDK_FUZZTIME=1000x.
  • Generated app integration: scripts/test-generated-app-integration.sh.
  • Generated output determinism: scripts/test-generated-output-determinism.sh.
  • Generated output smoke: representative build output, binary, WASM, SSR, CSS, SEO, component asset, and login example checks.

The release lanes live outside the pull-request CI workflow:

  • .github/workflows/golangci-lint.yml: manual strict lint workflow. It runs scripts/check-golangci-lint.sh with the pinned GolangCI-Lint version. Do not make this a required pull-request lane until the repository is clean under the configured lint set.
  • .github/workflows/release-dry-run.yml: scheduled weekly and manual; packages CLI/VS Code artifacts, writes checksums, and uploads workflow artifacts. This is GitHub-only because it uses Actions artifact upload.
  • .github/workflows/release.yml: tag/manual publishing workflow for real releases.
  • .github/workflows/release-smoke.yml: manual post-publish artifact smoke across Linux, macOS Intel, macOS arm64, and Windows.

Local Gates

Run the same local checks before handoff when relevant:

  • Go/module checks:

    scripts/check-root-deps.sh
    scripts/check-supply-chain-pins.sh
    scripts/test-go-modules.sh
    scripts/vulncheck-go-modules.sh
    go build ./cmd/gowdk
    scripts/check-dead-code.sh
    scripts/check-golangci-lint.sh
  • VS Code extension checks:

    node editors/vscode/scripts/sync-version.js --check
    node --check editors/vscode/extension.js
    node --check editors/vscode/extension-core.js
    node --test editors/vscode/*.test.js
  • Docs and example report checks:

    scripts/check-docs-links.sh
    scripts/check-docs-style.sh
    scripts/check-removed-syntax.sh
    scripts/check-doc-versions.sh
    scripts/check-example-reports.sh
  • Docs-site production check:

    (cd docs-site && scripts/install-tailwind-linux.sh && scripts/build-production.sh && scripts/smoke-production.sh)
  • Fuzz, integration, and determinism checks:

    scripts/test-parser-fuzz.sh
    GOWDK_FUZZTIME=100000x scripts/test-parser-fuzz.sh
    GOWDK_FUZZTIME=30s scripts/test-parser-fuzz.sh
    scripts/test-generated-app-integration.sh
    scripts/test-generated-output-determinism.sh
    scripts/test-runtime-race.sh
  • Example smoke checks:

    scripts/check-root-deps.sh
    scripts/vulncheck-go-modules.sh
    go run ./cmd/gowdk check --ssr examples/pages/*.gwdk examples/marketing/*.gwdk examples/actions/*.gwdk examples/partials/*.gwdk examples/api/*.gwdk examples/ssr/*.gwdk examples/go-interop/*.gwdk examples/components/base/*.gwdk examples/components/css/*.gwdk examples/components/assets/*.gwdk examples/components/wasm/*.gwdk examples/store-persist/*.gwdk examples/embed/*.gwdk examples/seo/*.gwdk examples/css/*.gwdk examples/tailwind/*.gwdk examples/contracts/*.gwdk examples/security/*.gwdk
    go run ./cmd/gowdk manifest --ssr examples/pages/*.gwdk examples/marketing/*.gwdk examples/actions/*.gwdk examples/partials/*.gwdk examples/api/*.gwdk examples/ssr/*.gwdk examples/go-interop/*.gwdk examples/components/base/*.gwdk examples/components/css/*.gwdk examples/components/assets/*.gwdk examples/components/wasm/*.gwdk examples/store-persist/*.gwdk examples/embed/*.gwdk examples/seo/*.gwdk examples/css/*.gwdk examples/tailwind/*.gwdk examples/contracts/*.gwdk examples/security/*.gwdk
    go run ./cmd/gowdk sitemap --ssr examples/pages/*.gwdk examples/marketing/*.gwdk examples/actions/*.gwdk examples/partials/*.gwdk examples/api/*.gwdk examples/ssr/*.gwdk examples/go-interop/*.gwdk examples/components/base/*.gwdk examples/components/css/*.gwdk examples/components/assets/*.gwdk examples/components/wasm/*.gwdk examples/store-persist/*.gwdk examples/embed/*.gwdk examples/seo/*.gwdk examples/css/*.gwdk examples/tailwind/*.gwdk examples/contracts/*.gwdk examples/security/*.gwdk
    go run ./cmd/gowdk routes --ssr examples/pages/*.gwdk examples/marketing/*.gwdk examples/actions/*.gwdk examples/partials/*.gwdk examples/api/*.gwdk examples/ssr/*.gwdk examples/go-interop/*.gwdk examples/components/base/*.gwdk examples/components/css/*.gwdk examples/components/assets/*.gwdk examples/components/wasm/*.gwdk examples/store-persist/*.gwdk examples/embed/*.gwdk examples/seo/*.gwdk examples/css/*.gwdk examples/tailwind/*.gwdk examples/contracts/*.gwdk examples/security/*.gwdk
    go run ./cmd/gowdk build --config examples/css/gowdk.config.go --out /tmp/gowdk-css-build examples/css/styled.page.gwdk
    go run ./cmd/gowdk build --config examples/seo/gowdk.config.go --out /tmp/gowdk-seo-build examples/seo/*.gwdk
    go run ./cmd/gowdk build --out /tmp/gowdk-embed-build --app /tmp/gowdk-embed-app --bin /tmp/gowdk-embed-site examples/embed/site.page.gwdk
    GOWDK_SMOKE_ADDR=127.0.0.1:18085 scripts/smoke-generated-binary.sh /tmp/gowdk-embed-site /embed "Embedded GOWDK"
    go run ./cmd/gowdk build --out /tmp/gowdk-wasm-build --app /tmp/gowdk-wasm-app --wasm /tmp/gowdk-site.wasm examples/embed/site.page.gwdk
    scripts/smoke-generated-wasm.sh /tmp/gowdk-site.wasm
    go run ./cmd/gowdk build --ssr --out /tmp/gowdk-hybrid-build --app /tmp/gowdk-hybrid-app --bin /tmp/gowdk-hybrid-site examples/ssr/hybrid-static.page.gwdk
    go run ./cmd/gowdk build --out /tmp/gowdk-component-assets examples/components/assets/*.gwdk
    go run ./cmd/gowdk build --out /tmp/gowdk-wasm-island examples/components/wasm/*.gwdk
    go run ./cmd/gowdk build --out /tmp/gowdk-store-persist examples/store-persist/*.gwdk

    These commands run from the repository root and rely on the root gowdk.config.go. Any smoke command run from another directory must pass --config <file>.

Fuzz, Integration, And Determinism

Baseline CI keeps these checks bounded and Linux-only so the OS matrix is not multiplied by generated-binary work:

  • scripts/test-parser-fuzz.sh runs the existing FuzzParseSyntax target. CI sets GOWDK_FUZZTIME=1000x so the smoke uses a deterministic execution count instead of a short wall-clock deadline. Local hardening can raise the count or use a duration, for example GOWDK_FUZZTIME=100000x scripts/test-parser-fuzz.sh or GOWDK_FUZZTIME=30s scripts/test-parser-fuzz.sh.
  • scripts/test-generated-app-integration.sh runs representative generated binary flows for embedded SPA serving, action redirect, CSRF, fragments, dynamic SSR, and contract query execution.
  • scripts/test-generated-output-determinism.sh builds the same page twice and diffs generated HTML, manifests, OpenAPI/AsyncAPI, build reports, and report CLI output after canonicalizing temp paths.
  • scripts/test-runtime-race.sh runs an explicit Linux-focused package list under go test -race -count=1: runtime/app, runtime/trace, runtime/contracts, runtime/contracts/fileoutbox, runtime/contracts/membroker, runtime/contracts/sse, runtime/ratelimit, and runtime/testkit. The script first verifies every selected package has tests so the CI lane cannot silently become empty.

If one of these reveals nondeterministic output, either fix the generator in the same change or open a narrower issue naming the unstable file/report.

Dead Code

scripts/check-dead-code.sh runs two pinned analyzers over reviewed starter package sets:

scripts/check-dead-code.sh

Staticcheck is pinned to honnef.co/go/tools/cmd/staticcheck@v0.7.0 and runs -checks=U1000 over cmd/gowdk, internal/source, internal/gwdkir, internal/gwdkanalysis, and runtime/contracts. This catches unused private declarations and unread private fields where a clean baseline is currently actionable.

The x/tools dead-code analyzer is pinned to golang.org/x/tools/cmd/deadcode@v0.45.0 and runs with -test over cmd/gowdk, internal/source, internal/gwdkir, and internal/gwdkanalysis. Its report is filtered to those packages so exported compiler-private wrapper functions are covered without turning public runtime APIs into false positives.

Public runtime/addon APIs, optional nested modules, generated app fixtures, generated docs-site output, examples, and build-tag-specific platform implementations are intentionally outside the first gate. Add packages only after confirming a clean baseline without broad suppressions; if an intentional entry point needs a suppression, keep it local to the declaration and document why external reachability is expected.

GolangCI-Lint

.golangci.yml is intentionally strict:

scripts/check-golangci-lint.sh

The gate verifies the config and runs golangci-lint run with correctness, resource-handling, formatting, maintainability, and dead-code linters enabled. Test files are included, module downloads are readonly, issue counts are uncapped, and existing findings are not hidden through exclusions. The wrapper uses golangci-lint when v2.12.2 is on PATH; otherwise it falls back to go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2. CI also installs that pinned version before running the wrapper.

Do not add broad linters.exclusions or issues.exclude entries to make a dirty baseline pass. Fix the finding, add a narrow //nolint:<linter> with a reason where the code is intentionally exceptional, or lower strictness only with an owning engineering note that explains the tradeoff.

Release Smoke

After publishing a tag, verify the current machine's release artifact locally:

scripts/smoke-release-artifact.sh vX.Y.Z

Pass an explicit asset name to test a non-native artifact:

scripts/smoke-release-artifact.sh vX.Y.Z gowdk-linux-amd64

Use GOWDK_RELEASE_REPO=owner/repo for forks. The GitHub-only matrix version is .github/workflows/release-smoke.yml; trigger it with the published tag as the version input.

Branch Protection

Require these checks before merging to main:

  • Go tests (ubuntu-latest)
  • Go tests (macos-14)
  • Reachable vulnerabilities
  • Runtime race detector
  • CLI build
  • Dead code
  • VS Code extension
  • Documentation links
  • Example reports
  • Parser fuzz smoke
  • Generated app integration
  • Generated output determinism
  • Generated output smoke

Do not require scheduled Release Dry Run or manual Release Artifact Smoke for normal pull requests. Use them for release readiness and post-publish verification.

Documentation Links

scripts/check-docs-links.sh runs the stdlib-only internal/doclint checker over every Markdown file in the repository. It is a targeted gate: a broken in-repo link fails CI instead of rotting silently.

It checks only local references and stays offline:

  • Relative file and directory links must resolve to an existing path.
  • #fragment anchors (same-file or file.md#fragment) must resolve to a GitHub-style heading slug in the target Markdown file.
  • External links (http, https, mailto, tel, protocol-relative //) are skipped — the check never makes network calls.
  • Links inside fenced or inline code are ignored because they are documentation examples, not live references.

Generated, vendored, and local-output directories are excluded by default (.git, .gowdk, node_modules, vendor, dist, bin, tmp). Override the set with -exclude and scope a run with -root:

scripts/check-docs-links.sh -root docs -exclude .git,node_modules

Markdown style checks live in scripts/check-docs-style.sh. That gate is kept small on purpose: missing fence languages and skipped heading levels fail; long paragraphs warn without blocking. The authoring rules live in docs/engineering/documentation-style.md.

Docs Site Build

The docs site is tested through the same production path Render uses. The docs-site CI job installs the pinned Linux Tailwind standalone CLI, runs docs-site/scripts/build-production.sh, starts the compiled binary through docs-site/scripts/smoke-production.sh, then runs go test ./... and go vet ./... in the docs-site module.

docs-site/dist/site is build output, not committed source. The source of truth is the repo Markdown, docs-site .gwdk/CSS/assets, and the in-tree compiler used by build-production.sh.

Cache Maintenance

GitHub Actions caching is enabled for Go through actions/setup-go in CI and release packaging. Keep those caches because they reduce module and build-cache work across repeated runs.

GitHub-managed CodeQL default setup also creates per-commit overlay database caches. Those entries are safe to regenerate and can quickly fill the repository cache quota. .github/workflows/cache-maintenance.yml runs weekly and can be triggered manually to keep only the newest CodeQL overlay caches:

gh workflow run cache-maintenance.yml

For local one-off cleanup with a GitHub token:

GOWDK_CACHE_PRUNE_KEEP=20 scripts/prune-github-caches.sh cssbruno/GoWDK

Release Jobs

Release packaging lives in .github/workflows/release.yml. It builds the supported CLI binaries, packages the VS Code .vsix, writes checksums.txt, uploads dist/* as a run artifact for CI downloads, attests the same files, and uploads them to the selected tag release. The release job fails if any expected tag release asset is missing after upload.

  • Expand the release matrix if additional platforms become supported.
  • Verify generated-output examples with gowdk build --out.
  • Automate the dependency and license gates documented in docs/engineering/dependency-policy.md.