Skip to content

Commit 02255d6

Browse files
committed
docs: align site with current SolverForge releases
Document the SolverForge 0.9.0 and solverforge-cli 2.0.0 release surfaces, replace the legacy employee scheduling guide with the current solverforge-hospital tutorial, and update active docs for the scalar/list, retained lifecycle, and neutral CLI scaffold contracts. Add release-gate and hospital tutorial verifiers so pre-release checks assert the published CLI scaffold targets and the live hospital guide contract.
1 parent 9fff7b5 commit 02255d6

40 files changed

Lines changed: 3505 additions & 1727 deletions

.github/workflows/site.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,11 @@ jobs:
3333
cache: npm
3434
cache-dependency-path: package-lock.json
3535

36-
- name: Install Ruby gems
37-
run: bundle install
36+
- name: Install dependencies
37+
run: make install
3838

39-
- name: Install Node dependencies
40-
run: npm ci
41-
42-
- name: Build frontend assets
43-
run: bundle exec rake frontend:build
44-
45-
- name: Build Bridgetown site
46-
run: bundle exec bridgetown build
39+
- name: Run local CI gate
40+
run: make ci-local
4741

4842
- name: Configure Pages
4943
if: github.event_name != 'pull_request'

Makefile

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,110 @@
11
PORT ?= 4017
22
BIND ?= 0.0.0.0
3+
RUBY_VERSION_REQUIRED ?= 3.4
4+
NODE_VERSION_REQUIRED ?= 22
35

4-
.PHONY: install frontend build start clean website-install website-frontend website-build website-start
6+
.DEFAULT_GOAL := help
7+
8+
export RUBY_VERSION_REQUIRED
9+
export NODE_VERSION_REQUIRED
10+
11+
.PHONY: help doctor install frontend frontend-watch build test lint ci-local pre-release verify-cli-release verify-hospital-tutorial start clean version
12+
13+
define status
14+
@printf '\n==> %s\n' "$(1)"
15+
endef
16+
17+
help:
18+
@printf 'SolverForge.org Bridgetown site\n\n'
19+
@printf 'Setup\n'
20+
@printf ' make doctor Verify local Ruby, Bundler, Node, and npm\n'
21+
@printf ' make install Install Ruby gems and Node packages\n'
22+
@printf '\nBuild and run\n'
23+
@printf ' make frontend Build esbuild assets\n'
24+
@printf ' make frontend-watch Watch esbuild assets during development\n'
25+
@printf ' make build Build frontend assets and Bridgetown output\n'
26+
@printf ' make start Serve locally on BIND=%s PORT=%s\n' "$(BIND)" "$(PORT)"
27+
@printf ' make clean Remove Bridgetown build output\n'
28+
@printf '\nQuality gates\n'
29+
@printf ' make test Build in test mode and verify the hospital tutorial\n'
30+
@printf ' make lint Run Ruby and JavaScript syntax checks\n'
31+
@printf ' make verify-cli-release Install the published CLI and verify scaffold targets\n'
32+
@printf ' make verify-hospital-tutorial Run portable tutorial contract checks\n'
33+
@printf ' make ci-local Run the same gate used by CI\n'
34+
@printf ' make pre-release Run the release-readiness gate\n'
35+
@printf '\nInspection\n'
36+
@printf ' make version Print toolchain and site tool versions\n'
37+
38+
doctor:
39+
$(call status,Checking required tools)
40+
@command -v ruby >/dev/null || { printf 'missing required command: ruby\n' >&2; exit 1; }
41+
@command -v bundle >/dev/null || { printf 'missing required command: bundle\n' >&2; exit 1; }
42+
@command -v node >/dev/null || { printf 'missing required command: node\n' >&2; exit 1; }
43+
@command -v npm >/dev/null || { printf 'missing required command: npm\n' >&2; exit 1; }
44+
@ruby -e 'required = ENV.fetch("RUBY_VERSION_REQUIRED"); actual = RUBY_VERSION; abort("Ruby #{required}.x required; found #{actual}") unless actual.start_with?("#{required}.")'
45+
@node -e 'const required = process.env.NODE_VERSION_REQUIRED; const actual = process.versions.node; if (!actual.startsWith(`$${required}.`)) { console.error(`Node $${required}.x required; found $${actual}`); process.exit(1); }'
46+
@printf 'Ruby: '; ruby -v
47+
@printf 'Bundler: '; bundle -v
48+
@printf 'Node: '; node -v
49+
@printf 'npm: '; npm -v
550

651
install:
7-
bundle install
8-
npm install
52+
$(call status,Installing Ruby gems)
53+
@bundle install
54+
$(call status,Installing Node packages)
55+
@npm ci
956

1057
frontend:
11-
bundle exec rake frontend:build
58+
$(call status,Building frontend assets)
59+
@bundle exec rake frontend:build
60+
61+
frontend-watch:
62+
$(call status,Watching frontend assets)
63+
@bundle exec rake frontend:dev
1264

1365
build: frontend
14-
bundle exec bridgetown build
66+
$(call status,Building Bridgetown site)
67+
@bundle exec bridgetown build
1568

16-
start:
17-
bundle exec bridgetown start -P $(PORT) -B $(BIND)
69+
test: frontend
70+
$(call status,Building Bridgetown site in test mode)
71+
@BRIDGETOWN_ENV=test bundle exec rake test
72+
$(call status,Verifying hospital tutorial contract)
73+
@ruby scripts/verify-hospital-tutorial.rb
1874

19-
clean:
20-
bundle exec bridgetown clean
75+
lint:
76+
$(call status,Checking Ruby syntax)
77+
@ruby -c Gemfile
78+
@ruby -c Rakefile
79+
@find . \( -path './.git' -o -path './.bridgetown-cache' -o -path './node_modules' -o -path './output' -o -path './vendor' \) -prune -o -name '*.rb' -print0 | xargs -0 -n 1 ruby -c
80+
$(call status,Checking JavaScript syntax)
81+
@find . \( -path './.git' -o -path './.bridgetown-cache' -o -path './node_modules' -o -path './output' -o -path './vendor' \) -prune -o \( -name '*.js' -o -name '*.mjs' \) -print0 | xargs -0 -n 1 node --check
82+
83+
ci-local: doctor lint build verify-hospital-tutorial
84+
85+
pre-release: verify-cli-release ci-local
86+
$(call status,Ready for release)
2187

22-
website-install: install
88+
verify-cli-release:
89+
$(call status,Verifying published solverforge-cli release)
90+
@ruby scripts/verify-cli-release.rb
2391

24-
website-frontend: frontend
92+
verify-hospital-tutorial:
93+
$(call status,Verifying hospital tutorial contract)
94+
@ruby scripts/verify-hospital-tutorial.rb
2595

26-
website-build: build
96+
start:
97+
$(call status,Starting Bridgetown on $(BIND):$(PORT))
98+
@bundle exec bridgetown start -P $(PORT) -B $(BIND)
99+
100+
clean:
101+
$(call status,Cleaning Bridgetown output)
102+
@bundle exec bridgetown clean
27103

28-
website-start: start
104+
version:
105+
$(call status,Tool versions)
106+
@printf 'Ruby: '; ruby -v
107+
@printf 'Bundler: '; bundle -v
108+
@printf 'Node: '; node -v
109+
@printf 'npm: '; npm -v
110+
@printf 'Bridgetown: '; bundle exec bridgetown -v

README.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,48 @@ workflow, update the matching published pages here in the same effort.
3232

3333
Preferred entry points:
3434

35-
1. `make install`
36-
2. `make build`
37-
3. `make start`
35+
1. `make help`
36+
2. `make install`
37+
3. `make ci-local`
38+
4. `make pre-release`
39+
5. `make start`
3840

3941
Direct Bridgetown commands:
4042

4143
1. `bundle install`
42-
2. `npm install`
44+
2. `npm ci`
4345
3. `bundle exec rake frontend:build`
4446
4. `bundle exec bridgetown build`
45-
5. `bundle exec bridgetown start -P 4017`
47+
5. `ruby scripts/verify-cli-release.rb`
48+
6. `ruby scripts/verify-hospital-tutorial.rb`
49+
7. `bundle exec bridgetown start -P 4017`
50+
51+
`make verify-hospital-tutorial` always runs site-local copy and snippet checks.
52+
When `SOLVERFORGE_CLI_REPO` or `SOLVERFORGE_HOSPITAL_REPO` point to local
53+
product checkouts, it also runs the CLI scaffold and live hospital app checks.
54+
The Make target is the stable public workflow; the Ruby script is an
55+
implementation detail behind that target.
56+
57+
`make ci-local` runs the same path as GitHub Actions: toolchain checks, syntax
58+
linting, a full Bridgetown build, and the portable hospital tutorial verifier.
59+
`make pre-release` first installs the published `solverforge-cli` release into
60+
`/tmp`, verifies the scaffold targets, and then delegates to the local CI gate.
61+
62+
## Lint follow-up
63+
64+
The current `make lint` target is dependency-light and only performs Ruby and
65+
JavaScript syntax checks with the existing toolchain. A stricter follow-up
66+
should add configured tooling before broadening the gate:
67+
68+
- Ruby: StandardRB or RuboCop, chosen once the repo style is settled
69+
- JavaScript/CSS: ESLint plus Prettier
70+
- Markdown/content: markdownlint and an internal link checker
71+
72+
After those tools are configured, extend `fmt`, `fmt-check`, and `lint` to use
73+
them instead of relying only on syntax checks.
4674

4775
## Publishing
4876

4977
This repo is meant to be served directly as the GitHub Pages source for
50-
`solverforge.github.io`. GitHub Actions builds the site from repository root
51-
and deploys `output/` to Pages.
78+
`solverforge.github.io`. GitHub Actions installs dependencies with
79+
`make install`, runs `make ci-local`, and deploys `output/` to Pages.

scripts/verify-cli-release.rb

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
require "fileutils"
5+
require "open3"
6+
require "tmpdir"
7+
8+
EXPECTED_CLI_VERSION = "2.0.0"
9+
EXPECTED_RUNTIME_VERSION = "0.9.0"
10+
EXPECTED_UI_VERSION = "0.6.1"
11+
EXPECTED_MAPS_VERSION = "2.1.3"
12+
13+
def fail!(message)
14+
warn "[verify-cli-release] ERROR: #{message}"
15+
exit 1
16+
end
17+
18+
def log(message)
19+
puts "[verify-cli-release] #{message}"
20+
end
21+
22+
def run_command(*argv, chdir: nil)
23+
options = {}
24+
options[:chdir] = chdir if chdir
25+
stdout, stderr, status = Open3.capture3(*argv, **options)
26+
fail!("command failed: #{argv.join(" ")}\n#{stderr}") unless status.success?
27+
28+
stdout
29+
end
30+
31+
def assert_contains(text, needle, label)
32+
fail!("#{label} is missing: #{needle}") unless text.include?(needle)
33+
end
34+
35+
def assert_file_contains(path, needle)
36+
fail!("missing file: #{path}") unless File.file?(path)
37+
38+
assert_contains(File.read(path), needle, path)
39+
end
40+
41+
Dir.mktmpdir("solverforge-cli-release.") do |tmp_dir|
42+
install_root = File.join(tmp_dir, "install")
43+
scaffold_root = File.join(tmp_dir, "scaffold")
44+
FileUtils.mkdir_p(scaffold_root)
45+
46+
log "Installing solverforge-cli #{EXPECTED_CLI_VERSION} from crates.io"
47+
run_command(
48+
"cargo",
49+
"install",
50+
"solverforge-cli",
51+
"--version",
52+
EXPECTED_CLI_VERSION,
53+
"--root",
54+
install_root,
55+
"--locked"
56+
)
57+
58+
cli = File.join(install_root, "bin", "solverforge")
59+
fail!("missing installed CLI binary: #{cli}") unless File.executable?(cli)
60+
61+
version_output = run_command(cli, "--version")
62+
assert_contains(version_output, "CLI version: #{EXPECTED_CLI_VERSION}", "solverforge --version")
63+
assert_contains(version_output, "Scaffold runtime target: SolverForge crate target #{EXPECTED_RUNTIME_VERSION}", "solverforge --version")
64+
assert_contains(version_output, "Scaffold UI target: solverforge-ui #{EXPECTED_UI_VERSION}", "solverforge --version")
65+
assert_contains(version_output, "Scaffold maps target: solverforge-maps #{EXPECTED_MAPS_VERSION}", "solverforge --version")
66+
assert_contains(version_output, "Runtime source: crates.io: solverforge #{EXPECTED_RUNTIME_VERSION}", "solverforge --version")
67+
assert_contains(version_output, "UI source: crates.io: solverforge-ui #{EXPECTED_UI_VERSION}", "solverforge --version")
68+
assert_contains(version_output, "Maps source: crates.io: solverforge-maps #{EXPECTED_MAPS_VERSION}", "solverforge --version")
69+
70+
run_command(cli, "new", "release-gate", "--skip-git", "--skip-readme", "--quiet", chdir: scaffold_root)
71+
72+
app_root = File.join(scaffold_root, "release-gate")
73+
assert_file_contains(File.join(app_root, "Cargo.toml"), "solverforge = { version = \"#{EXPECTED_RUNTIME_VERSION}\", features = [\"serde\", \"console\", \"verbose-logging\"] }")
74+
assert_file_contains(File.join(app_root, "Cargo.toml"), "solverforge-ui = { version = \"#{EXPECTED_UI_VERSION}\" }")
75+
assert_file_contains(File.join(app_root, "Cargo.toml"), "solverforge-maps = { version = \"#{EXPECTED_MAPS_VERSION}\" }")
76+
assert_file_contains(File.join(app_root, "solverforge.app.toml"), "cli_version = \"#{EXPECTED_CLI_VERSION}\"")
77+
assert_file_contains(File.join(app_root, "solverforge.app.toml"), "target = \"solverforge #{EXPECTED_RUNTIME_VERSION}\"")
78+
assert_file_contains(File.join(app_root, "solverforge.app.toml"), "ui_source = \"crates.io: solverforge-ui #{EXPECTED_UI_VERSION}\"")
79+
80+
log "Published CLI release matches the documented scaffold targets"
81+
end

0 commit comments

Comments
 (0)