forge-ci 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaedbe8086290f0420daa471c104aa0715a3ddc1bcacdb7062f43a5e04e7fb13
4
- data.tar.gz: 1e718244f274b8184db6c7647a9bbec5ee250020eb735d58d40eb099a04722c2
3
+ metadata.gz: b7deaf8a35cd853691e015e86e2d0b4ce097e83609a1669c4303d5c60f7fe240
4
+ data.tar.gz: 391fa1dcaa79c33f7bf7af876b551d06128893e8dfffe48ecc702b7074d6daf6
5
5
  SHA512:
6
- metadata.gz: '0694a54d72604d0c2ff44f5ff65fa94abdd8d7225f450119c0367aac2beec0f77933285e597e34cb9ec144628c106309db1aa106728c17f373b5600519c71755'
7
- data.tar.gz: 3a055b45785bf5e5a3032ea73a4b97d4cd5940267d172e5fe00f4be068af68f282116742baf1eede753cf311de0faf5efbe8089e8f3f250fdbbb1ce63722057c
6
+ metadata.gz: c6964b6831ccc946d970b2bb214dc9c2cfb9447779862d65e04e731dd1ea1837eeb7469f604d0e8643527a54066ae48934834f3c88858bcc7fdf3149b3d30f40
7
+ data.tar.gz: 1b88099b87e003cdc4816b48a83a8ea5f5eabeb59602dc13ca6f37d5f807288244bcd30acdd783b4e08e5918b5b1a9cfbe6a8f76db54901812083fe77d9eb9ed
data/CHANGELOG.md ADDED
@@ -0,0 +1,37 @@
1
+ # Changelog
2
+
3
+ Versions of the `forge-ci` gem (the compiler and CLI). The control plane and
4
+ runner are deployed from this repository's `main` and aren't versioned
5
+ separately.
6
+
7
+ ## Unreleased
8
+
9
+ ## 0.3.0 (2026-10-24)
10
+
11
+ - `setup_remote_docker` takes `docker_layer_caching: true`: the compiler
12
+ passes it to the IR (`layer_caching: true`) and rejects non-boolean values.
13
+ With `FORGE_CI_BUILD_CACHE_REGISTRY` on the server, such jobs get a
14
+ registry-backed layer cache (`forge-ci-build`, or Kamal via
15
+ `FORGE_CI_BUILD_CACHE_IMAGE`).
16
+ - `gem install forge-ci` is the documented install; `rake build`,
17
+ `rake install` and `rake release` work from a checkout.
18
+ - Gemspec metadata: source and changelog links, MFA required to publish.
19
+ - The bundled agent skill installs the CLI with `gem install forge-ci`, and
20
+ covers `docker_layer_caching`.
21
+
22
+ ## 0.2.0 (2026-10-22)
23
+
24
+ - `forge-ci trigger` (start a pipeline through the admin API, `--wait` for
25
+ the result) and `forge-ci cancel`.
26
+ - `forge-ci skill install` / `forge-ci skill show`: the bundled agent skill
27
+ ships in the gem.
28
+ - `parallelism:` reaches the IR (with `circleci tests` splitting in the
29
+ runner).
30
+ - The compiler accepts `setup_remote_docker`, bare or with options.
31
+
32
+ ## 0.1.0
33
+
34
+ - First release: `forge-ci validate` and `forge-ci compile`, compiling
35
+ CircleCI 2.1 configs (executors, commands, parameters, workflows,
36
+ `requires`, `matrix`, branch filters, caches, workspaces, artifacts) into
37
+ ForgeCI's IR.
data/README.md CHANGED
@@ -44,7 +44,12 @@ control plane.
44
44
  - **Parallel test splitting.** `parallelism: N` with `circleci tests glob`,
45
45
  `split` and `run`.
46
46
  - **Scale to zero.** Idle runners remove themselves; the control plane scales
47
- them back up when jobs queue.
47
+ them back up when jobs queue. Only tested with AWS EC2 Spot runners so far
48
+ (see [TODO.md](TODO.md#tested-so-far)).
49
+ - **Registry-backed Docker layer caching.** `docker_layer_caching: true`
50
+ exports image layers to your registry during a build and restores them on
51
+ the next runner, so Spot reclamation never costs a full rebuild
52
+ (see [configuration](docs/configuration.md#docker-layer-caching)).
48
53
  - **Secrets done carefully.** Contexts are encrypted, masked in logs and never
49
54
  given to pull requests from forks.
50
55
  - **GitHub native.** Pipelines on push and pull request, private repos and
@@ -74,14 +79,18 @@ Coolify, S3, scaling to zero) see **[DEPLOY.md](DEPLOY.md)**.
74
79
  - **From any script, without the App:** `forge-ci trigger .circleci/config.yml --project myapp --wait`
75
80
  ([setup](DEPLOY.md#use-it-without-the-github-app)).
76
81
 
77
- Check a config locally first; the compiler needs only Ruby 3.0+:
82
+ Check a config locally first; the compiler needs only Ruby 3.0+. `gem install`
83
+ puts the `forge-ci` CLI on your PATH:
78
84
 
79
85
  ```sh
80
- gem build forge-ci.gemspec && gem install ./forge-ci-0.2.0.gem
86
+ gem install forge-ci
81
87
  forge-ci validate .circleci/config.yml
82
88
  forge-ci compile .circleci/config.yml --branch main # the jobs that will run on main
83
89
  ```
84
90
 
91
+ Working from a checkout of this repo? `rake install` builds the gem from
92
+ source and installs it the same way (`rake build` just produces the `.gem`).
93
+
85
94
  ```yaml
86
95
  # .circleci/config.yml
87
96
  version: 2.1
data/lib/forge_ci/ir.rb CHANGED
@@ -111,9 +111,13 @@ module ForgeCI
111
111
  { type: "add_ssh_keys", fingerprints: cfg["fingerprints"] || [] }
112
112
  when "setup_remote_docker"
113
113
  # The runner gives the job its own Docker daemon (see the runner's
114
- # ALLOW_DOCKER_SOCKET). `version` and `docker_layer_caching` don't
115
- # apply: the runner's daemon and its layer cache are used as is.
116
- { type: "setup_remote_docker" }
114
+ # ALLOW_DOCKER_SOCKET). `version` is ignored (the runner's daemon is
115
+ # what it is); `docker_layer_caching` asks for the registry-backed
116
+ # layer cache (FORGE_CI_BUILD_CACHE_REGISTRY on the server) so builds
117
+ # survive ephemeral runners.
118
+ step = { type: "setup_remote_docker" }
119
+ step[:layer_caching] = true if cfg["docker_layer_caching"] == true
120
+ step
117
121
  else
118
122
  raise Error, "internal error: unknown step type #{type.inspect} reached IR normalization"
119
123
  end
@@ -313,9 +313,14 @@ module ForgeCI
313
313
  errors.add(path, "\"store_test_results:\" needs a \"path:\" to the JUnit XML results directory")
314
314
  end
315
315
 
316
- # `version:` and `docker_layer_caching:` are accepted and ignored: the
317
- # runner's own Docker daemon is used.
318
- def validate_setup_remote_docker(_cfg, _path, _errors); end
316
+ # `version:` is ignored (the runner's daemon is what it is).
317
+ # `docker_layer_caching:` turns on the registry-backed layer cache.
318
+ def validate_setup_remote_docker(cfg, path, errors)
319
+ dlc = cfg["docker_layer_caching"]
320
+ return unless cfg.key?("docker_layer_caching") && ![true, false].include?(dlc)
321
+
322
+ errors.add(path + ["docker_layer_caching"], "\"docker_layer_caching:\" must be true or false")
323
+ end
319
324
 
320
325
  def validate_add_ssh_keys(cfg, path, errors)
321
326
  return unless cfg.key?("fingerprints") && !cfg["fingerprints"].is_a?(Array)
data/lib/forge_ci.rb CHANGED
@@ -16,5 +16,5 @@ require_relative "forge_ci/compiler"
16
16
  # JSON-serializable intermediate representation (IR) that a scheduler and
17
17
  # runner can execute. Pure Ruby, stdlib only, no network, no processes.
18
18
  module ForgeCI
19
- VERSION = "0.2.0"
19
+ VERSION = "0.3.0"
20
20
  end
@@ -30,7 +30,12 @@ Write standard CircleCI 2.1. These are the differences that matter:
30
30
  runners set up with `ALLOW_DOCKER_SOCKET=1` accept it, normally just the
31
31
  deploy runner, so use it only on jobs with that runner's `resource_class`;
32
32
  elsewhere the job fails with an error. Pull requests from forks never get
33
- it. `version:` and `docker_layer_caching:` are accepted and ignored.
33
+ it. `version:` is accepted and ignored. `docker_layer_caching: true` keeps
34
+ the image layer cache in a registry, if the server has
35
+ `FORGE_CI_BUILD_CACHE_REGISTRY`: build with `forge-ci-build` (it takes
36
+ `docker build` arguments), or point Kamal's `builder: cache: image:` at
37
+ `FORGE_CI_BUILD_CACHE_IMAGE`. Without the server setting the job logs a
38
+ warning and builds uncached.
34
39
  - **Lists, not strings:** `branches: only: [main]`, not `only: main`.
35
40
  - **Absolute paths:** the runner expands `~` to `/root`, but `cimg/*` images
36
41
  run as the `circleci` user. Use `/home/circleci/project` for
@@ -83,13 +88,15 @@ steps:
83
88
 
84
89
  ## Validate before you commit
85
90
 
86
- The CLI needs only Ruby 3.0+. If `forge-ci` isn't installed, run it from a
87
- checkout:
91
+ The CLI needs only Ruby 3.0+. If `forge-ci` isn't installed, install it with
92
+ `gem install forge-ci`. If you can't install gems, run it from a checkout:
88
93
 
89
94
  ```sh
90
95
  git clone --depth 1 https://github.com/azmi2409/forge-ci.git /tmp/forge-ci
91
96
  alias forge-ci="ruby -I/tmp/forge-ci/lib /tmp/forge-ci/exe/forge-ci"
97
+ ```
92
98
 
99
+ ```sh
93
100
  forge-ci validate .circleci/config.yml # must print "valid"
94
101
  forge-ci compile .circleci/config.yml --branch main # the jobs that will run on main
95
102
  forge-ci compile .circleci/config.yml --branch my-feature # ...and on a branch
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forge-ci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Azmi Muwahid
@@ -19,6 +19,7 @@ executables:
19
19
  extensions: []
20
20
  extra_rdoc_files: []
21
21
  files:
22
+ - CHANGELOG.md
22
23
  - MIT-LICENSE
23
24
  - README.md
24
25
  - exe/forge-ci
@@ -34,7 +35,10 @@ files:
34
35
  homepage: https://github.com/azmi2409/forge-ci
35
36
  licenses:
36
37
  - MIT
37
- metadata: {}
38
+ metadata:
39
+ source_code_uri: https://github.com/azmi2409/forge-ci
40
+ changelog_uri: https://github.com/azmi2409/forge-ci/blob/main/CHANGELOG.md
41
+ rubygems_mfa_required: 'true'
38
42
  rdoc_options: []
39
43
  require_paths:
40
44
  - lib