Skip to content

Commit f9791b8

Browse files
authored
Merge branch 'master' into drop-make
2 parents 909c470 + 7c16a01 commit f9791b8

File tree

6 files changed

+114
-84
lines changed

6 files changed

+114
-84
lines changed

README.md

Lines changed: 83 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,13 @@ $ uv sync --all-packages
88

99
# Master configuration
1010

11-
## Web server settings
12-
13-
Using your production-quality web server of choice (Apache, Nginx, etc.), choose
14-
a URL at which to host the master. Call this `BUILDBOT_WWW`. Then, set up a
15-
reverse proxy for the buildbot webserver (on port 8012). For Apache, your
16-
configuration might look like:
17-
18-
```
19-
ProxyPass /ws ws://localhost:8012/ws
20-
ProxyPassReverse /ws ws://localhost:8012/ws
21-
ProxyPass / http://localhost:8012/
22-
ProxyPassReverse / http://localhost:8012/
23-
24-
SetEnvIf X-Url-Scheme https HTTPS=1
25-
ProxyPreserveHost On
26-
```
27-
28-
Note that you will need to enable `proxy_wstunnel` for this to work (via
29-
`a2enmod`). It is essential that HTTPS only is used (for security).
30-
31-
**Close port 8012 to the internet.** If you can't have port 9990 open, redirect
32-
another port to it. Whichever port this is, call it `MASTER_PORT`.
33-
34-
Make a note of your master's IP address. Call this `MASTER_ADDR`.
11+
The master is deployed via [Docker Compose][dc], which manages three services:
12+
a PostgreSQL database, the Buildbot master, and a [Caddy] reverse proxy with
13+
automatic HTTPS.
3514

3615
## Secrets
3716

38-
Four secrets control authentication with external users and servers. These will
17+
Five secrets control authentication with external users and servers. These will
3918
need to be determined before starting up a new master.
4019

4120
1. Obtain a [GitHub personal access token](https://github.com/settings/tokens)
@@ -48,16 +27,30 @@ need to be determined before starting up a new master.
4827
Call this `WEBHOOK_SECRET`.
4928
4. Choose a password for the `halidenightly` user to authenticate with the web
5029
interface. Call this `WWW_PASSWORD`.
30+
5. Generate a password for the PostgreSQL database. Call this `DB_PASSWORD`.
31+
This is only needed when using PostgreSQL (i.e., when
32+
`HALIDE_BB_MASTER_DB_URL` contains `{DB_PASSWORD}`). The default SQLite
33+
backend does not require it.
5134

5235
A convenient command for generating a secure secret is `openssl rand -hex 20`.
5336

54-
## GitHub Configuration
37+
Write all the secrets to the corresponding files:
38+
39+
```console
40+
$ echo "$GITHUB_TOKEN" > secrets/github_token.txt
41+
$ echo "$WORKER_SECRET" > secrets/halide_bb_pass.txt
42+
$ echo "$WEBHOOK_SECRET" > secrets/webhook_token.txt
43+
$ echo "$WWW_PASSWORD" > secrets/buildbot_www_pass.txt
44+
$ echo "$DB_PASSWORD" > secrets/db_password.txt
45+
```
46+
47+
## GitHub configuration
5548

5649
Make your way to the Webhooks section of your repository settings. The url is
5750
`https://github.com/{owner}/{repo}/settings/hooks`. The following settings are
5851
the correct ones:
5952

60-
1. **Payload URL:** `$BUILDBOT_WWW/change_hook/github`
53+
1. **Payload URL:** `https://buildbot.halide-lang.org/master/change_hook/github`
6154
2. **Content type:** `application/json`
6255
3. **Secret:** `$WEBHOOK_SECRET`
6356
4. **SSL verification:** Select _Enable SSL verification_
@@ -67,47 +60,91 @@ the correct ones:
6760

6861
## Starting the master
6962

70-
First, write all the secrets to the corresponding files:
63+
Choose a directory to hold artifacts from package builds (the default is
64+
`./data/artifacts`):
7165

7266
```console
73-
$ echo "$GITHUB_TOKEN" > secrets/github_token.txt
74-
$ echo "$WORKER_SECRET" > secrets/halide_bb_pass.txt
75-
$ echo "$WEBHOOK_SECRET" > secrets/webhook_token.txt
76-
$ echo "$WWW_PASSWORD" > secrets/buildbot_www_pass.txt
67+
$ export HALIDE_BB_MASTER_ARTIFACTS_DIR=/srv/www/buildbot/public_html/artifacts
7768
```
7869

79-
Then, create a database for the master to save its work. This only needs to be
80-
done once.
70+
Then start all services:
8171

8272
```console
83-
$ ./master.sh upgrade-master
73+
$ docker compose up -d --build
8474
```
8575

86-
Choose a directory to hold artifacts for package runs:
76+
The database is automatically initialized on first start. Caddy handles TLS
77+
certificates, so there is no manual web server configuration needed. The
78+
Buildbot web interface is available at `https://buildbot.halide-lang.org/master/`
79+
and artifacts are served at the site root.
80+
81+
Port 9990 must be reachable by workers. Port 8012 is internal only; Caddy
82+
proxies it on ports 80/443.
83+
84+
### Running without Docker
85+
86+
By default, the master uses a SQLite database (`sqlite:///state.sqlite`), so
87+
no external database is required. To use PostgreSQL instead, set
88+
`HALIDE_BB_MASTER_DB_URL`:
8789

8890
```console
89-
$ export HALIDE_BB_MASTER_ARTIFACTS_DIR=/srv/www/buildbot/public_html/artifacts
91+
$ export HALIDE_BB_MASTER_DB_URL="postgresql://buildbot:{DB_PASSWORD}@db/buildbot"
9092
```
9193

92-
Finally, start the master!
94+
Then start the master:
9395

9496
```console
9597
$ ./master.sh start
9698
```
9799

100+
The script automatically runs `upgrade-master` before starting. If the master
101+
is already running, invoking `./master.sh` with no arguments will reconfig it
102+
instead.
103+
98104
# Worker configuration
99105

100106
The master recognizes workers by their reported names, e.g. `linux-worker-4`
101-
or `win-worker-1`. To launch the buildbot daemon on the worker named
102-
`$WORKER_NAME`, run the following commands after setting up the Python
103-
environment as detailed above:
107+
or `win-worker-1`.
108+
109+
## Linux / macOS
110+
111+
Write the worker secret and set the worker name, then use the wrapper script:
104112

105113
```console
106114
$ echo "$WORKER_SECRET" > worker/halide_bb_pass.txt
107-
$ export HALIDE_BB_WORKER_NAME=$WORKER_NAME # required
108-
$ export HALIDE_BB_MASTER_ADDR=$MASTER_ADDR # default = public Halide master
109-
$ export HALIDE_BB_MASTER_PORT=$MASTER_PORT # default = 9990
110-
$ uv run --package worker buildbot-worker start worker
115+
$ export HALIDE_BB_WORKER_NAME=$WORKER_NAME
116+
$ ./worker.sh
111117
```
112118

113-
[uv]: https://docs.astral.sh/uv
119+
## Windows
120+
121+
```powershell
122+
> Set-Content worker/halide_bb_pass.txt "$WORKER_SECRET"
123+
> $env:HALIDE_BB_WORKER_NAME = "$WORKER_NAME"
124+
> .\worker.ps1
125+
```
126+
127+
## Optional environment variables
128+
129+
| Variable | Default | Description |
130+
|-------------------------|----------------------------|-----------------|
131+
| `HALIDE_BB_MASTER_ADDR` | `buildbot.halide-lang.dev` | Master hostname |
132+
| `HALIDE_BB_MASTER_PORT` | `9990` | Master PB port |
133+
134+
## Platform-specific installation
135+
136+
Automated installation scripts that set up system dependencies and configure
137+
the worker to start automatically are provided under `worker/`:
138+
139+
- **macOS:** `worker/macos/install.sh` — installs Homebrew dependencies,
140+
configures ccache, and installs a launchd agent so the worker starts on login.
141+
Requires `HALIDE_BB_WORKER_NAME`, `HL_WEBGPU_NODE_BINDINGS`,
142+
`HL_WEBGPU_NATIVE_LIB`, and `EMSDK` to be set before running.
143+
144+
- **Windows:** `worker/windows/install.ps1` — installs dependencies via winget,
145+
sets up Visual Studio 2022, installs uv, and bootstraps vcpkg with the
146+
required libraries.
147+
148+
[Caddy]: https://caddyserver.com
149+
[dc]: https://docs.docker.com/compose/
150+
[uv]: https://docs.astral.sh/uv

docker-compose.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ services:
99
POSTGRES_DB: buildbot
1010
POSTGRES_USER: buildbot
1111
POSTGRES_PASSWORD_FILE: /run/secrets/db_password.txt
12+
logging:
13+
driver: local
1214
restart: unless-stopped
1315

1416
buildbot:
@@ -31,6 +33,9 @@ services:
3133
environment:
3234
HALIDE_BB_MASTER_ARTIFACTS_DIR: /artifacts
3335
HALIDE_BB_MASTER_SECRETS_DIR: /run/secrets
36+
HALIDE_BB_MASTER_DB_URL: "postgresql://buildbot:{DB_PASSWORD}@db/buildbot"
37+
logging:
38+
driver: local
3439
restart: unless-stopped
3540

3641
caddy:
@@ -44,6 +49,8 @@ services:
4449
- caddy-data:/data
4550
- caddy-config:/config
4651
- ${HALIDE_BB_MASTER_ARTIFACTS_DIR:-./data/artifacts}:/artifacts:ro
52+
logging:
53+
driver: local
4754
restart: unless-stopped
4855

4956
volumes:

master.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,19 @@ fi
2828
# Check necessary files are present
2929

3030
secrets_dir="${HALIDE_BB_MASTER_SECRETS_DIR:-secrets}"
31-
for secret in buildbot_www_pass db_password github_token halide_bb_pass webhook_token; do
31+
for secret in buildbot_www_pass github_token halide_bb_pass webhook_token; do
3232
if [ ! -s "$secrets_dir/${secret}.txt" ]; then
3333
fail "Missing or empty $secrets_dir/${secret}.txt: cannot continue"
3434
fi
3535
done
3636

37+
db_url="${HALIDE_BB_MASTER_DB_URL:-sqlite:///state.sqlite}"
38+
if echo "$db_url" | grep -q '{DB_PASSWORD}'; then
39+
if [ ! -s "$secrets_dir/db_password.txt" ]; then
40+
fail "Missing or empty $secrets_dir/db_password.txt: required by HALIDE_BB_MASTER_DB_URL"
41+
fi
42+
fi
43+
3744
##
3845
# Resolve the buildbot command
3946

master/Dockerfile

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,17 @@ RUN apt-get update \
2121
# Non-root user
2222
RUN useradd --create-home --home-dir /buildbot buildbot
2323

24+
USER buildbot
25+
WORKDIR /buildbot
26+
2427
# Copy virtual environment from builder
25-
COPY --from=builder /buildbot/.venv /buildbot/.venv
28+
COPY --from=builder --chown=buildbot:buildbot /buildbot/.venv /buildbot/.venv
2629
ENV PATH="/buildbot/.venv/bin:$PATH" \
2730
VIRTUAL_ENV="/buildbot/.venv"
2831

29-
# Copy master source files
30-
COPY master/master.cfg \
31-
master/custom_steps.py \
32-
master/buildbot.tac \
33-
master/toolchain.linux-arm32.cmake \
34-
/buildbot/master/
35-
36-
COPY master.sh /buildbot/master.sh
37-
RUN chmod +x /buildbot/master.sh
38-
39-
# Ensure buildbot owns its home directory
40-
RUN chown -R buildbot:buildbot /buildbot
41-
42-
USER buildbot
43-
WORKDIR /buildbot
32+
# Copy source files
33+
COPY --chown=buildbot:buildbot master/ master/
34+
COPY --chown=buildbot:buildbot master.sh master.sh
4435

4536
EXPOSE 8012 9990
4637

master/buildbot.tac

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,14 @@
1-
import os
1+
import sys
22
from pathlib import Path
33

44
from buildbot.master import BuildMaster
55
from twisted.application import service
6-
from twisted.python.log import ILogObserver, FileLogObserver
7-
from twisted.python.logfile import LogFile
8-
9-
basedir = str(Path(__file__).parent.resolve())
10-
rotateLength = 10000000
11-
maxRotatedFiles = 10
12-
configfile = "master.cfg"
13-
14-
# Default umask for server
15-
umask = None
16-
17-
logfile = LogFile.fromFullPath(
18-
os.path.join(basedir, "twistd.log"), rotateLength=rotateLength, maxRotatedFiles=maxRotatedFiles
19-
)
6+
from twisted.logger import ILogObserver, textFileLogObserver
207

218
# note: this line is matched against to check that this is a buildmaster
229
# directory; do not edit it.
2310
application = service.Application('buildmaster') # fmt: skip
24-
application.setComponent(ILogObserver, FileLogObserver(logfile).emit)
11+
application.setComponent(ILogObserver, textFileLogObserver(sys.stdout))
2512

26-
m = BuildMaster(basedir, configfile, umask)
13+
m = BuildMaster(str(Path(__file__).parent), "master.cfg", umask=None)
2714
m.setServiceParent(application)
28-
m.log_rotation.rotateLength = rotateLength
29-
m.log_rotation.maxRotatedFiles = maxRotatedFiles

master/master.cfg

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,14 @@ SECRETS_DIR = REPO_DIR / os.environ.get("HALIDE_BB_MASTER_SECRETS_DIR", "secrets
5252
# SECRETS
5353

5454
BUILDBOT_WWW_PASS = (SECRETS_DIR / "buildbot_www_pass.txt").read_text().strip()
55-
DB_PASSWORD = (SECRETS_DIR / "db_password.txt").read_text().strip()
5655
GITHUB_TOKEN = (SECRETS_DIR / "github_token.txt").read_text().strip()
5756
HALIDE_BB_PASS = (SECRETS_DIR / "halide_bb_pass.txt").read_text().strip()
5857
WEBHOOK_TOKEN = (SECRETS_DIR / "webhook_token.txt").read_text().strip()
5958

59+
DB_URL = os.environ.get("HALIDE_BB_MASTER_DB_URL", "sqlite:///state.sqlite")
60+
if "{DB_PASSWORD}" in DB_URL:
61+
DB_PASSWORD = (SECRETS_DIR / "db_password.txt").read_text().strip()
62+
DB_URL = DB_URL.replace("{DB_PASSWORD}", DB_PASSWORD)
6063

6164
# LLVM
6265

@@ -2200,7 +2203,7 @@ c["buildbotURL"] = "https://buildbot.halide-lang.org/master/"
22002203
# DB URL
22012204

22022205
c["db"] = {
2203-
"db_url": f"postgresql://buildbot:{DB_PASSWORD}@db/buildbot",
2206+
"db_url": DB_URL,
22042207
}
22052208

22062209
# GitHub Integration

0 commit comments

Comments
 (0)