fresh build
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
GITEA_SERVER_URL=
|
||||
GITEA_REPOSITORY=
|
||||
GITEA_TOKEN=
|
||||
GITEA_REF_NAME=
|
||||
@@ -1,2 +0,0 @@
|
||||
out/
|
||||
.env
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Runs INSIDE the .build/prod container. Clones, patches, builds the binary,
|
||||
# smoke-tests it, and drops it in .build/prod/out/ for the release step.
|
||||
#
|
||||
set -euo pipefail
|
||||
cd /source
|
||||
|
||||
# The repo is bind-mounted from the host (different uid), so mark it safe:
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
OUT_DIR="/source/.build/prod/out"
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
bash scripts/build.sh
|
||||
bash scripts/smoke.sh dist/httptoolkit
|
||||
|
||||
cp -v dist/httptoolkit "$OUT_DIR/httptoolkit"
|
||||
echo "==> Artifacts:"
|
||||
ls -lh "$OUT_DIR"
|
||||
@@ -1,22 +0,0 @@
|
||||
services:
|
||||
prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: htk-prod-builder:local
|
||||
network_mode: host
|
||||
working_dir: /source
|
||||
environment:
|
||||
- PUPPETEER_SKIP_DOWNLOAD=true
|
||||
- PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
volumes:
|
||||
# The whole repo (with submodules already checked out by the CI step):
|
||||
- ../../:/source
|
||||
# Persist package caches between runs to speed up rebuilds:
|
||||
- htk-npm-cache:/root/.npm
|
||||
- htk-bun-cache:/root/.bun/install/cache
|
||||
command: bash .build/prod/build.sh
|
||||
|
||||
volumes:
|
||||
htk-npm-cache:
|
||||
htk-bun-cache:
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Publish a NEW Gitea release for this build and upload everything in out/.
|
||||
# Never deletes existing releases/tags - each build gets its own tag.
|
||||
#
|
||||
# Config via env (or a local .env next to this script):
|
||||
# GITEA_SERVER_URL, GITEA_REPOSITORY, PAT_GITEA
|
||||
# Tag: $1 if given, else derived as v<server-version>-<shortsha>
|
||||
# (a build suffix is appended if that tag already exists).
|
||||
#
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Optional: load credentials from a local .env for manual runs.
|
||||
[ -f .env ] && source ./.env
|
||||
|
||||
: "${GITEA_SERVER_URL:?}"
|
||||
: "${GITEA_REPOSITORY:?}"
|
||||
: "${PAT_GITEA:?}"
|
||||
|
||||
ROOT="$(git rev-parse --show-toplevel)"
|
||||
SHA="$(git rev-parse HEAD)"
|
||||
SHORT="$(git rev-parse --short HEAD)"
|
||||
OUT_DIR="$(pwd)/out"
|
||||
REPO_API="${GITEA_SERVER_URL}/api/v1/repos/${GITEA_REPOSITORY}"
|
||||
AUTH=(-H "Authorization: token ${PAT_GITEA}")
|
||||
|
||||
# Resolve a unique release tag:
|
||||
TAG="${1:-}"
|
||||
if [ -z "$TAG" ]; then
|
||||
VER="$(jq -r .version "$ROOT/httptoolkit-server/package.json")"
|
||||
TAG="v${VER}-${SHORT}"
|
||||
# If a release for this commit already exists (e.g. a scheduled rebuild of an
|
||||
# unchanged commit), keep the old one and make this tag unique instead.
|
||||
if curl -sf "${AUTH[@]}" "${REPO_API}/releases/tags/${TAG}" > /dev/null 2>&1; then
|
||||
TAG="${TAG}-${GITHUB_RUN_NUMBER:-$(date -u +%Y%m%d%H%M%S)}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "==> Creating release $TAG @ $SHORT"
|
||||
RESP=$(curl -s -X POST "${REPO_API}/releases" "${AUTH[@]}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"tag_name\": \"${TAG}\",
|
||||
\"target_commitish\": \"${SHA}\",
|
||||
\"name\": \"HTTP Toolkit ${TAG}\",
|
||||
\"body\": \"Self-hosted single-file build from ${SHORT}.\",
|
||||
\"draft\": false,
|
||||
\"prerelease\": false
|
||||
}")
|
||||
|
||||
RID=$(echo "$RESP" | jq -r '.id // empty')
|
||||
if [ -z "$RID" ]; then
|
||||
echo "!! Failed to create release:"; echo "$RESP"; exit 1
|
||||
fi
|
||||
echo "==> Release id $RID"
|
||||
|
||||
# Upload artifacts.
|
||||
shopt -s nullglob
|
||||
for f in "$OUT_DIR"/*; do
|
||||
[ -f "$f" ] || continue
|
||||
name=$(basename "$f")
|
||||
echo "==> Uploading $name"
|
||||
curl -s -X POST "${REPO_API}/releases/${RID}/assets?name=${name}" "${AUTH[@]}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@${f}" > /dev/null
|
||||
done
|
||||
echo "==> Release complete."
|
||||
@@ -1,7 +1,8 @@
|
||||
# Builder image for the self-hosted HTTP Toolkit single-file binary (Linux x64).
|
||||
# Provides Node, Bun, and the toolchain needed to build the server's native modules.
|
||||
FROM node:22-bookworm
|
||||
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
||||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
python3 \
|
||||
@@ -14,8 +15,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
jq \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Bun (used for the single-file `--compile` step)
|
||||
RUN curl -fsSL https://bun.sh/install | bash
|
||||
ENV PATH="/root/.bun/bin:${PATH}"
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
CMD /source/build.sh
|
||||
@@ -1,128 +0,0 @@
|
||||
# Self-hosted HTTP Toolkit
|
||||
|
||||
A private distribution repo that builds [HTTP Toolkit](https://httptoolkit.com) into a
|
||||
**single self-contained binary** that runs the backend and serves the web UI locally:
|
||||
|
||||
```bash
|
||||
./httptoolkit --port 7070
|
||||
# → starts the proxy server and opens the web UI at http://localhost:7070
|
||||
```
|
||||
|
||||
No Electron, no hosted UI, no account/login. Upstream is tracked as **git submodules**
|
||||
and all local modifications live in this repo as **patches** + an **overlay**, so
|
||||
updating to a new upstream release is a controlled, reviewable step.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
.
|
||||
├── httptoolkit-ui/ # submodule → github.com/httptoolkit/httptoolkit-ui (pinned)
|
||||
├── httptoolkit-server/ # submodule → github.com/httptoolkit/httptoolkit-server (pinned)
|
||||
├── patches/
|
||||
│ ├── ui/ # diffs against upstream UI files
|
||||
│ └── server/ # diffs against upstream server files
|
||||
├── overlay/server/ # NEW files copied into the server submodule (never conflict)
|
||||
│ ├── htk-entry.ts # single-file binary entry (Bun)
|
||||
│ └── src/
|
||||
│ ├── htk-app.ts # shared: run backend + serve UI + open browser
|
||||
│ └── commands/app.ts # oclif fallback command
|
||||
├── scripts/
|
||||
│ ├── apply.sh # reset submodules → apply patches → copy overlay
|
||||
│ ├── build.sh # build UI → embed → bun compile → dist/
|
||||
│ └── smoke.sh # launch binary & verify it serves + backend is up
|
||||
├── .build/prod/ # Docker builder (Gitea `docker-compose` runner)
|
||||
│ ├── Dockerfile # Node + Bun + native toolchain
|
||||
│ ├── compose.yml # mounts repo, runs build.sh
|
||||
│ ├── build.sh # build + smoke → out/
|
||||
│ └── release.sh # Gitea-API release + upload
|
||||
└── .gitea/workflows/build.yml
|
||||
```
|
||||
|
||||
## What the patches change
|
||||
|
||||
| Kind | File | Change |
|
||||
|------|------|--------|
|
||||
| UI patch | `src/model/account/account-store.ts` | injects a synthetic active Pro subscription |
|
||||
| UI patch | `src/components/settings/settings-page.tsx` | removes the account/subscription card |
|
||||
| UI patch | `src/components/app.tsx` | removes the "Give feedback" sidebar button |
|
||||
| Server patch | `src/constants.ts` | allow `localhost`/`127.0.0.1` origins in prod builds |
|
||||
| Overlay | `htk-entry.ts`, `src/htk-app.ts`, `src/commands/app.ts` | serve the UI locally + `--port` |
|
||||
|
||||
**Security note:** upstream restricts a packaged build's API to `https://app.httptoolkit.tech`
|
||||
so no *other* local page can drive your proxy. Because we self-host the UI on localhost we
|
||||
must allow localhost origins (this matches upstream's own dev-mode allowlist). Trade-off: any
|
||||
local HTTP page could talk to the server while it's running. Acceptable for a personal tool.
|
||||
|
||||
## Build locally
|
||||
|
||||
Requires **node ≥22**, **npm**, **bun**, and **tar**.
|
||||
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
bash scripts/build.sh # → dist/httptoolkit
|
||||
bash scripts/smoke.sh # optional: verify it runs
|
||||
```
|
||||
|
||||
Run it:
|
||||
|
||||
```bash
|
||||
./dist/httptoolkit --port 7070 # UI on :7070
|
||||
./dist/httptoolkit --no-open # don't auto-open a browser
|
||||
./dist/httptoolkit --help
|
||||
```
|
||||
|
||||
## Updating to a new upstream release
|
||||
|
||||
```bash
|
||||
# bump a submodule to a new tag
|
||||
cd httptoolkit-ui && git fetch && git checkout v<new> && cd ..
|
||||
git add httptoolkit-ui
|
||||
|
||||
# re-apply and see if patches still fit
|
||||
bash scripts/apply.sh
|
||||
```
|
||||
|
||||
If a patch no longer applies, `apply.sh` fails and names the patch. Fix it:
|
||||
|
||||
```bash
|
||||
cd httptoolkit-ui
|
||||
git checkout -- . # reset
|
||||
# hand-apply the change, then regenerate the patch:
|
||||
git diff -- <file> > ../patches/ui/000X-....patch
|
||||
```
|
||||
|
||||
Overlay files never conflict (they're new files), so only the small `patches/` diffs
|
||||
ever need attention on upgrade.
|
||||
|
||||
## Packaging notes / risks
|
||||
|
||||
- **Single file via Bun `--compile`.** The server pulls in native `.node` addons
|
||||
(`node-datachannel`, `registry-js`, `adbkit`, …). These **cannot be cross-compiled**,
|
||||
so the binary is built **per host platform**. `scripts/smoke.sh` is the guard: if a
|
||||
native addon won't load from the embedded FS, it fails there.
|
||||
- **Linux only, for now.** CI builds inside a Linux Docker container, which produces a
|
||||
trustworthy Linux x64 binary. Windows/macOS binaries are **not** reliably buildable
|
||||
from Linux Docker (foreign-platform native addons can't be produced or smoke-tested
|
||||
there, and macOS needs signing) — they'd need real Windows/macOS runners.
|
||||
- The UI is embedded as `ui.tar.gz` and extracted to `$TMPDIR/httptoolkit-ui-<version>`
|
||||
on first run.
|
||||
- No `HTK_SERVER_TOKEN` is set, so the local UI talks to the backend without a token.
|
||||
|
||||
## CI (Gitea Actions, Docker)
|
||||
|
||||
Matches the `docker-compose` runner convention:
|
||||
|
||||
- **`.gitea/workflows/build.yml`** — on a `v*` tag (or manual dispatch): checks out with
|
||||
submodules, runs `docker compose run --rm prod` in `.build/prod/`, then creates a Gitea
|
||||
release and uploads the artifacts via the Gitea API (`secrets.PAT_GITEA`).
|
||||
- **`.build/prod/`** — the Docker builder:
|
||||
- `Dockerfile` — Node 22 + Bun + native-build toolchain
|
||||
- `compose.yml` — mounts the repo at `/source`, caches npm/bun
|
||||
- `build.sh` — runs `scripts/build.sh` + `scripts/smoke.sh`, drops the binary in `out/`
|
||||
- `release.sh` — Gitea-API release + asset upload
|
||||
|
||||
Tag a release:
|
||||
|
||||
```bash
|
||||
git tag v1.27.1 && git push origin v1.27.1
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
cd /source
|
||||
|
||||
|
||||
OUT_DIR="/source/builds"
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
git clone https://github.com/httptoolkit/httptoolkit-ui
|
||||
git clone https://github.com/httptoolkit/httptoolkit-server
|
||||
|
||||
##
|
||||
## add the patch codes here
|
||||
##
|
||||
cp -v dist/httptoolkit "$OUT_DIR/httptoolkit"
|
||||
@@ -0,0 +1,7 @@
|
||||
services:
|
||||
release-httptoolkit:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ./:/source
|
||||
Reference in New Issue
Block a user