From 92abc93c5dab1fbce51e02f3f1082e970b0da041 Mon Sep 17 00:00:00 2001 From: crimson-knight Date: Sat, 1 Aug 2026 14:12:17 -0400 Subject: [PATCH] Release 1.5.0: compatibility chart, GitHub Actions CI, worktree-safe build specs - Bump version to 1.5.0 and declare crystal >= 1.20.0 (the constraint >= 1.0.0 overstated what actually compiles). - Add COMPATIBILITY.md documenting which Crystal versions build which Amber releases, with measured results for 1.20.3 and 1.21.0. - Replace the dead CircleCI config's role with a GitHub Actions workflow: spec matrix on Crystal 1.20.3 + latest (Linux) and latest (macOS), plus the postgres-backed granite build spec. CircleCI has been failing at checkout for weeks and every other amberframework repo already runs GitHub Actions. - Fix the generated-app amber dependency rewrite in the spec helpers to use an absolute path: the old ../../../amber literal only resolved when the checkout directory was named amber, so the granite build spec could never pass from a worktree or renamed CI checkout. It also means build specs now exercise the local framework rather than the last released tag. Verified: granite build spec 8/8, main suite 487/0 on 1.21.0. --- .github/workflows/ci.yml | 74 ++++++++++++++++++++++++++++++ COMPATIBILITY.md | 49 ++++++++++++++++++++ shard.yml | 4 +- spec/support/helpers/cli_helper.cr | 6 ++- src/amber/version.cr | 2 +- 5 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 COMPATIBILITY.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..bcc5044ae --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,74 @@ +name: CI + +on: + workflow_dispatch: + push: + branches: + - master + tags: + - "v1.*" + pull_request: + branches: + - master + +jobs: + specs: + name: Specs — Crystal ${{ matrix.crystal }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + crystal: ["1.20.3", "latest"] + include: + - os: macos-latest + crystal: "latest" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Crystal + uses: crystal-lang/install-crystal@v1 + with: + crystal: ${{ matrix.crystal }} + + - name: Install dependencies + run: shards install + + - name: Check formatting + run: crystal tool format --check src spec + + - name: Run specs + run: crystal spec + + granite: + name: Granite build spec — Crystal latest + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: granite_test + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Crystal + uses: crystal-lang/install-crystal@v1 + + - name: Install dependencies + run: shards install + + - name: Run granite build spec + run: crystal spec spec/build_spec_granite.cr + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/granite_test diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md new file mode 100644 index 000000000..849d794e8 --- /dev/null +++ b/COMPATIBILITY.md @@ -0,0 +1,49 @@ +# Crystal ↔ Amber compatibility + +Which Crystal compiler versions can build which Amber releases. "Verified" means we +compiled the framework, ran the full spec suite, and (for the most recent rows) +generated a new app with `amber new`, compiled it, and served requests with it. + +## Supported combinations + +| Amber release | Crystal requirement (declared) | Verified working | Known broken | Status | +|---|---|---|---|---| +| **2.0.0-beta.2** (v2 beta) | `>= 1.20.0, < 2.0` | 1.20.3, 1.21.0 | < 1.20.0 | **Active development** (`v2-dev`) | +| **2.0.0-beta.1** | `>= 1.20.0, < 2.0` | 1.20.x | < 1.20.0 | Superseded by beta.2 | +| **1.5.0** | `>= 1.20.0, < 2.0` | 1.20.3, 1.21.0 | — | **Current v1 release** | +| 1.4.1 / 1.4.0 | `>= 1.0.0, < 2.0` (declared) | 1.9.2 (CI), 1.20.3 | **1.21.0+** — does not compile | Upgrade to 1.5.0 | +| 1.3.x | `>= 1.0.0, < 2.0` (declared) | ~1.6 era (CI of the day) | 1.21.0+ | EOL — upgrade | +| 1.2.x | `>= 1.0.0, < 2.0` (declared) | ~1.2 era (CI of the day) | 1.21.0+ | EOL — upgrade | +| 0.36.0 and earlier | `0.35.x` and earlier | pre-1.0 compilers only | all Crystal 1.x | EOL | + +## Why 1.4.1 and earlier break on Crystal 1.21 + +Crystal 1.21 enables multithreading by default, and `Process.fork` fails at +**compile time** (`Error: Process fork is unsupported with multithreaded mode`). +Amber ≤ 1.4.1 used `Process.fork` in `Amber::Cluster.fork`, which is reachable +from `Amber::Server#run`, so every app failed to compile — even apps that never +enable cluster mode. Amber 1.5.0 replaces the fork with a `Process.new` spawn of +the app binary (the same mechanism v2 uses), preserving `process_count` / +master-worker semantics. + +Two secondary breakages also fixed in 1.5.0: + +- **ameba ≤ 1.6.4 does not compile on Crystal 1.21**, and both the framework and + the generated app template pinned `~> 1.5.0`, so `shards install` failed in + development. Both now pin `1.7.0-dev` (the first ameba tag with Crystal 1.21 + support); the pin moves to `~> 1.7.0` once ameba tags a stable release. +- Old declared constraints (`>= 1.0.0`) overstate reality; 1.5.0 declares + `>= 1.20.0` to match what is actually tested. + +## Policy + +- **v1** (`master`): tested in CI against the two most recent Crystal minor + releases (currently 1.20.x and 1.21.x). Older Crystal versions may work but + are not supported. +- **v2** (`v2-dev`, 2.0.0 betas): requires Crystal 1.20+. Tested against + `latest` on Linux and macOS. +- A new Crystal minor release that breaks Amber is treated as a bug in Amber: + file an issue with the compiler error and the Crystal version. + +_Last verified 2026-08-01 on macOS arm64 (local) — spec suites: v1 master 487/0, +v2 beta.2 2320/0, both on Crystal 1.20.3 and 1.21.0._ diff --git a/shard.yml b/shard.yml index 90287469c..912ee93b8 100644 --- a/shard.yml +++ b/shard.yml @@ -1,11 +1,11 @@ name: amber -version: 1.4.1 +version: 1.5.0 authors: - Amber Team and Contributors -crystal: ">= 1.0.0, < 2.0" +crystal: ">= 1.20.0, < 2.0" license: MIT diff --git a/spec/support/helpers/cli_helper.cr b/spec/support/helpers/cli_helper.cr index 2857f3ffb..7d9c79b38 100644 --- a/spec/support/helpers/cli_helper.cr +++ b/spec/support/helpers/cli_helper.cr @@ -91,7 +91,11 @@ module CLIHelper def prepare_yaml(path) if File.exists?("#{path}/shard.yml") shard = File.read("#{path}/shard.yml") - shard = shard.gsub(/github\:\samberframework\/amber\n.*(?=\n)/, "path: ../../../amber") + # Point the generated app at the framework checkout under test. An absolute + # path keeps this working from git worktrees and CI checkouts whose + # directory is not named "amber". + amber_root = File.expand_path("../..", path) + shard = shard.gsub(/github\:\samberframework\/amber\n.*(?=\n)/, "path: #{amber_root}") File.write("#{path}/shard.yml", shard) end end diff --git a/src/amber/version.cr b/src/amber/version.cr index a2a2881e5..63a10024e 100644 --- a/src/amber/version.cr +++ b/src/amber/version.cr @@ -1,3 +1,3 @@ module Amber - VERSION = "1.4.1" + VERSION = "1.5.0" end