@izykitten/ce 0.0.3-dev.3 → 0.0.3-dev.5

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.
Files changed (3) hide show
  1. package/README.md +60 -23
  2. package/dist/ce.js +948 -88
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -31,19 +31,19 @@ Only build commands are rewritten: `build`, `buildx build` and `image build` for
31
31
 
32
32
  ## Tags from the Forgejo run
33
33
 
34
- Tags and the `TAG_PREFIX`/`CACHE_PREFIX` values can use placeholders, filled from the Forgejo Actions environment and its event file. ce makes no API calls and does not look at the checkout.
35
-
36
- | Placeholder | Value |
37
- |---|---|
38
- | `{image}` | registry host and repository, lowercased, e.g. `code.izy.sh/library/gateway` |
39
- | `{ref}` | the branch name, `pr-<number>` for a pull request, or the tag name |
40
- | `{branch}`, `{pr}`, `{tag}` | the branch, PR number or tag, set only when building that kind of ref |
41
- | `{default}` | set only when building the default branch, never for a pull request or tag |
42
- | `{revision}`, `{sha}` | the commit, in full and as its first 7 characters |
43
- | `{version}`, `{major}`, `{minor}`, `{patch}` | from a SemVer tag such as `v1.2.3` or `1.2.3-rc.1` |
44
- | `{stable}` | set only for a SemVer tag without a pre-release |
45
- | `{env.NAME}` | the environment variable `NAME`, e.g. a value from an earlier step |
46
- | `{arg.NAME}` | the build arg `NAME` from this command's `--build-arg`, the value the build gets |
34
+ Tags and the `TAG_PREFIX`/`CACHE_PREFIX` values can use placeholders, filled from the Forgejo Actions environment and its event file. ce makes no API calls, and reads nothing from the checkout but the Containerfile, for a `{arg.NAME}` that needs its default.
35
+
36
+ | Placeholder | Value |
37
+ | -------------------------------------------- | ---------------------------------------------------------------------------------- |
38
+ | `{image}` | registry host and repository, lowercased, e.g. `code.izy.sh/library/gateway` |
39
+ | `{ref}` | the branch name, `pr-<number>` for a pull request, or the tag name |
40
+ | `{branch}`, `{pr}`, `{tag}` | the branch, PR number or tag, set only when building that kind of ref |
41
+ | `{default}` | set only when building the default branch, never for a pull request or tag |
42
+ | `{revision}`, `{sha}` | the commit, in full and as its first 7 characters |
43
+ | `{version}`, `{major}`, `{minor}`, `{patch}` | from a SemVer tag such as `v1.2.3` or `1.2.3-rc.1` |
44
+ | `{stable}` | set only for a SemVer tag without a pre-release |
45
+ | `{env.NAME}` | the environment variable `NAME`, e.g. a value from an earlier step |
46
+ | `{arg.NAME}` | the build arg `NAME` as the build gets it, from `--build-arg` or the Containerfile |
47
47
 
48
48
  `{name}` must have a value (an empty variable has none): if it has none in this run, ce fails with exit 2 before anything runs. To leave a tag out instead, guard it with `{?name}`, which expands to nothing and keeps the tag only when `name` has a value. Every guard in a tag has to pass, and a tag's other values are only needed when it is kept. Names are checked in every tag, so a typo fails even in one a guard leaves out. If the guards leave out every tag, ce fails rather than build an untagged image.
49
49
 
@@ -51,14 +51,6 @@ Values are made safe for a tag: any ASCII character a tag cannot have becomes `-
51
51
 
52
52
  Prefixes can use guards too. A guard that does not pass leaves the prefix empty, since a prefix cannot be left out, and the prefix's other values are then not needed. `CACHE_PREFIX='{?pr}pr-{pr}'` gives each pull request a cache of its own (`pr-3`) and leaves every other build sharing the unprefixed one; with `CACHE_FROM_DEFAULT`, a PR also reads that shared one, as the prefix is empty on the default branch. The image name cannot use guards.
53
53
 
54
- `{arg.NAME}` takes the value from `--build-arg NAME=value`, or from the environment for `--build-arg NAME`, as the engine does, so a tag can name a value worked out on the command line:
55
-
56
- ```sh
57
- ce docker build --build-arg VERSION="$(cat VERSION)" -t '{image}:{arg.VERSION}' .
58
- ```
59
-
60
- The last `--build-arg NAME` wins. One whose variable is not set is passed over by Docker, which keeps an earlier value, while podman and buildah drop the value for the Containerfile's default. Where the build would use the Containerfile's default, which ce does not read, `{arg.NAME}` is an error, guarded or not, unless another guard beside it does not pass. An empty value (`--build-arg NAME=`) is no value. With podman's `--build-arg-file`, which ce does not read either, `{arg.NAME}` needs a `--build-arg NAME` of its own.
61
-
62
54
  Guards decide from the run's metadata, so they need it too: outside a Forgejo Actions run, `{?default}` fails like `{default}` would. Only `{env.NAME}` and `{arg.NAME}` work everywhere. A guard that does not pass decides on its own, though: a tag with one is left out, and a prefix with one is empty, even if another guard in it could not be worked out, so `{?default}{?env.X}` outside a run with `X` empty is simply left out. To tell whether a branch is the default one, ce reads `repository.default_branch` from the event file, or `DEFAULT_BRANCH` when the event has none, as on a scheduled run; set `DEFAULT_BRANCH: main` in such a workflow. Pull requests and tags are never the default branch, so they need neither.
63
55
 
64
56
  Put templates in single quotes: `?` is a glob character in zsh.
@@ -68,7 +60,7 @@ A branch, PR and default-branch build:
68
60
  ```yaml
69
61
  - name: Container Build & Push
70
62
  env:
71
- CACHE_PREFIX: '{ref}'
63
+ CACHE_PREFIX: "{ref}"
72
64
  CADDY_VERSION: ${{ steps.caddy.outputs.version }}
73
65
  run: >
74
66
  bunx @izykitten/ce docker buildx build --push --cache type=gha,mode=max
@@ -89,6 +81,50 @@ A release on a SemVer tag, with the version aliases only for stable releases:
89
81
 
90
82
  `{stable}` does not mean newest: rebuilding an older release moves its aliases back to it.
91
83
 
84
+ ### Build args and the Containerfile
85
+
86
+ `{arg.NAME}` is the value the build gets for the build arg `NAME`, so a tag can carry a version from the command line or the Containerfile. The Containerfile is only read when a `{arg.NAME}` needs it; builds without one never open it.
87
+
88
+ With `--build-arg`, it is that value:
89
+
90
+ ```sh
91
+ ce docker build --build-arg VERSION="$(cat VERSION)" -t '{image}:{arg.VERSION}' .
92
+ ```
93
+
94
+ The last `--build-arg NAME` wins, and `--build-arg NAME` alone takes the environment's `NAME`. If that is not set, Docker keeps an earlier value, while podman and buildah fall back to the Containerfile's default. An empty value (`--build-arg NAME=`) is no value.
95
+
96
+ Without a `--build-arg`, it is the Containerfile's default:
97
+
98
+ ```dockerfile
99
+ ARG CADDY_VERSION=2.11.7
100
+ FROM caddy:builder
101
+ ARG CADDY_VERSION
102
+ RUN xcaddy build v${CADDY_VERSION}
103
+ ```
104
+
105
+ `-t '{image}:caddy-{arg.CADDY_VERSION}'` then tags `caddy-2.11.7`, with nothing on the command line.
106
+
107
+ **What ce reads**
108
+
109
+ - **The file:** the `-f` file (with Docker, the last one), else the context's `Dockerfile` (or `dockerfile`); podman and buildah look for `Containerfile` first.
110
+ - **The stage:** the one being built, `--target`'s or else the last. Other stages do not matter, unless this one is built `FROM` one of them, which it then starts from.
111
+ - **The default:** the stage's own `ARG NAME=…`, the last one winning, or that of the stage it is built from; else the global `ARG NAME=…` before the first `FROM`, which a bare `ARG NAME` in the stage, or a `FROM` line, also gets. No default anywhere, or an empty one, is no value, and a guard leaves its tag out.
112
+ - **`$` in a default:** worked out as the engine does, from the `ARG`s, `--build-arg`s and `ENV`s before it, with `$NAME`, `${NAME}`, `${NAME:-x}` and `${NAME:+x}` (and with Docker, `${NAME-x}` and `${NAME+x}`). With Docker, in a stage from `scratch`, a name nothing sets is empty, but for `PATH`.
113
+ - **Builtins** such as `TARGETPLATFORM`, and `SOURCE_DATE_EPOCH` and proxies such as `HTTP_PROXY`, which the engine may set itself, are the builder's, unless a `--build-arg` sets them. Docker also takes a builtin's own `ARG` default, and works out a `SOURCE_DATE_EPOCH` that is not a plain number such as `1700000000` itself.
114
+ - **podman and buildah** differ inside a stage: an `ENV`, the base image's too, wins over an `ARG`, so ce only works out a reference to a name an `ENV` there sets. A stage gets the `ARG`s of the stage its `FROM` names as written, so none through `FROM $BASE`. `TARGETPLATFORM` is always the platform they build.
115
+
116
+ **What ce refuses**, with exit 2 and the reason:
117
+
118
+ - **The file is not there to read:** `-f -`, a `-f` URL or a remote context; with podman or buildah, several `-f` files or a `.in` one for `cpp`.
119
+ - **Another frontend:** a `# syntax=` directive or `BUILDKIT_SYNTAX` naming anything but `docker/dockerfile` untagged, `:1`, or `:1.21` and later, which may be pinned by a digest.
120
+ - **A value ce cannot know:** a reference to a builtin, or to a name the base image's `ENV` may set; a form like `${NAME#x}`; with podman or buildah, `--env` or `--unsetenv` changing a name it refers to.
121
+ - **Instructions ce does not read:** an `ARG` or `ENV` name with something to expand, such as `ENV $NAME=x`, or with flags.
122
+ - **Characters other than ASCII's:** letters in an instruction, a stage name or a name after a `$`; space in an `ARG`, `ENV` or `FROM` line or a heredoc's line. Also a line ending in more than one carriage return.
123
+ - **Heredocs ce cannot place:** a delimiter that is not a word, which may be quoted; on its line, a `${}` with space or quotes in its word outside double quotes, or with quotes, `$` or `<` in it anywhere.
124
+ - **Stages that change under it:** a `--build-context` replacing a stage the built one comes from (with podman and buildah, what a `FROM` names); with podman or buildah, a stage built from one with an `ONBUILD ARG` or `ONBUILD ENV`, which they run only for some image formats.
125
+
126
+ Two places always need a `--build-arg NAME`: a `{arg.NAME}` in the cache prefix with `CACHE_FROM_DEFAULT`, as the default branch may have another Containerfile; and with podman's `--build-arg-file`, which ce does not read. ce does not see a base image's own `ONBUILD` lines, and does not model Docker's legacy builder (`DOCKER_BUILDKIT=0`). Every rule here has a test in `test/containerfile.test.ts`.
127
+
92
128
  ### Checking a template
93
129
 
94
130
  `--dry-run` before the engine, or `CE_DRY_RUN=true`, prints the build summary and the engine command ce would run, and exits 0 without running it or waiting for the engine. A template that fails still exits 2, so it also works as a check before pushing a workflow. It checks the templates, not the engine: if the engine is not on `PATH`, it warns and still exits 0, so it works on a machine without one:
@@ -120,13 +156,14 @@ These behave the same under Node and Bun, and [test/contract.test.ts](test/contr
120
156
 
121
157
  The wording of messages is not part of that and may change.
122
158
 
123
- In 0.0.3, the `--cache-from` that `--cache` makes no longer has a gha `mode=`, which only applies to export, and a `--cache-from` given twice is passed once.
159
+ In 0.0.3, the `--cache-from` that `--cache` makes no longer has a gha `mode=`, which only applies to export, and a `--cache-from` given twice is passed once. podman and buildah are no longer run through `gosu` as `$USER` when it is on `PATH`: ce runs every engine directly, as the user ce runs as, so to drop root, run ce itself as another user, e.g. with a `USER` line in the image.
124
160
 
125
161
  Compared with the Python version:
126
162
 
127
163
  - The state file is locked with `ce-forgejo-credentials.json.pidlock`, holding the holder's PID and hostname, rather than `flock`, which Node does not have. A lock whose holder died is broken right away if the PID is gone on the same host, otherwise after two minutes. It does not exclude a Python `ce` using the same Docker config at the same moment.
128
164
  - Replacing the process with the engine uses `process.execve`. Node aborts rather than report an `execve` failure, so `ce` first checks that the engine is an executable file on `PATH`.
129
165
  - Messages are worded differently in places, and the `Usage:` line shows the absolute path of the script.
166
+ - podman and buildah are not run through `gosu`, which the runner image's `ce` does when `gosu` is on `PATH`.
130
167
  - `docker-credential-ce-forgejo` runs the helper code directly instead of `exec ce credential-helper`, so `ce` does not have to be on `PATH`.
131
168
  - JSON files keep the same structure and sorted keys. Numbers are written as JavaScript writes them (`4102444800` rather than `4102444800.0`), and non-ASCII characters are not `\u`-escaped.
132
169