Skip to content

Commit 6e7be57

Browse files
committed
ci: add ci.1focus host runner mode and tighten workflow performance
1 parent 9315150 commit 6e7be57

6 files changed

Lines changed: 464 additions & 33 deletions

File tree

.github/workflows/canary.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ env:
1818

1919
jobs:
2020
build:
21+
timeout-minutes: 40
2122
env:
2223
# Don't reference `secrets.*` in `if:` expressions; GitHub rejects that at workflow-parse time.
2324
MACOS_SIGN_P12_B64: ${{ secrets.MACOS_SIGN_P12_B64 }}
@@ -45,6 +46,12 @@ jobs:
4546
with:
4647
targets: ${{ matrix.target }}
4748

49+
- name: Cache Rust build
50+
uses: Swatinem/rust-cache@v2
51+
with:
52+
workspaces: ". -> target"
53+
cache-on-failure: true
54+
4855
- name: Install cross-compilation tools (Linux ARM)
4956
if: matrix.target == 'aarch64-unknown-linux-gnu'
5057
run: |
@@ -88,6 +95,7 @@ jobs:
8895

8996
build-linux-host-simd:
9097
if: ${{ false }}
98+
timeout-minutes: 40
9199
runs-on: ubuntu-latest
92100
env:
93101
RUSTFLAGS: -C target-cpu=native
@@ -100,6 +108,12 @@ jobs:
100108
with:
101109
targets: x86_64-unknown-linux-gnu
102110

111+
- name: Cache Rust build
112+
uses: Swatinem/rust-cache@v2
113+
with:
114+
workspaces: ". -> target"
115+
cache-on-failure: true
116+
103117
- name: Build (Linux host SIMD)
104118
run: cargo build --release --target x86_64-unknown-linux-gnu --features linux-host-simd-json
105119

@@ -119,6 +133,7 @@ jobs:
119133

120134
release:
121135
needs: build
136+
timeout-minutes: 20
122137
runs-on: ubuntu-latest
123138
steps:
124139
- name: Checkout

.github/workflows/release.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ env:
1313

1414
jobs:
1515
build:
16+
timeout-minutes: 40
1617
env:
1718
# Don't reference `secrets.*` in `if:` expressions; GitHub rejects that at workflow-parse time.
1819
MACOS_SIGN_P12_B64: ${{ secrets.MACOS_SIGN_P12_B64 }}
@@ -40,6 +41,12 @@ jobs:
4041
with:
4142
targets: ${{ matrix.target }}
4243

44+
- name: Cache Rust build
45+
uses: Swatinem/rust-cache@v2
46+
with:
47+
workspaces: ". -> target"
48+
cache-on-failure: true
49+
4350
- name: Install cross-compilation tools (Linux ARM)
4451
if: matrix.target == 'aarch64-unknown-linux-gnu'
4552
run: |
@@ -83,6 +90,7 @@ jobs:
8390

8491
build-linux-host-simd:
8592
if: ${{ false }}
93+
timeout-minutes: 40
8694
runs-on: ubuntu-latest
8795
env:
8896
RUSTFLAGS: -C target-cpu=native
@@ -95,6 +103,12 @@ jobs:
95103
with:
96104
targets: x86_64-unknown-linux-gnu
97105

106+
- name: Cache Rust build
107+
uses: Swatinem/rust-cache@v2
108+
with:
109+
workspaces: ". -> target"
110+
cache-on-failure: true
111+
98112
- name: Build (Linux host SIMD)
99113
run: cargo build --release --target x86_64-unknown-linux-gnu --features linux-host-simd-json
100114

@@ -114,6 +128,7 @@ jobs:
114128

115129
release:
116130
needs: build
131+
timeout-minutes: 20
117132
runs-on: ubuntu-latest
118133
steps:
119134
- name: Checkout

flow.toml

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ description = "Upload the latest darwin/arm64 release tarball to the release hos
126126
[[tasks]]
127127
name = "ci-blacksmith-status"
128128
command = "python3 ./scripts/ci_blacksmith.py status"
129-
description = "Show CI runner mode for canary/release workflows (github or blacksmith)"
129+
description = "Show CI runner mode for canary/release workflows (github, blacksmith, or host)"
130130

131131
[[tasks]]
132132
name = "ci-blacksmith-enable"
@@ -148,6 +148,41 @@ name = "ci-blacksmith-disable-apply"
148148
command = "python3 ./scripts/ci_blacksmith.py disable --commit --push"
149149
description = "Disable Blacksmith CI mode, commit workflow updates, and push"
150150

151+
[[tasks]]
152+
name = "ci-host-enable"
153+
command = "python3 ./scripts/ci_blacksmith.py host"
154+
description = "Keep standard Linux CI lanes on GitHub runners, but enable Linux host SIMD build on ci-1focus self-hosted runner"
155+
156+
[[tasks]]
157+
name = "ci-host-enable-apply"
158+
command = "python3 ./scripts/ci_blacksmith.py host --commit --push"
159+
description = "Enable host SIMD CI mode, commit workflow updates, and push"
160+
161+
[[tasks]]
162+
name = "ci-host-runner-status"
163+
command = "python3 ./scripts/ci_host_runner.py status --repo nikivdev/flow"
164+
description = "Show ci-1focus runner service status on infra host and GitHub runner registration state"
165+
166+
[[tasks]]
167+
name = "ci-host-runner-install"
168+
command = "python3 ./scripts/ci_host_runner.py install --repo nikivdev/flow"
169+
description = "Install/register self-hosted GitHub runner on configured infra Linux host (label: ci-1focus)"
170+
171+
[[tasks]]
172+
name = "ci-host-runner-remove"
173+
command = "python3 ./scripts/ci_host_runner.py remove --repo nikivdev/flow"
174+
description = "Unregister ci-1focus self-hosted GitHub runner and remove runner service on infra host"
175+
176+
[[tasks]]
177+
name = "ci-host-bootstrap"
178+
command = "python3 ./scripts/ci_host_runner.py install --repo nikivdev/flow && python3 ./scripts/ci_blacksmith.py host"
179+
description = "One-command setup: install ci-1focus runner on infra host and switch workflows to host SIMD mode"
180+
181+
[[tasks]]
182+
name = "ci-host-bootstrap-apply"
183+
command = "python3 ./scripts/ci_host_runner.py install --repo nikivdev/flow && python3 ./scripts/ci_blacksmith.py host --commit --push"
184+
description = "Install ci-1focus runner, switch workflows to host SIMD mode, then commit and push workflow updates"
185+
151186
[[tasks]]
152187
name = "test-flow-task-tracing"
153188
command = "bun i-run.ts"

readme.md

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,28 @@ Stable releases are cut by pushing a git tag that starts with `v`:
8787
Canary releases are published automatically on every push to `main` via
8888
`.github/workflows/canary.yml` (GitHub release tag: `canary`).
8989

90-
Optional Linux host SIMD lane:
91-
92-
- Flow has first-class tasks for CI runner mode (no GitHub env/repo vars needed):
93-
- `f ci-blacksmith-status`
94-
- `f ci-blacksmith-enable`
95-
- `f ci-blacksmith-enable-apply`
96-
- `f ci-blacksmith-disable`
97-
- `f ci-blacksmith-disable-apply`
98-
- `ci-blacksmith-enable` switches Linux jobs to Blacksmith runners and enables
99-
the Linux host SIMD build job (`--features linux-host-simd-json` with
100-
`RUSTFLAGS=-C target-cpu=native`).
101-
- `ci-blacksmith-disable` reverts to GitHub-hosted Linux runners and keeps the
102-
SIMD lane disabled by default for reliability.
103-
- `*-apply` variants also commit and push workflow changes in one command.
90+
CI runner modes (no workflow env var toggles):
91+
92+
- `f ci-blacksmith-status` shows the active mode (`github`, `blacksmith`, or `host`).
93+
- `f ci-blacksmith-enable` / `f ci-blacksmith-enable-apply` switch Linux lanes to Blacksmith runners and enable the SIMD lane.
94+
- `f ci-host-enable` / `f ci-host-enable-apply` keep normal Linux lanes on GitHub-hosted runners, but run the SIMD lane on `ci-1focus` self-hosted runner.
95+
- `f ci-blacksmith-disable` / `f ci-blacksmith-disable-apply` revert to default GitHub mode with SIMD lane disabled.
96+
97+
Set up `ci.1focus.ai` host runner (painless path):
98+
99+
1. Point infra to your Linux host: `infra host set <user@ip>`
100+
2. Make sure GitHub CLI auth is ready: `gh auth status`
101+
3. Install/register runner on host: `f ci-host-runner-install`
102+
4. Verify runner service + registration: `f ci-host-runner-status`
103+
5. Switch workflows to host SIMD mode: `f ci-host-enable-apply`
104+
105+
Or run all in one command:
106+
107+
- `f ci-host-bootstrap-apply`
108+
109+
Notes:
110+
111+
- Host mode is a compile-time balance: expensive SIMD builds run on your Linux host, while default Linux matrix jobs stay on GitHub-hosted runners for throughput.
104112
- Blacksmith setup and runner tags:
105113
- https://docs.blacksmith.sh/github-actions/quickstart
106114
- https://docs.blacksmith.sh/github-actions/runner-tags

scripts/ci_blacksmith.py

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
#!/usr/bin/env python3
22
"""
3-
Toggle CI workflows between GitHub-hosted and Blacksmith runner profiles.
3+
Toggle CI workflows between runner profiles.
4+
5+
Profiles:
6+
- github: Default GitHub-hosted Linux jobs, SIMD lane disabled.
7+
- blacksmith: Blacksmith Linux jobs, SIMD lane enabled on Blacksmith.
8+
- host: GitHub Linux jobs, SIMD lane enabled on ci.1focus.ai self-hosted runner.
49
510
Usage:
611
python3 scripts/ci_blacksmith.py status
712
python3 scripts/ci_blacksmith.py enable
813
python3 scripts/ci_blacksmith.py enable --commit --push
14+
python3 scripts/ci_blacksmith.py host
915
python3 scripts/ci_blacksmith.py disable
1016
"""
1117

@@ -28,21 +34,33 @@
2834
BLACKSMITH_X64 = "blacksmith-2vcpu-ubuntu-2404"
2935
BLACKSMITH_ARM = "blacksmith-2vcpu-ubuntu-2404-arm"
3036
BLACKSMITH_SIMD = "blacksmith-4vcpu-ubuntu-2404"
37+
HOST_SIMD = "[self-hosted, linux, x64, ci-1focus]"
3138

3239
WORKFLOW_REL_PATHS = [
3340
".github/workflows/canary.yml",
3441
".github/workflows/release.yml",
3542
]
3643

3744

38-
def rewrite_workflow(path: Path, enable: bool) -> bool:
45+
def rewrite_workflow(path: Path, mode: str) -> bool:
3946
content = path.read_text(encoding="utf-8")
4047
original = content
4148

42-
linux_x64 = BLACKSMITH_X64 if enable else GITHUB_X64
43-
linux_arm = BLACKSMITH_ARM if enable else GITHUB_ARM
44-
simd_runs_on = BLACKSMITH_SIMD if enable else "ubuntu-latest"
45-
simd_if_line = "" if enable else " if: ${{ false }}\n"
49+
if mode == "blacksmith":
50+
linux_x64 = BLACKSMITH_X64
51+
linux_arm = BLACKSMITH_ARM
52+
simd_runs_on = BLACKSMITH_SIMD
53+
simd_if_line = ""
54+
elif mode == "host":
55+
linux_x64 = GITHUB_X64
56+
linux_arm = GITHUB_ARM
57+
simd_runs_on = HOST_SIMD
58+
simd_if_line = ""
59+
else:
60+
linux_x64 = GITHUB_X64
61+
linux_arm = GITHUB_ARM
62+
simd_runs_on = "ubuntu-latest"
63+
simd_if_line = " if: ${{ false }}\n"
4664

4765
content = re.sub(
4866
r"(- target: x86_64-unknown-linux-gnu\s*\n\s*os:\s*)([^\n]+)",
@@ -57,12 +75,35 @@ def rewrite_workflow(path: Path, enable: bool) -> bool:
5775
count=1,
5876
)
5977

60-
content = re.sub(
61-
r"( build-linux-host-simd:\n)(?:\s+if:.*\n)?(\s+runs-on:.*\n)",
62-
rf"\1{simd_if_line} runs-on: {simd_runs_on}\n",
63-
content,
64-
count=1,
78+
simd_block = re.compile(
79+
r"(^ build-linux-host-simd:\n)(?P<body>(?:^ .*\n)*)",
80+
re.MULTILINE,
6581
)
82+
block_match = simd_block.search(content)
83+
if block_match:
84+
body_lines = block_match.group("body").splitlines(keepends=True)
85+
rewritten_body: list[str] = []
86+
has_runs_on = False
87+
for line in body_lines:
88+
if re.match(r"^ if:", line):
89+
continue
90+
if re.match(r"^ runs-on:", line):
91+
rewritten_body.append(f" runs-on: {simd_runs_on}\n")
92+
has_runs_on = True
93+
continue
94+
rewritten_body.append(line)
95+
96+
if not has_runs_on:
97+
rewritten_body.insert(0, f" runs-on: {simd_runs_on}\n")
98+
if simd_if_line:
99+
rewritten_body.insert(0, simd_if_line)
100+
101+
replacement = block_match.group(1) + "".join(rewritten_body)
102+
content = (
103+
content[: block_match.start()]
104+
+ replacement
105+
+ content[block_match.end() :]
106+
)
66107

67108
changed = content != original
68109
if changed:
@@ -74,6 +115,8 @@ def detect_profile(path: Path) -> str:
74115
content = path.read_text(encoding="utf-8")
75116
if BLACKSMITH_X64 in content and BLACKSMITH_ARM in content:
76117
return "blacksmith"
118+
if HOST_SIMD in content and "if: ${{ false }}" not in content:
119+
return "host"
77120
if GITHUB_X64 in content and "blacksmith-" not in content:
78121
return "github"
79122
if GITHUB_X64 in content and GITHUB_ARM in content:
@@ -130,19 +173,18 @@ def maybe_commit_and_push(mode: str, commit: bool, push: bool) -> int:
130173
return 0
131174

132175

133-
def set_mode(enable: bool, commit: bool, push: bool) -> int:
176+
def set_mode(mode: str, commit: bool, push: bool) -> int:
134177
if push and not commit:
135178
print("--push requires --commit", file=sys.stderr)
136179
return 2
137180

138181
changed_any = False
139182
for wf in WORKFLOWS:
140-
changed = rewrite_workflow(wf, enable)
183+
changed = rewrite_workflow(wf, mode=mode)
141184
changed_any = changed_any or changed
142185
state = "updated" if changed else "unchanged"
143186
print(f"{wf.relative_to(ROOT)}: {state}")
144187

145-
mode = "blacksmith" if enable else "github"
146188
if changed_any:
147189
print(f"CI runner mode set to: {mode}")
148190
else:
@@ -154,8 +196,8 @@ def main() -> int:
154196
parser = argparse.ArgumentParser(description="Manage CI runner profile.")
155197
parser.add_argument(
156198
"command",
157-
choices=["status", "enable", "disable"],
158-
help="status | enable (Blacksmith) | disable (GitHub-hosted)",
199+
choices=["status", "enable", "disable", "host"],
200+
help="status | enable (Blacksmith) | host (self-hosted SIMD lane) | disable (GitHub-hosted)",
159201
)
160202
parser.add_argument(
161203
"--commit",
@@ -172,9 +214,11 @@ def main() -> int:
172214
if args.command == "status":
173215
return status()
174216
if args.command == "enable":
175-
return set_mode(enable=True, commit=args.commit, push=args.push)
217+
return set_mode(mode="blacksmith", commit=args.commit, push=args.push)
218+
if args.command == "host":
219+
return set_mode(mode="host", commit=args.commit, push=args.push)
176220
if args.command == "disable":
177-
return set_mode(enable=False, commit=args.commit, push=args.push)
221+
return set_mode(mode="github", commit=args.commit, push=args.push)
178222
return 2
179223

180224

0 commit comments

Comments
 (0)