Skip to content

hooks: preBuild and postBuild commands in builder.json, run on every runner - #27

Open
Interlap01 wants to merge 4 commits into
mainfrom
hooks
Open

Interlap01 wants to merge 4 commits into
mainfrom
hooks

Conversation

@Interlap01

Copy link
Copy Markdown
Collaborator

Roadmap item 11. hooks.preBuild / hooks.postBuild in builder.json (top level, per-profile per-field override) run on the CI runner: preBuild after every dependency step and before the build number and the archive, postBuild once the IPA exists and before it is uploaded. Hooks get BUILDER_HOOK, BUILDER_BUILD_ID, BUILDER_PROFILE, BUILDER_CONFIGURATION, BUILDER_DISTRIBUTION, BUILDER_IOS_PATH, BUILDER_PROJECT_TYPE, BUILDER_BUILD_NUMBER and, for postBuild, BUILDER_IPA; a failing hook fails the job by name.

Transport: the hooks key inside the existing profile dispatch input (no new workflow input), builder.json on tag builds, BUILD_HOOKS / BUILD_PROFILE for runner.sh. Simulator builds never run hooks. The shared run_hook block is byte-identical in ios-build.yml and runner.sh, with a test that diffs them.

…field and sent to the runners

A top-level `hooks` object applies to every build; a profile's `hooks`
overrides it field by field (a non-blank command replaces, a blank or
absent one keeps the top-level; surrounding whitespace is dropped).
ResolveProfile puts the result on BuildSettings.Hooks, with no profile too.

Transport keeps GitHub under its ten-input limit: the `profile` input
gains an optional `hooks` key, and ProfileInput now returns an object
with an empty name when only top-level hooks are set, which the Resolve
step already reads as "no profile". runner.sh gets BUILD_HOOKS (JSON of
the commands set) from buildRemote only, since a simulator build never
runs hooks, plus BUILD_PROFILE for BUILDER_PROFILE; both names are
reserved for profile env. The build banner lists the hooks by name.
run_hook lives in a `# >>> build hooks` block that is byte-identical in
ios-build.yml (Build IPA step) and runner.sh: it runs the command from
the checkout root as `bash -eo pipefail -c` with the profile env and
BUILDER_{HOOK,BUILD_ID,PROFILE,CONFIGURATION,DISTRIBUTION,IOS_PATH,
PROJECT_TYPE,BUILD_NUMBER}, BUILDER_IPA for postBuild, a foldable group
on GitHub, and fails the job naming the hook and its exit code.

preBuild runs after pod install and project selection, before the build
number, the signing settings and the archive; in runner.sh at the top of
build_ipa rather than prepare, which the simulator mode shares. postBuild
runs once build/<id>.ipa exists, before the artifact upload.

The Resolve parameters step takes the hooks from the `profile` input on
a dispatch and merges them from builder.json in jq on a tag build, then
exports BUILDER_HOOK_PRE_BUILD/POST_BUILD through the same base64
heredoc as the env, only when non-blank. runner.sh reads BUILD_HOOKS,
validates it once jq is there, and exports PROJECT_TYPE for the hooks.

Tests: TestBuildHooksBlockIdentical, TestRunHook (cwd, variables, IPA
for postBuild only, first-failure stop, pipefail, exit code in the
message), TestBuildHooksPlacement, the Resolve step for tag and dispatch
with overrides, blanks and non-object hooks, and the end-to-end runner.sh
build with both hooks recording what they saw.
README gets a "Build hooks" section after the profiles (when each runs,
working directory, BUILDER_* variables, failure semantics, per-profile
override, not for ios share) and `hooks` in the configuration example;
CLAUDE.md gets the example, the profile field, and a Build Hooks pattern
covering the transport, placement and the shared block's identity test.
A hook whose value was a number or a list vanished on the runner: the tag
build's jq merge and the GITHUB_ENV export kept only strings, and runner.sh's
hook_command did the same, while the CLI refuses such a builder.json when it
decodes Hooks. The Resolve parameters step now checks both hook objects (top
level and profile) and the profile input, and check_build_hooks checks
BUILD_HOOKS, each failing with the hook's name; null stays "absent". The hook
keys travel base64-encoded through the export loop like the env names.

run_hook ran from GITHUB_WORKSPACE before BUILDER_WORKSPACE, so runner.sh
under GitHub Actions would have left its own checkout, and `cd ""` succeeds
silently, so with neither set a hook ran from the iOS directory. The root is
now BUILDER_WORKSPACE, else GITHUB_WORKSPACE, and an empty one fails. The
providers test points GITHUB_WORKSPACE elsewhere to prove it, TestRunHook
covers both cases, and TestCheckBuildHooks runs runner.sh's validation.

check_build_hooks no longer prints an empty "hooks:" line for {}. README:
BUILDER_DISTRIBUTION is also empty on the legacy ios.signing path, and a
command is one string.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant