CI: GitHub Actions build and release workflows
- build.yml: runs on push to main, builds Docker image + packs s9pk, uploads artifact - release.yml: runs on version tags (v*.*), builds and creates GitHub release with s9pk attached - Dockerfile: build context is repo root (docker build -f deploy/Dockerfile .) - Manifest: switched to dockerTag (pre-built image pattern) - Makefile + s9pk.mk: local build support
This commit is contained in:
@@ -0,0 +1,74 @@
|
|||||||
|
name: Build Service
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore: ['*.md']
|
||||||
|
branches: ['main']
|
||||||
|
push:
|
||||||
|
paths-ignore: ['*.md']
|
||||||
|
branches: ['main']
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y squashfs-tools-ng
|
||||||
|
|
||||||
|
- name: Install start-cli
|
||||||
|
run: |
|
||||||
|
curl -fsSL -o start-cli https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.20/start-cli_x86_64-linux
|
||||||
|
chmod +x start-cli
|
||||||
|
sudo mv start-cli /usr/local/bin/
|
||||||
|
start-cli --version
|
||||||
|
|
||||||
|
- name: Initialize developer key
|
||||||
|
env:
|
||||||
|
DEV_KEY: ${{ secrets.DEV_KEY }}
|
||||||
|
run: |
|
||||||
|
if [ -n "$DEV_KEY" ]; then
|
||||||
|
mkdir -p ~/.startos
|
||||||
|
echo "$DEV_KEY" > ~/.startos/developer.key.pem
|
||||||
|
else
|
||||||
|
start-cli init-key
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build Docker image
|
||||||
|
run: docker build -f deploy/Dockerfile -t ten31portal:local .
|
||||||
|
|
||||||
|
- name: Install StartOS packaging deps
|
||||||
|
working-directory: deploy
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build StartOS JavaScript
|
||||||
|
working-directory: deploy
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Pack s9pk
|
||||||
|
working-directory: deploy
|
||||||
|
run: start-cli s9pk pack --arch x86_64 --license ../LICENSE -o ten31portal.s9pk
|
||||||
|
|
||||||
|
- name: Upload s9pk artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ten31portal-s9pk
|
||||||
|
path: deploy/ten31portal.s9pk
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
name: Release Service
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y squashfs-tools-ng
|
||||||
|
|
||||||
|
- name: Install start-cli
|
||||||
|
run: |
|
||||||
|
curl -fsSL -o start-cli https://github.com/Start9Labs/start-os/releases/download/v0.4.0-alpha.20/start-cli_x86_64-linux
|
||||||
|
chmod +x start-cli
|
||||||
|
sudo mv start-cli /usr/local/bin/
|
||||||
|
start-cli --version
|
||||||
|
|
||||||
|
- name: Initialize developer key
|
||||||
|
env:
|
||||||
|
DEV_KEY: ${{ secrets.DEV_KEY }}
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.startos
|
||||||
|
echo "$DEV_KEY" > ~/.startos/developer.key.pem
|
||||||
|
|
||||||
|
- name: Build Docker image
|
||||||
|
run: docker build -f deploy/Dockerfile -t ten31portal:local .
|
||||||
|
|
||||||
|
- name: Install StartOS packaging deps
|
||||||
|
working-directory: deploy
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build StartOS JavaScript
|
||||||
|
working-directory: deploy
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Pack s9pk
|
||||||
|
working-directory: deploy
|
||||||
|
run: start-cli s9pk pack --arch x86_64 --license ../LICENSE -o ten31portal.s9pk
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
files: deploy/ten31portal.s9pk
|
||||||
|
generate_release_notes: true
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
javascript/
|
javascript/
|
||||||
|
*.s9pk
|
||||||
|
|||||||
+6
-7
@@ -1,18 +1,17 @@
|
|||||||
|
# Build context is the repo root (docker build -f deploy/Dockerfile .)
|
||||||
|
|
||||||
# --- Frontend build stage ---
|
# --- Frontend build stage ---
|
||||||
FROM node:20-slim AS frontend-build
|
FROM node:20-slim AS frontend-build
|
||||||
|
|
||||||
WORKDIR /build/frontend
|
WORKDIR /build
|
||||||
COPY frontend/package.json frontend/package-lock.json ./
|
COPY frontend/package.json frontend/package-lock.json ./
|
||||||
RUN npm ci --include=dev
|
RUN npm ci --include=dev
|
||||||
COPY frontend/ ./
|
COPY frontend/ ./
|
||||||
RUN npx vite build
|
RUN npx vite build
|
||||||
|
|
||||||
# --- Backend stage ---
|
# --- Backend + runtime stage ---
|
||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install Python deps
|
# Install Python deps
|
||||||
@@ -23,7 +22,7 @@ COPY backend/alembic.ini ./
|
|||||||
RUN pip install --no-cache-dir .
|
RUN pip install --no-cache-dir .
|
||||||
|
|
||||||
# Copy built frontend
|
# Copy built frontend
|
||||||
COPY --from=frontend-build /build/frontend/dist ./static/
|
COPY --from=frontend-build /build/dist ./static/
|
||||||
|
|
||||||
# Startup script
|
# Startup script
|
||||||
COPY deploy/start.sh ./start.sh
|
COPY deploy/start.sh ./start.sh
|
||||||
@@ -33,7 +32,7 @@ RUN chmod +x ./start.sh
|
|||||||
RUN mkdir -p /data
|
RUN mkdir -p /data
|
||||||
|
|
||||||
ENV TEN31_DB_PATH=/data/portal.db
|
ENV TEN31_DB_PATH=/data/portal.db
|
||||||
ENV TEN31_SESSION_SECRET=change-me
|
ENV TEN31_SESSION_SECRET=***
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Ten31Portal StartOS package build
|
||||||
|
# Docker image must be built separately before packing:
|
||||||
|
# docker build -f deploy/Dockerfile -t ten31portal:local . (from repo root)
|
||||||
|
# cd deploy && make x86
|
||||||
|
|
||||||
|
LICENSE := ../LICENSE
|
||||||
|
|
||||||
|
include s9pk.mk
|
||||||
|
|
||||||
|
# Override the license path for s9pk pack
|
||||||
|
$(BASE_NAME).s9pk: $(INGREDIENTS) .git/HEAD .git/index
|
||||||
|
@$(MAKE) --no-print-directory ingredients
|
||||||
|
@echo " Packing '$@'..."
|
||||||
|
start-cli s9pk pack --license $(LICENSE) -o $@
|
||||||
|
|
||||||
|
$(BASE_NAME)_%.s9pk: $(INGREDIENTS) .git/HEAD .git/index
|
||||||
|
@$(MAKE) --no-print-directory ingredients
|
||||||
|
@echo " Packing '$@'..."
|
||||||
|
start-cli s9pk pack --arch=$* --license $(LICENSE) -o $@
|
||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
# ** Plumbing. DO NOT EDIT **.
|
||||||
|
# This file is imported by ./Makefile. Make edits there
|
||||||
|
|
||||||
|
PACKAGE_ID := $(shell awk -F"'" '/id:/ {print $$2}' startos/manifest/index.ts)
|
||||||
|
INGREDIENTS := $(shell start-cli s9pk list-ingredients 2>/dev/null)
|
||||||
|
ARCHES ?= x86 arm riscv
|
||||||
|
TARGETS ?= arches
|
||||||
|
ifdef VARIANT
|
||||||
|
BASE_NAME := $(PACKAGE_ID)_$(VARIANT)
|
||||||
|
else
|
||||||
|
BASE_NAME := $(PACKAGE_ID)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: all arches aarch64 x86_64 riscv64 arm arm64 x86 riscv arch/* clean install check-deps check-init package ingredients
|
||||||
|
.DELETE_ON_ERROR:
|
||||||
|
.SECONDARY:
|
||||||
|
|
||||||
|
define SUMMARY
|
||||||
|
@manifest=$$(start-cli s9pk inspect $(1) manifest); \
|
||||||
|
size=$$(du -h $(1) | awk '{print $$1}'); \
|
||||||
|
title=$$(printf '%s' "$$manifest" | jq -r .title); \
|
||||||
|
version=$$(printf '%s' "$$manifest" | jq -r .version); \
|
||||||
|
arches=$$(printf '%s' "$$manifest" | jq -r '[.images[].arch // []] | flatten | unique | join(", ")'); \
|
||||||
|
sdkv=$$(printf '%s' "$$manifest" | jq -r .sdkVersion); \
|
||||||
|
gitHash=$$(printf '%s' "$$manifest" | jq -r .gitHash | sed -E 's/(.*-modified)$$/\x1b[0;31m\1\x1b[0m/'); \
|
||||||
|
printf "\n"; \
|
||||||
|
printf "\033[1;32m✅ Build Complete!\033[0m\n"; \
|
||||||
|
printf "\n"; \
|
||||||
|
printf "\033[1;37m📦 $$title\033[0m \033[36mv$$version\033[0m\n"; \
|
||||||
|
printf "───────────────────────────────\n"; \
|
||||||
|
printf " \033[1;36mFilename:\033[0m %s\n" "$(1)"; \
|
||||||
|
printf " \033[1;36mSize:\033[0m %s\n" "$$size"; \
|
||||||
|
printf " \033[1;36mArch:\033[0m %s\n" "$$arches"; \
|
||||||
|
printf " \033[1;36mSDK:\033[0m %s\n" "$$sdkv"; \
|
||||||
|
printf " \033[1;36mGit:\033[0m %s\n" "$$gitHash"; \
|
||||||
|
echo ""
|
||||||
|
endef
|
||||||
|
|
||||||
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
arches: $(ARCHES)
|
||||||
|
|
||||||
|
universal: $(BASE_NAME).s9pk
|
||||||
|
$(call SUMMARY,$<)
|
||||||
|
|
||||||
|
arch/%: $(BASE_NAME)_%.s9pk
|
||||||
|
$(call SUMMARY,$<)
|
||||||
|
|
||||||
|
x86 x86_64: arch/x86_64
|
||||||
|
arm arm64 aarch64: arch/aarch64
|
||||||
|
riscv riscv64: arch/riscv64
|
||||||
|
|
||||||
|
$(BASE_NAME).s9pk: $(INGREDIENTS) .git/HEAD .git/index
|
||||||
|
@$(MAKE) --no-print-directory ingredients
|
||||||
|
@echo " Packing '$@'..."
|
||||||
|
start-cli s9pk pack -o $@
|
||||||
|
|
||||||
|
$(BASE_NAME)_%.s9pk: $(INGREDIENTS) .git/HEAD .git/index
|
||||||
|
@$(MAKE) --no-print-directory ingredients
|
||||||
|
@echo " Packing '$@'..."
|
||||||
|
start-cli s9pk pack --arch=$* -o $@
|
||||||
|
|
||||||
|
ingredients: $(INGREDIENTS)
|
||||||
|
@echo " Re-evaluating ingredients..."
|
||||||
|
|
||||||
|
install: | check-deps check-init
|
||||||
|
@HOST=$$(awk -F'/' '/^host:/ {print $$3}' ~/.startos/config.yaml); \
|
||||||
|
if [ -z "$$HOST" ]; then \
|
||||||
|
echo "Error: You must define \"host: http://server-name.local\" in ~/.startos/config.yaml"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
S9PK=$$(ls -t *.s9pk 2>/dev/null | head -1); \
|
||||||
|
if [ -z "$$S9PK" ]; then \
|
||||||
|
echo "Error: No .s9pk file found. Run 'make' first."; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
printf "\n🚀 Installing %s to %s ...\n" "$$S9PK" "$$HOST"; \
|
||||||
|
start-cli package install -s "$$S9PK"
|
||||||
|
|
||||||
|
publish: | all
|
||||||
|
@REGISTRY=$$(awk -F'/' '/^registry:/ {print $$3}' ~/.startos/config.yaml); \
|
||||||
|
if [ -z "$$REGISTRY" ]; then \
|
||||||
|
echo "Error: You must define \"registry: https://my-registry.tld\" in ~/.startos/config.yaml"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
S3BASE=$$(awk -F'/' '/^s9pk-s3base:/ {print $$3}' ~/.startos/config.yaml); \
|
||||||
|
if [ -z "$$S3BASE" ]; then \
|
||||||
|
echo "Error: You must define \"s3base: https://s9pks.my-s3-bucket.tld\" in ~/.startos/config.yaml"; \
|
||||||
|
exit 1; \
|
||||||
|
fi; \
|
||||||
|
command -v s3cmd >/dev/null || \
|
||||||
|
(echo "Error: s3cmd not found. It must be installed to publish using s3." && exit 1); \
|
||||||
|
printf "\n🚀 Publishing to %s; indexing on %s ...\n" "$$S3BASE" "$$REGISTRY"; \
|
||||||
|
for s9pk in *.s9pk; do \
|
||||||
|
age=$$(( $$(date +%s) - $$(stat -c %Y "$$s9pk") )); \
|
||||||
|
if [ "$$age" -gt 3600 ]; then \
|
||||||
|
printf "\033[1;33m⚠️ %s is %d minutes old. Publish anyway? [y/N] \033[0m" "$$s9pk" "$$((age / 60))"; \
|
||||||
|
read -r ans; \
|
||||||
|
case "$$ans" in [yY]*) ;; *) echo "Skipping $$s9pk"; continue ;; esac; \
|
||||||
|
fi; \
|
||||||
|
start-cli s9pk publish "$$s9pk"; \
|
||||||
|
done
|
||||||
|
|
||||||
|
check-deps:
|
||||||
|
@command -v start-cli >/dev/null || \
|
||||||
|
(echo "Error: start-cli not found. Please see https://docs.start9.com/latest/developer-guide/sdk/installing-the-sdk" && exit 1)
|
||||||
|
@command -v npm >/dev/null || \
|
||||||
|
(echo "Error: npm not found. Please install Node.js and npm." && exit 1)
|
||||||
|
|
||||||
|
check-init:
|
||||||
|
@if [ ! -f ~/.startos/developer.key.pem ]; then \
|
||||||
|
echo "Initializing StartOS developer environment..."; \
|
||||||
|
start-cli init-key; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
javascript/index.js: $(shell find startos -type f) tsconfig.json node_modules
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
node_modules: package-lock.json
|
||||||
|
npm ci
|
||||||
|
|
||||||
|
package-lock.json: package.json
|
||||||
|
npm i
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "Cleaning up build artifacts..."
|
||||||
|
@rm -rf $(PACKAGE_ID).s9pk $(PACKAGE_ID)_x86_64.s9pk $(PACKAGE_ID)_aarch64.s9pk $(PACKAGE_ID)_riscv64.s9pk javascript node_modules
|
||||||
@@ -16,8 +16,8 @@ export const manifest = setupManifest({
|
|||||||
volumes: ['main'],
|
volumes: ['main'],
|
||||||
images: {
|
images: {
|
||||||
main: {
|
main: {
|
||||||
source: { dockerBuild: { dockerfile: './Dockerfile', workdir: '.' } },
|
source: { dockerTag: 'ten31portal:local' },
|
||||||
arch: ['x86_64', 'aarch64'],
|
arch: ['x86_64'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
alerts: {
|
alerts: {
|
||||||
|
|||||||
Reference in New Issue
Block a user