Skip to content

Commit 6fa6c99

Browse files
committed
fix(examples): harden runnable example flows
1 parent ab095e0 commit 6fa6c99

17 files changed

Lines changed: 171 additions & 37 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ jobs:
242242

243243
- name: Run parser fuzz smoke
244244
env:
245-
GOWDK_FUZZTIME: 1s
245+
GOWDK_FUZZTIME: 1000x
246246
run: scripts/test-parser-fuzz.sh
247247

248248
generated-app-integration:

docs/engineering/ci.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Required pull-request lanes:
2828
a `removed-syntax-ok` marker.
2929
- `Example reports`: `scripts/check-example-reports.sh`.
3030
- `Parser fuzz smoke`: `scripts/test-parser-fuzz.sh` with
31-
`GOWDK_FUZZTIME=1s`.
31+
`GOWDK_FUZZTIME=1000x`.
3232
- `Generated app integration`: `scripts/test-generated-app-integration.sh`.
3333
- `Generated output determinism`:
3434
`scripts/test-generated-output-determinism.sh`.
@@ -89,6 +89,7 @@ Run the same local checks before handoff when relevant:
8989

9090
```sh
9191
scripts/test-parser-fuzz.sh
92+
GOWDK_FUZZTIME=100000x scripts/test-parser-fuzz.sh
9293
GOWDK_FUZZTIME=30s scripts/test-parser-fuzz.sh
9394
scripts/test-generated-app-integration.sh
9495
scripts/test-generated-output-determinism.sh
@@ -126,7 +127,10 @@ Baseline CI keeps these checks bounded and Linux-only so the OS matrix is not
126127
multiplied by generated-binary work:
127128

128129
- `scripts/test-parser-fuzz.sh` runs the existing `FuzzParseSyntax` target.
129-
CI sets `GOWDK_FUZZTIME=1s`; local hardening can raise it, for example
130+
CI sets `GOWDK_FUZZTIME=1000x` so the smoke uses a deterministic execution
131+
count instead of a short wall-clock deadline. Local hardening can raise the
132+
count or use a duration, for example
133+
`GOWDK_FUZZTIME=100000x scripts/test-parser-fuzz.sh` or
130134
`GOWDK_FUZZTIME=30s scripts/test-parser-fuzz.sh`.
131135
- `scripts/test-generated-app-integration.sh` runs representative generated
132136
binary flows for embedded SPA serving, action redirect, CSRF, fragments,

docs/engineering/testing.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ must pass `--config <file>`.
7272
## Fuzz, Integration, And Determinism
7373

7474
- `scripts/test-parser-fuzz.sh` is the explicit parser fuzz runner. It defaults
75-
to `GOWDK_FUZZTIME=1s` for CI smoke cost; use a longer local run such as
75+
to `GOWDK_FUZZTIME=1000x` for deterministic CI smoke cost; use a larger
76+
count or a longer local run such as
77+
`GOWDK_FUZZTIME=100000x scripts/test-parser-fuzz.sh` or
7678
`GOWDK_FUZZTIME=30s scripts/test-parser-fuzz.sh` before risky parser work.
7779
- `scripts/test-generated-app-integration.sh` is the generated-app integration
7880
slice. It builds temporary binaries through `internal/appgen` tests and

docs/learning/native.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,11 @@ cd examples/flagship
181181
make check
182182
make routes
183183
make build
184-
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_ADDR=127.0.0.1:8092 bin/flagship
184+
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b \
185+
GOWDK_FLAGSHIP_SECRET=development-flagship-session-secret-32b \
186+
GOWDK_FLAGSHIP_PASSWORD=demo-password \
187+
GOWDK_ADDR=127.0.0.1:8092 \
188+
bin/flagship
185189
```
186190

187191
The flagship app covers static output, build-time Go data, actions,

examples/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,19 @@ is required by project-level compiler commands.
1818
| SSR and guards | `examples/auth-guard/` | `cd examples/auth-guard && make check && make routes && make build` |
1919
| One generated binary | `examples/embed/` | `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` |
2020
| Contracts and realtime | `examples/contracts/` | `go run ./cmd/gowdk build --config examples/contracts/gowdk.config.go --out /tmp/gowdk-contracts-build --app /tmp/gowdk-contracts-app --bin /tmp/gowdk-contracts-site examples/contracts/patients.page.gwdk` |
21-
| CSS and Tailwind | `examples/css/`, `examples/tailwind/` | `go run ./cmd/gowdk build --config examples/css/gowdk.config.go --out /tmp/gowdk-css-build examples/css/styled.page.gwdk` |
21+
| CSS | `examples/css/` | `go run ./cmd/gowdk build --config examples/css/gowdk.config.go --out /tmp/gowdk-css-build examples/css/styled.page.gwdk` |
22+
| Tailwind | `examples/tailwind/` | `go run ./cmd/gowdk build --config examples/tailwind/gowdk.config.go --out /tmp/gowdk-tailwind-build examples/tailwind/site.page.gwdk` |
23+
| SEO | `examples/seo/` | `go run ./cmd/gowdk build --config examples/seo/gowdk.config.go --out /tmp/gowdk-seo-build examples/seo/*.gwdk` |
2224
| Component assets and WASM islands | `examples/components/` | `go run ./cmd/gowdk build --out /tmp/gowdk-wasm-island examples/components/wasm/*.gwdk` |
2325
| Full-stack vertical slice | `examples/flagship/` | `cd examples/flagship && make check && make routes && make build` |
2426

27+
The Tailwind build command requires the standalone `tailwindcss` executable on
28+
`PATH`. To validate the source without running the CSS processor:
29+
30+
```sh
31+
go run ./cmd/gowdk check --config examples/tailwind/gowdk.config.go examples/tailwind/site.page.gwdk
32+
```
33+
2534
## Full Example Check
2635

2736
Validate the broad source set with SSR enabled:

examples/flagship/Makefile

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
ROOT := ../..
2-
CONFIG := examples/flagship/gowdk.config.go
3-
APP_DIR := examples/flagship/.gowdk/app
1+
CONFIG := gowdk.config.go
2+
APP_DIR := .gowdk/app
43
HOOK_FILE := $(APP_DIR)/gowdkapp/flagship_hooks.go
54

65
.PHONY: check routes build serve clean
76

87
check:
9-
cd $(ROOT) && go run ./cmd/gowdk check --config $(CONFIG)
8+
go run ../../cmd/gowdk check --config $(CONFIG)
109

1110
routes:
12-
cd $(ROOT) && go run ./cmd/gowdk routes --config $(CONFIG)
11+
go run ../../cmd/gowdk routes --config $(CONFIG)
1312

1413
$(HOOK_FILE): apphooks/flagship_hooks.go.txt
15-
mkdir -p $(ROOT)/$(APP_DIR)/gowdkapp
16-
cp apphooks/flagship_hooks.go.txt $(ROOT)/$(HOOK_FILE)
14+
mkdir -p $(APP_DIR)/gowdkapp
15+
cp apphooks/flagship_hooks.go.txt $(HOOK_FILE)
1716

1817
build: $(HOOK_FILE)
19-
cd $(ROOT) && go run ./cmd/gowdk build --config $(CONFIG) --target flagship
18+
go run ../../cmd/gowdk build --config $(CONFIG) --target flagship
2019

2120
serve: build
22-
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_ADDR=127.0.0.1:8092 bin/flagship
21+
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_FLAGSHIP_SECRET=development-flagship-session-secret-32b GOWDK_FLAGSHIP_PASSWORD=demo-password GOWDK_ADDR=127.0.0.1:8092 bin/flagship
2322

2423
clean:
2524
rm -rf .gowdk bin dist

examples/flagship/README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ Run from this directory:
1111
make check
1212
make routes
1313
make build
14-
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b GOWDK_ADDR=127.0.0.1:8092 bin/flagship
14+
GOWDK_CSRF_SECRET=development-flagship-csrf-secret-32b \
15+
GOWDK_FLAGSHIP_SECRET=development-flagship-session-secret-32b \
16+
GOWDK_FLAGSHIP_PASSWORD=demo-password \
17+
GOWDK_ADDR=127.0.0.1:8092 \
18+
bin/flagship
1519
```
1620

1721
Expected build outputs:
@@ -66,9 +70,10 @@ The main generated routes are:
6670

6771
## Demo Credentials
6872

69-
Use `demo@example.com` and `demo-password`. Override them with
70-
`GOWDK_FLAGSHIP_EMAIL`, `GOWDK_FLAGSHIP_PASSWORD`, and
71-
`GOWDK_FLAGSHIP_SECRET`.
73+
Use `demo@example.com` and set `GOWDK_FLAGSHIP_PASSWORD=demo-password` for the
74+
demo. `GOWDK_FLAGSHIP_EMAIL` can override the demo email.
75+
`GOWDK_FLAGSHIP_PASSWORD` is required; `GOWDK_FLAGSHIP_SECRET` is also required
76+
and signs the demo session cookie.
7277

7378
## Current Limitations
7479

examples/flagship/apphooks/flagship_hooks.go.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package gowdkapp
33
import (
44
"time"
55

6-
gowdkratelimit "github.com/cssbruno/gowdk/addons/ratelimit"
76
flagship "github.com/cssbruno/gowdk/examples/flagship/src/app"
87
gowdkguard "github.com/cssbruno/gowdk/runtime/guard"
8+
gowdkratelimit "github.com/cssbruno/gowdk/runtime/ratelimit"
99
)
1010

1111
func init() {

examples/flagship/gowdk.config.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ var Config = gowdk.Config{
1414
Include: []string{"src/**/*.gwdk"},
1515
},
1616
Build: gowdk.BuildConfig{
17-
Output: "examples/flagship/dist",
17+
Output: "dist",
1818
Targets: []gowdk.BuildTargetConfig{
1919
{
2020
Name: "flagship",
21-
Output: "examples/flagship/dist",
22-
App: "examples/flagship/.gowdk/app",
23-
Binary: "examples/flagship/bin/flagship",
21+
Output: "dist",
22+
App: ".gowdk/app",
23+
Binary: "bin/flagship",
2424
},
2525
},
2626
},
2727
CSS: gowdk.CSSConfig{
28-
Include: []string{"examples/flagship/styles/**/*.css"},
28+
Include: []string{"styles/*.css"},
2929
Output: gowdk.CSSOutputConfig{
3030
Dir: "assets/gowdk",
3131
HrefPrefix: "/assets/gowdk",

examples/flagship/src/app/app.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,17 @@ import (
2424
const sessionCookie = "gowdk_flagship_session"
2525

2626
func Login(_ context.Context, values form.Values) (response.Response, error) {
27+
if len(sessionSecret()) == 0 {
28+
return response.RedirectTo("/?login=failed"), nil
29+
}
30+
wantEmail, wantPassword, ok := configuredCredentials()
31+
if !ok {
32+
return response.RedirectTo("/?login=failed"), nil
33+
}
34+
2735
email := strings.TrimSpace(values.First("email"))
2836
password := values.First("password")
29-
if !constantEqual(email, env("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")) ||
30-
!constantEqual(password, env("GOWDK_FLAGSHIP_PASSWORD", "demo-password")) {
37+
if !constantEqual(email, wantEmail) || !constantEqual(password, wantPassword) {
3138
return response.RedirectTo("/?login=failed"), nil
3239
}
3340

@@ -127,6 +134,9 @@ var sessions = struct {
127134
}{Values: map[string]session{}}
128135

129136
func currentSession(request *http.Request) (session, bool) {
137+
if len(sessionSecret()) == 0 {
138+
return session{}, false
139+
}
130140
if request == nil {
131141
return session{}, false
132142
}
@@ -159,11 +169,21 @@ func sign(value string) string {
159169
}
160170

161171
func signature(value string) string {
162-
mac := hmac.New(sha256.New, []byte(env("GOWDK_FLAGSHIP_SECRET", "development-flagship-secret-change-me")))
172+
mac := hmac.New(sha256.New, sessionSecret())
163173
_, _ = mac.Write([]byte(value))
164174
return base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
165175
}
166176

177+
func sessionSecret() []byte {
178+
return []byte(strings.TrimSpace(os.Getenv("GOWDK_FLAGSHIP_SECRET")))
179+
}
180+
181+
func configuredCredentials() (email, password string, ok bool) {
182+
email = env("GOWDK_FLAGSHIP_EMAIL", "demo@example.com")
183+
password = strings.TrimSpace(os.Getenv("GOWDK_FLAGSHIP_PASSWORD"))
184+
return email, password, password != ""
185+
}
186+
167187
func sessionDuration() time.Duration {
168188
return 12 * time.Hour
169189
}

0 commit comments

Comments
 (0)