mirror of
https://github.com/tale/headplane.git
synced 2026-07-26 07:48:14 +00:00
chore: switch to build script
This commit is contained in:
+8
-4
@@ -1,7 +1,11 @@
|
|||||||
node_modules
|
|
||||||
.dockerignore
|
|
||||||
Dockerfile
|
|
||||||
|
|
||||||
/.cache
|
/.cache
|
||||||
|
/.github
|
||||||
|
/.react-router
|
||||||
|
/node_modules
|
||||||
/build
|
/build
|
||||||
|
/docs
|
||||||
|
/nix
|
||||||
|
|
||||||
|
.dockerignore
|
||||||
.env
|
.env
|
||||||
|
Dockerfile
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ jobs:
|
|||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod', '**/go.sum') }}
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.mod', '**/go.sum') }}
|
||||||
|
|
||||||
- name: CI pipeline
|
- name: CI pipeline
|
||||||
run: mise run ci
|
run: ./build.sh --skip-pnpm-prune
|
||||||
|
|
||||||
nix:
|
nix:
|
||||||
name: nix
|
name: nix
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"formatter": {
|
|
||||||
"language_server": {
|
|
||||||
"name": "biome"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"code_actions_on_format": {
|
|
||||||
"source.fixAll.biome": true,
|
|
||||||
"source.organizeImports.biome": true,
|
|
||||||
"source.organizeImports": true
|
|
||||||
},
|
|
||||||
"languages": {
|
|
||||||
"YAML": {
|
|
||||||
"tab_size": 2,
|
|
||||||
"hard_tabs": false
|
|
||||||
},
|
|
||||||
"Go": {
|
|
||||||
"formatter": {
|
|
||||||
"language_server": {
|
|
||||||
"name": "gopls"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+39
-37
@@ -1,11 +1,7 @@
|
|||||||
FROM --platform=$BUILDPLATFORM jdxcode/mise:latest AS mise-context
|
FROM --platform=$BUILDPLATFORM golang:1.25.1 AS go-base
|
||||||
COPY mise.toml ./
|
WORKDIR /run
|
||||||
RUN --mount=type=secret,id=gh_token,env=MISE_GITHUB_TOKEN mise install
|
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM mise-context AS go-build
|
COPY go.mod go.sum build.sh ./
|
||||||
WORKDIR /build/
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
COPY cmd/ ./cmd/
|
COPY cmd/ ./cmd/
|
||||||
@@ -14,51 +10,57 @@ COPY internal/ ./internal/
|
|||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG IMAGE_TAG
|
ARG IMAGE_TAG
|
||||||
RUN mkdir -p /build/app/ && \
|
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 IMAGE_TAG=$IMAGE_TAG \
|
||||||
GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 IMAGE_TAG=$IMAGE_TAG \
|
./build.sh --wasm --agent --fake-shell \
|
||||||
mise run wasm ::: agent ::: fake-shell
|
--wasm-output /bin/hp_ssh.wasm \
|
||||||
|
--agent-output /bin/hp_agent \
|
||||||
|
--fake-shell-output /bin/fake-sh
|
||||||
|
|
||||||
RUN chmod +x /build/build/hp_agent
|
RUN chmod +x /bin/hp_ssh.wasm
|
||||||
RUN chmod +x /build/build/sh
|
RUN chmod +x /bin/hp_agent
|
||||||
|
RUN chmod +x /bin/fake-sh
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM mise-context AS js-build
|
# Folder needs to exist for later stages
|
||||||
WORKDIR /build
|
RUN mkdir -p /var/lib/headplane/agent
|
||||||
|
|
||||||
|
FROM --platform=$BUILDPLATFORM node:22.16-slim AS js-base
|
||||||
|
WORKDIR /run
|
||||||
|
|
||||||
|
RUN corepack enable
|
||||||
COPY patches ./patches
|
COPY patches ./patches
|
||||||
COPY package.json pnpm-lock.yaml ./
|
COPY package.json pnpm-lock.yaml build.sh ./
|
||||||
RUN pnpm install --frozen-lockfile
|
|
||||||
|
COPY --from=go-base /bin/hp_ssh.wasm /run/app/hp_ssh.wasm
|
||||||
|
COPY --from=go-base /bin/wasm_exec.js /run/app/wasm_exec.js
|
||||||
|
RUN ./build.sh --app --app-install-only
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN mise trust
|
RUN ./build.sh --app
|
||||||
COPY --from=go-build /build/app/hp_ssh.wasm /build/app/hp_ssh.wasm
|
|
||||||
COPY --from=go-build /build/app/wasm_exec.js /build/app/wasm_exec.js
|
|
||||||
|
|
||||||
ARG IMAGE_TAG
|
|
||||||
RUN IMAGE_TAG=$IMAGE_TAG pnpm run build
|
|
||||||
RUN mkdir -p /var/lib/headplane/agent
|
|
||||||
RUN pnpm prune --prod
|
|
||||||
|
|
||||||
FROM gcr.io/distroless/nodejs22-debian12:latest AS final
|
FROM gcr.io/distroless/nodejs22-debian12:latest AS final
|
||||||
COPY --from=js-build /build/build/ /app/build/
|
COPY --from=js-base /run/build /app/build
|
||||||
COPY --from=js-build /build/drizzle /app/drizzle/
|
COPY --from=js-base /run/drizzle /app/drizzle
|
||||||
COPY --from=js-build /var/lib/headplane /var/lib/headplane
|
COPY --from=js-base /run/node_modules /app/node_modules
|
||||||
COPY --from=js-build /build/node_modules/ /app/node_modules/
|
|
||||||
COPY --from=go-build /build/build/hp_agent /usr/libexec/headplane/agent
|
COPY --from=go-base /bin/hp_agent /usr/libexec/headplane/agent
|
||||||
|
COPY --from=go-base /var/lib/headplane /var/lib/headplane
|
||||||
|
|
||||||
# Fake shell to inform the user that they should use the debug image
|
# Fake shell to inform the user that they should use the debug image
|
||||||
COPY --from=go-build /build/build/sh /bin/sh
|
COPY --from=go-base /bin/fake-sh /bin/sh
|
||||||
COPY --from=go-build /build/build/sh /bin/bash
|
COPY --from=go-base /bin/fake-sh /bin/bash
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
CMD [ "/app/build/server/index.js" ]
|
CMD [ "/app/build/server/index.js" ]
|
||||||
|
|
||||||
FROM node:22-alpine AS debug-shell
|
FROM node:22-alpine AS debug-shell
|
||||||
RUN apk add --no-cache bash curl git
|
RUN apk add --no-cache bash curl
|
||||||
|
|
||||||
COPY --from=js-build /build/build/ /app/build/
|
COPY --from=js-base /run/build /app/build
|
||||||
COPY --from=js-build /build/drizzle /app/drizzle/
|
COPY --from=js-base /run/drizzle /app/drizzle
|
||||||
COPY --from=js-build /var/lib/headplane /var/lib/headplane
|
COPY --from=js-base /run/node_modules /app/node_modules
|
||||||
COPY --from=js-build /build/node_modules/ /app/node_modules/
|
|
||||||
COPY --from=go-build /build/build/hp_agent /usr/libexec/headplane/agent
|
COPY --from=go-base /bin/hp_agent /usr/libexec/headplane/agent
|
||||||
|
COPY --from=go-base /var/lib/headplane /var/lib/headplane
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
CMD [ "node", "/app/build/server/index.js" ]
|
CMD [ "node", "/app/build/server/index.js" ]
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
FROM golang:1.23 AS builder
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
COPY agent/ ./agent
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build \
|
|
||||||
-trimpath \
|
|
||||||
-ldflags "-s -w" \
|
|
||||||
-o /app/hp_agent ./agent/cmd/hp_agent
|
|
||||||
|
|
||||||
FROM scratch
|
|
||||||
COPY --from=builder /app/hp_agent /hp_agent
|
|
||||||
ENTRYPOINT ["/hp_agent"]
|
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# This is a general purpose build script for Headplane to be used across many
|
||||||
|
# different environments such as CI, Docker, Nix, and locally. For specific
|
||||||
|
# usage instructions, run `./build.sh --help`.
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
cd "$ROOT_DIR" || exit 1
|
||||||
|
|
||||||
|
APP_DIR="$ROOT_DIR/app"
|
||||||
|
BUILD_DIR="$ROOT_DIR/build"
|
||||||
|
|
||||||
|
BUILD_WASM=0
|
||||||
|
BUILD_APP=0
|
||||||
|
BUILD_AGENT=0
|
||||||
|
BUILD_FAKE_SHELL=0
|
||||||
|
SKIP_PATH_CHECKS=0
|
||||||
|
SKIP_PNPM_PRUNE=0
|
||||||
|
APP_INSTALL_ONLY=0
|
||||||
|
|
||||||
|
WASM_OUTPUT="$APP_DIR/hp_ssh.wasm"
|
||||||
|
AGENT_OUTPUT="$BUILD_DIR/hp_agent"
|
||||||
|
FAKE_SHELL_OUTPUT="$BUILD_DIR/hp_fake_sh"
|
||||||
|
|
||||||
|
die() { echo "error: $*" >&2; exit 1; }
|
||||||
|
run() { echo ">> $*"; "$@"; }
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--wasm) BUILD_WASM=1 ;;
|
||||||
|
--app) BUILD_APP=1 ;;
|
||||||
|
--agent) BUILD_AGENT=1 ;;
|
||||||
|
--fake-shell) BUILD_FAKE_SHELL=1 ;;
|
||||||
|
--skip-path-checks) SKIP_PATH_CHECKS=1 ;;
|
||||||
|
--skip-pnpm-prune) SKIP_PNPM_PRUNE=1 ;;
|
||||||
|
--app-install-only) APP_INSTALL_ONLY=1 ;;
|
||||||
|
|
||||||
|
--wasm-output)
|
||||||
|
shift
|
||||||
|
[ $# -gt 0 ] || die "--wasm-output requires a path"
|
||||||
|
WASM_OUTPUT=$1
|
||||||
|
;;
|
||||||
|
|
||||||
|
--agent-output)
|
||||||
|
shift
|
||||||
|
[ $# -gt 0 ] || die "--agent-output requires a path"
|
||||||
|
AGENT_OUTPUT=$1
|
||||||
|
;;
|
||||||
|
|
||||||
|
--fake-shell-output)
|
||||||
|
shift
|
||||||
|
[ $# -gt 0 ] || die "--fake-shell-output requires a path"
|
||||||
|
FAKE_SHELL_OUTPUT=$1
|
||||||
|
;;
|
||||||
|
|
||||||
|
--help)
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [flags]
|
||||||
|
--wasm build wasm module
|
||||||
|
--app build react-router app
|
||||||
|
--agent build tailscale agent
|
||||||
|
--fake-shell build fake shell binary (for Docker)
|
||||||
|
--skip-path-checks skip safety checks (ie. checking PATH)
|
||||||
|
--skip-pnpm-prune skip pruning devDependencies from node_modules
|
||||||
|
--app-install-only only install app dependencies, skip build
|
||||||
|
--wasm-output <path> override wasm output path
|
||||||
|
--agent-output <path> override agent output path
|
||||||
|
--fake-shell-output <path> override fake shell output path
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "unknown flag: $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# By default build everything except for the fake shell
|
||||||
|
if [ "$BUILD_WASM" -eq 0 ] && [ "$BUILD_APP" -eq 0 ] && \
|
||||||
|
[ "$BUILD_AGENT" -eq 0 ] && [ "$BUILD_FAKE_SHELL" -eq 0 ]; then
|
||||||
|
BUILD_WASM=1
|
||||||
|
BUILD_APP=1
|
||||||
|
BUILD_AGENT=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SKIP_PATH_CHECKS" -eq 0 ]; then
|
||||||
|
[ -d "$ROOT_DIR" ] || die "missing project root"
|
||||||
|
|
||||||
|
need_go=0
|
||||||
|
need_pnpm=0
|
||||||
|
|
||||||
|
[ "$BUILD_WASM" -eq 1 ] && need_go=1
|
||||||
|
[ "$BUILD_APP" -eq 1 ] && need_pnpm=1
|
||||||
|
[ "$BUILD_AGENT" -eq 1 ] && need_go=1
|
||||||
|
[ "$BUILD_FAKE_SHELL" -eq 1 ] && need_go=1
|
||||||
|
|
||||||
|
if [ $need_go -eq 1 ]; then
|
||||||
|
echo "==> Checking for Go toolchain"
|
||||||
|
command -v go >/dev/null 2>&1 || die "go not installed"
|
||||||
|
go version >/dev/null 2>&1 || die "go not working"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $need_pnpm -eq 1 ]; then
|
||||||
|
echo "==> Checking for pnpm"
|
||||||
|
command -v pnpm >/dev/null 2>&1 || die "pnpm not installed"
|
||||||
|
pnpm --version >/dev/null 2>&1 || die "pnpm not working"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
build_wasm() {
|
||||||
|
echo "==> Building SSH WASM module → $WASM_OUTPUT"
|
||||||
|
mkdir -p "$(dirname "$WASM_OUTPUT")"
|
||||||
|
echo "// $(go version)" > "$(dirname "$WASM_OUTPUT")/wasm_exec.js"
|
||||||
|
|
||||||
|
# This depends on Go 1.23+ since the path is different in earlier versions
|
||||||
|
cat "$(go env GOROOT)/lib/wasm/wasm_exec.js" >> \
|
||||||
|
"$(dirname "$WASM_OUTPUT")/wasm_exec.js"
|
||||||
|
|
||||||
|
GOOS=js GOARCH=wasm go build -o "$WASM_OUTPUT" ./cmd/hp_ssh
|
||||||
|
}
|
||||||
|
|
||||||
|
build_app() {
|
||||||
|
echo "==> Building React Router app → $BUILD_DIR"
|
||||||
|
[ -f "$WASM_OUTPUT" ] || echo "warning: Building without SSH WASM module"
|
||||||
|
pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
if [ "$APP_INSTALL_ONLY" -eq 1 ]; then
|
||||||
|
echo "==> Skipping app build (install only)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
if [ "$SKIP_PNPM_PRUNE" -eq 0 ]; then
|
||||||
|
echo "==> Pruning devDependencies from node_modules"
|
||||||
|
pnpm prune --prod
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
build_agent() {
|
||||||
|
echo "==> Building Tailscale agent → $AGENT_OUTPUT"
|
||||||
|
mkdir -p "$(dirname "$AGENT_OUTPUT")"
|
||||||
|
go build -o "$AGENT_OUTPUT" ./cmd/hp_agent
|
||||||
|
}
|
||||||
|
|
||||||
|
build_fake_shell() {
|
||||||
|
[ -n "${IMAGE_TAG:-}" ] || die \
|
||||||
|
"\$IMAGE_TAG is required to build fake shell binary"
|
||||||
|
|
||||||
|
echo "==> Building fake shell binary → $FAKE_SHELL_OUTPUT"
|
||||||
|
mkdir -p "$(dirname "$FAKE_SHELL_OUTPUT")"
|
||||||
|
go build -ldflags="-s -w -X main.imageTag=${IMAGE_TAG}" \
|
||||||
|
-o "$FAKE_SHELL_OUTPUT" ./cmd/fake_sh
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$BUILD_FAKE_SHELL" = 1 ] && build_fake_shell
|
||||||
|
|
||||||
|
[ "$BUILD_WASM" = 1 ] && build_wasm
|
||||||
|
[ "$BUILD_APP" = 1 ] && build_app
|
||||||
|
[ "$BUILD_AGENT" = 1 ] && build_agent
|
||||||
|
[ "$BUILD_FAKE_SHELL" = 1 ] && build_fake_shell
|
||||||
|
|
||||||
|
echo "✅ Build complete."
|
||||||
@@ -3,37 +3,6 @@ go = "1.25.1"
|
|||||||
pnpm = "10.4.0"
|
pnpm = "10.4.0"
|
||||||
node = "22.16"
|
node = "22.16"
|
||||||
|
|
||||||
[tasks.copy-wasm-shim]
|
|
||||||
alias = ["gojs"]
|
|
||||||
description = "Copies Go's wasm_exec.js to the public directory"
|
|
||||||
run = [
|
|
||||||
"echo // $(go version) > app/wasm_exec.js",
|
|
||||||
"cat $(go env GOROOT)/lib/wasm/wasm_exec.js >> app/wasm_exec.js",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tasks.build-go-wasm]
|
|
||||||
alias = ["wasm"]
|
|
||||||
depends = ["copy-wasm-shim"]
|
|
||||||
description = "Builds the Go WebAssembly module for Tailscale SSH"
|
|
||||||
env = { GOOS = "js", GOARCH = "wasm" }
|
|
||||||
run = "go build -o app/hp_ssh.wasm ./cmd/hp_ssh"
|
|
||||||
|
|
||||||
[tasks.build-go-agent]
|
|
||||||
alias = ["agent"]
|
|
||||||
description = "Builds the Go agent for HostInfo"
|
|
||||||
run = "go build -o build/hp_agent ./cmd/hp_agent"
|
|
||||||
# env = { CGO_ENABLED = "1" }
|
|
||||||
# run = "go build -o build/hp_agent.so -buildmode=c-shared ./cmd/hp_agent"
|
|
||||||
|
|
||||||
|
|
||||||
[tasks.build-fake-shell]
|
|
||||||
alias = ["fake-shell"]
|
|
||||||
description = "Builds the fake shell for Distroless docker images"
|
|
||||||
run = [
|
|
||||||
'test -n "$IMAGE_TAG" || (echo "IMAGE_TAG is not set" && exit 1)',
|
|
||||||
'go build -ldflags="-s -w -X main.imageTag=$IMAGE_TAG" -o build/sh ./cmd/fake_sh'
|
|
||||||
]
|
|
||||||
|
|
||||||
[tasks.build-nixos-docs]
|
[tasks.build-nixos-docs]
|
||||||
alias = ["nixos-docs"]
|
alias = ["nixos-docs"]
|
||||||
description = "Builds NixOS module documentation"
|
description = "Builds NixOS module documentation"
|
||||||
|
|||||||
@@ -6,9 +6,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"prebuild": "npx @jdxcode/mise run build-go-wasm",
|
|
||||||
"build": "react-router build",
|
"build": "react-router build",
|
||||||
"postbuild": "npx @jdxcode/mise run build-go-agent",
|
|
||||||
"dev": "HEADPLANE_LOAD_ENV_OVERRIDES=true HEADPLANE_CONFIG_PATH=./config.example.yaml react-router dev",
|
"dev": "HEADPLANE_LOAD_ENV_OVERRIDES=true HEADPLANE_CONFIG_PATH=./config.example.yaml react-router dev",
|
||||||
"start": "node build/server/index.js",
|
"start": "node build/server/index.js",
|
||||||
"typecheck": "react-router typegen && tsgo",
|
"typecheck": "react-router typegen && tsgo",
|
||||||
|
|||||||
Reference in New Issue
Block a user