mirror of
https://github.com/fluxerapp/fluxer.git
synced 2026-09-02 21:04:06 +03:00
workspace: reconcile latest Fluxer into the open source release and continue development there
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
# Like dev/Caddyfile.dev, but LiveKit and Mailpit are referenced by their
|
||||
# Docker Compose hostnames instead of 127.0.0.1.
|
||||
{
|
||||
auto_https off
|
||||
admin off
|
||||
}
|
||||
|
||||
:48763 {
|
||||
handle /_caddy_health {
|
||||
respond "OK" 200
|
||||
}
|
||||
|
||||
@gateway path /gateway /gateway/*
|
||||
handle @gateway {
|
||||
uri strip_prefix /gateway
|
||||
reverse_proxy 127.0.0.1:49107
|
||||
}
|
||||
|
||||
@marketing path /marketing /marketing/*
|
||||
handle @marketing {
|
||||
uri strip_prefix /marketing
|
||||
reverse_proxy 127.0.0.1:49531
|
||||
}
|
||||
|
||||
@server path /admin /admin/* /api /api/* /s3 /s3/* /queue /queue/* /media /media/* /_health /_ready /_live /.well-known/fluxer
|
||||
handle @server {
|
||||
reverse_proxy 127.0.0.1:49319
|
||||
}
|
||||
|
||||
@livekit path /livekit /livekit/*
|
||||
handle @livekit {
|
||||
uri strip_prefix /livekit
|
||||
reverse_proxy livekit:7880
|
||||
}
|
||||
|
||||
redir /mailpit /mailpit/
|
||||
handle_path /mailpit/* {
|
||||
rewrite * /mailpit{path}
|
||||
reverse_proxy mailpit:8025
|
||||
}
|
||||
|
||||
handle {
|
||||
reverse_proxy 127.0.0.1:49427 {
|
||||
header_up Connection {http.request.header.Connection}
|
||||
header_up Upgrade {http.request.header.Upgrade}
|
||||
}
|
||||
}
|
||||
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
}
|
||||
}
|
||||
}
|
||||
+175
-31
@@ -1,40 +1,184 @@
|
||||
# Language runtimes (Node.js, Go, Rust, Python) are installed via devcontainer
|
||||
# features. This Dockerfile handles Erlang/OTP (no feature available) and
|
||||
# tools like Caddy, process-compose, rebar3, uv, ffmpeg, and exiftool.
|
||||
FROM chrislusf/seaweedfs:4.31 AS seaweedfs
|
||||
|
||||
FROM erlang:28-slim AS erlang
|
||||
FROM erlang:28.5.0.1
|
||||
|
||||
FROM mcr.microsoft.com/devcontainers/base:debian-13
|
||||
ARG USERNAME=vscode
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=1000
|
||||
ARG NODE_MAJOR=24
|
||||
ARG ELP_VERSION=2026-02-27
|
||||
ARG HELM_VERSION=4.2.0
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG REBAR3_VERSION=3.24.0
|
||||
ARG PROCESS_COMPOSE_VERSION=1.90.0
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Both erlang:28-slim and debian-13 are Trixie-based, so OpenSSL versions match.
|
||||
COPY --from=erlang /usr/local/lib/erlang /usr/local/lib/erlang
|
||||
RUN ln -sf /usr/local/lib/erlang/bin/* /usr/local/bin/
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libncurses6 libsctp1 \
|
||||
build-essential pkg-config \
|
||||
ffmpeg libimage-exiftool-perl \
|
||||
sqlite3 libsqlite3-dev \
|
||||
libssl-dev openssl \
|
||||
gettext-base lsof iproute2 \
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
bash \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
clang \
|
||||
cmake \
|
||||
curl \
|
||||
dbus-x11 \
|
||||
desktop-file-utils \
|
||||
dpkg-dev \
|
||||
ffmpeg \
|
||||
fakeroot \
|
||||
git \
|
||||
gnupg \
|
||||
imagemagick \
|
||||
jq \
|
||||
libasound2 \
|
||||
libatk-bridge2.0-0 \
|
||||
libavcodec-dev \
|
||||
libavfilter-dev \
|
||||
libavformat-dev \
|
||||
libavutil-dev \
|
||||
libdbus-1-dev \
|
||||
libdrm2 \
|
||||
libfido2-dev \
|
||||
libgbm1 \
|
||||
libgtk-3-0 \
|
||||
libnotify4 \
|
||||
libnss3 \
|
||||
libpipewire-0.3-dev \
|
||||
libpulse-dev \
|
||||
libsecret-1-0 \
|
||||
libudev-dev \
|
||||
libuv1-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libswresample-dev \
|
||||
libswscale-dev \
|
||||
libvips-dev \
|
||||
libwayland-dev \
|
||||
libwebp-dev \
|
||||
libssl-dev \
|
||||
libx11-xcb1 \
|
||||
libxcb-dri3-0 \
|
||||
libxcomposite1 \
|
||||
libxdamage1 \
|
||||
libxkbcommon-dev \
|
||||
libxkbcommon0 \
|
||||
libxrandr2 \
|
||||
libxshmfence1 \
|
||||
libxss1 \
|
||||
libxtst6 \
|
||||
llvm \
|
||||
meson \
|
||||
ninja-build \
|
||||
openssh-client \
|
||||
pkg-config \
|
||||
protobuf-compiler \
|
||||
python3 \
|
||||
python3-pip \
|
||||
rsync \
|
||||
sudo \
|
||||
rpm \
|
||||
unzip \
|
||||
webp \
|
||||
xauth \
|
||||
xvfb \
|
||||
xz-utils \
|
||||
xdg-utils \
|
||||
zstd \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -fsSL "https://github.com/erlang/rebar3/releases/download/${REBAR3_VERSION}/rebar3" \
|
||||
-o /usr/local/bin/rebar3 \
|
||||
&& chmod +x /usr/local/bin/rebar3
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
apache2-utils \
|
||||
bat \
|
||||
btop \
|
||||
docker-cli \
|
||||
dnsutils \
|
||||
fd-find \
|
||||
gdb \
|
||||
htop \
|
||||
hyperfine \
|
||||
iproute2 \
|
||||
iputils-ping \
|
||||
kind \
|
||||
kubernetes-client \
|
||||
lldb \
|
||||
lsof \
|
||||
ltrace \
|
||||
net-tools \
|
||||
netcat-openbsd \
|
||||
nmap \
|
||||
postgresql-client \
|
||||
procps \
|
||||
redis-tools \
|
||||
ripgrep \
|
||||
shellcheck \
|
||||
shfmt \
|
||||
socat \
|
||||
sqlite3 \
|
||||
strace \
|
||||
tcpdump \
|
||||
tmux \
|
||||
tree \
|
||||
valgrind \
|
||||
wrk \
|
||||
yq \
|
||||
&& ln -sf /usr/bin/fdfind /usr/local/bin/fd \
|
||||
&& ln -sf /usr/bin/batcat /usr/local/bin/bat \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN curl -fsSL "https://caddyserver.com/api/download?os=linux&arch=amd64" \
|
||||
-o /usr/local/bin/caddy \
|
||||
&& chmod +x /usr/local/bin/caddy
|
||||
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& corepack enable \
|
||||
&& corepack prepare pnpm@10.29.3 --activate
|
||||
|
||||
RUN curl -fsSL "https://github.com/F1bonacc1/process-compose/releases/download/v${PROCESS_COMPOSE_VERSION}/process-compose_linux_amd64.tar.gz" \
|
||||
| tar xz -C /usr/local/bin process-compose \
|
||||
&& chmod +x /usr/local/bin/process-compose
|
||||
RUN ARCH="$(dpkg --print-architecture)" \
|
||||
&& case "$ARCH" in \
|
||||
amd64) HELM_ARCH="amd64" ;; \
|
||||
arm64) HELM_ARCH="arm64" ;; \
|
||||
*) echo "Unsupported architecture for Helm: $ARCH" >&2; exit 1 ;; \
|
||||
esac \
|
||||
&& curl -fsSL "https://get.helm.sh/helm-v${HELM_VERSION}-linux-${HELM_ARCH}.tar.gz" -o /tmp/helm.tgz \
|
||||
&& tar -C /tmp -xzf /tmp/helm.tgz "linux-${HELM_ARCH}/helm" \
|
||||
&& mv "/tmp/linux-${HELM_ARCH}/helm" /usr/local/bin/helm \
|
||||
&& chmod +x /usr/local/bin/helm \
|
||||
&& rm -rf /tmp/helm.tgz "/tmp/linux-${HELM_ARCH}"
|
||||
|
||||
RUN curl -fsSL "https://github.com/astral-sh/uv/releases/latest/download/uv-x86_64-unknown-linux-gnu.tar.gz" \
|
||||
| tar xz --strip-components=1 -C /usr/local/bin \
|
||||
&& chmod +x /usr/local/bin/uv /usr/local/bin/uvx
|
||||
RUN python3 -m pip install --break-system-packages --no-cache-dir awscli cqlsh
|
||||
|
||||
RUN if ! command -v rebar3 >/dev/null 2>&1; then \
|
||||
curl -fsSL https://s3.amazonaws.com/rebar3/rebar3 -o /usr/local/bin/rebar3 \
|
||||
&& chmod +x /usr/local/bin/rebar3; \
|
||||
fi
|
||||
|
||||
RUN ARCH="$(dpkg --print-architecture)" \
|
||||
&& case "$ARCH" in \
|
||||
amd64) ELP_ARCH="x86_64" ;; \
|
||||
arm64) ELP_ARCH="aarch64" ;; \
|
||||
*) echo "Unsupported architecture for ELP: $ARCH" >&2; exit 1 ;; \
|
||||
esac \
|
||||
&& curl -fsSL "https://github.com/WhatsApp/erlang-language-platform/releases/download/${ELP_VERSION}/elp-linux-${ELP_ARCH}-unknown-linux-gnu-otp-28.tar.gz" -o /tmp/elp.tgz \
|
||||
&& tar -C /usr/local/bin -xzf /tmp/elp.tgz elp \
|
||||
&& chmod +x /usr/local/bin/elp \
|
||||
&& rm /tmp/elp.tgz
|
||||
|
||||
RUN if ! getent group "${USER_GID}" >/dev/null; then groupadd --gid "${USER_GID}" "${USERNAME}"; fi \
|
||||
&& if ! id -u "${USERNAME}" >/dev/null 2>&1; then useradd --uid "${USER_UID}" --gid "${USER_GID}" -m "${USERNAME}" --shell /bin/bash; fi \
|
||||
&& echo "${USERNAME} ALL=(root) NOPASSWD:ALL" > "/etc/sudoers.d/${USERNAME}" \
|
||||
&& chmod 0440 "/etc/sudoers.d/${USERNAME}"
|
||||
|
||||
COPY --from=seaweedfs /usr/bin/weed /usr/local/bin/weed
|
||||
|
||||
USER ${USERNAME}
|
||||
|
||||
ENV DOCKER_HOST="unix:///var/run/docker.sock" \
|
||||
KUBECONFIG="/workspaces/fluxer/.fluxer/k8s/local-kubeconfig" \
|
||||
PATH="/home/${USERNAME}/.cargo/bin:${PATH}" \
|
||||
PNPM_HOME="/home/${USERNAME}/.local/share/pnpm"
|
||||
|
||||
RUN curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile default --component clippy,rustfmt \
|
||||
&& rustup target add wasm32-unknown-unknown \
|
||||
&& cargo install cargo-watch --locked
|
||||
|
||||
RUN sudo apt-get update \
|
||||
&& sudo apt-get install -y --no-install-recommends python3-venv \
|
||||
&& sudo rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /workspaces/fluxer
|
||||
|
||||
@@ -1,75 +1,73 @@
|
||||
{
|
||||
"name": "Fluxer",
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"service": "app",
|
||||
"workspaceFolder": "/workspace",
|
||||
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "24",
|
||||
"pnpmVersion": "10.29.3"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/go:1": {
|
||||
"version": "1.24"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/rust:1": {
|
||||
"version": "1.93.0",
|
||||
"targets": "wasm32-unknown-unknown"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"version": "os-provided",
|
||||
"installTools": false
|
||||
}
|
||||
},
|
||||
|
||||
"onCreateCommand": ".devcontainer/on-create.sh",
|
||||
|
||||
"service": "workspace",
|
||||
"workspaceFolder": "/workspaces/fluxer",
|
||||
"shutdownAction": "stopCompose",
|
||||
"remoteUser": "vscode",
|
||||
"remoteEnv": {
|
||||
"FLUXER_CONFIG": "${containerWorkspaceFolder}/config/config.json",
|
||||
"FLUXER_DATABASE": "sqlite"
|
||||
"DOCKER_HOST": "unix:///var/run/docker.sock",
|
||||
"KUBECONFIG": "/workspaces/fluxer/.fluxer/k8s/local-kubeconfig"
|
||||
},
|
||||
|
||||
"forwardPorts": [48763, 6379, 7700, 7880],
|
||||
|
||||
"runServices": ["workspace", "cassandra", "valkey", "nats", "livekit", "elasticsearch"],
|
||||
"forwardPorts": [
|
||||
3000, 8088, 8080, 8771, 8082, 3010, 3020, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111,
|
||||
8112, 8113, 8114, 8115, 8116, 8117, 8118, 8119, 8120, 8121, 8122, 8123, 8124, 8125, 3900, 8888, 9333, 9340, 23646,
|
||||
4222, 7880, 9200, 8000
|
||||
],
|
||||
"portsAttributes": {
|
||||
"48763": {
|
||||
"label": "Fluxer (Caddy)",
|
||||
"onAutoForward": "openBrowser",
|
||||
"protocol": "http"
|
||||
"8000": {
|
||||
"label": "Zensical docs",
|
||||
"onAutoForward": "openBrowserOnce"
|
||||
},
|
||||
"6379": {
|
||||
"label": "Valkey",
|
||||
"onAutoForward": "silent"
|
||||
"8088": {
|
||||
"label": "Fluxer dev proxy",
|
||||
"onAutoForward": "notify"
|
||||
},
|
||||
"7700": {
|
||||
"label": "Meilisearch",
|
||||
"onAutoForward": "silent"
|
||||
"3000": {
|
||||
"label": "Rspack dev server"
|
||||
},
|
||||
"3020": {
|
||||
"label": "Fluxer admin"
|
||||
},
|
||||
"8100": {
|
||||
"label": "Fluxer Rust service health"
|
||||
},
|
||||
"3900": {
|
||||
"label": "SeaweedFS S3"
|
||||
},
|
||||
"8888": {
|
||||
"label": "SeaweedFS filer"
|
||||
},
|
||||
"9333": {
|
||||
"label": "SeaweedFS master"
|
||||
},
|
||||
"9340": {
|
||||
"label": "SeaweedFS volume"
|
||||
},
|
||||
"23646": {
|
||||
"label": "SeaweedFS admin"
|
||||
},
|
||||
"7880": {
|
||||
"label": "LiveKit",
|
||||
"onAutoForward": "silent"
|
||||
"label": "LiveKit"
|
||||
},
|
||||
"9229": {
|
||||
"label": "Node.js Debugger",
|
||||
"onAutoForward": "silent"
|
||||
"9200": {
|
||||
"label": "Elasticsearch"
|
||||
}
|
||||
},
|
||||
|
||||
"postCreateCommand": "find /workspaces/fluxer -maxdepth 4 -type d -name node_modules -prune -exec sudo chown -R vscode:vscode {} + && sudo chown -R vscode:vscode /home/vscode/.local/share/pnpm && cargo run -p fluxer-dev -- bootstrap && bash /workspaces/fluxer/fluxer_docs/serve.sh --bootstrap",
|
||||
"postStartCommand": "cargo run -p fluxer-dev -- post-start && bash /workspaces/fluxer/fluxer_docs/serve.sh --daemon",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"TypeScriptTeam.native-preview",
|
||||
"biomejs.biome",
|
||||
"clinyong.vscode-css-modules",
|
||||
"rust-lang.rust-analyzer",
|
||||
"tamasfe.even-better-toml",
|
||||
"TypeScriptTeam.native-preview",
|
||||
"unifiedjs.vscode-mdx",
|
||||
"pgourlain.erlang",
|
||||
"golang.go",
|
||||
"rust-lang.rust-analyzer"
|
||||
],
|
||||
"settings": {
|
||||
"typescript.preferences.includePackageJsonAutoImports": "auto",
|
||||
"typescript.suggest.autoImports": true,
|
||||
"typescript.experimental.useTsgo": true
|
||||
}
|
||||
"clinyong.vscode-css-modules"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,394 @@
|
||||
name: fluxer-dev
|
||||
|
||||
services:
|
||||
app:
|
||||
workspace:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ..:/workspace:cached
|
||||
context: ..
|
||||
dockerfile: .devcontainer/Dockerfile
|
||||
command: sleep infinity
|
||||
init: true
|
||||
env_file:
|
||||
- ../config/env/development.env
|
||||
environment:
|
||||
FLUXER_SEARCH_URL: http://elasticsearch:9200
|
||||
FLUXER_SEARCH_USERNAME: elastic
|
||||
FLUXER_SEARCH_PASSWORD: fluxer-dev-elasticsearch
|
||||
FLUXER_POSTGRES_HOST: postgres
|
||||
FLUXER_SELF_HOSTED: "true"
|
||||
DOCKER_HOST: unix:///var/run/docker.sock
|
||||
KUBECONFIG: /workspaces/fluxer/.fluxer/k8s/local-kubeconfig
|
||||
volumes:
|
||||
- ..:/workspaces/fluxer:cached
|
||||
- type: volume
|
||||
source: root-node-modules
|
||||
target: /workspaces/fluxer/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-app-node-modules
|
||||
target: /workspaces/fluxer/fluxer_app/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-desktop-node-modules
|
||||
target: /workspaces/fluxer/fluxer_desktop/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-marketing-node-modules
|
||||
target: /workspaces/fluxer/fluxer_marketing/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-admin-node-modules
|
||||
target: /workspaces/fluxer/fluxer_admin/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-config-node-modules
|
||||
target: /workspaces/fluxer/packages/config/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-constants-node-modules
|
||||
target: /workspaces/fluxer/packages/constants/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-date-utils-node-modules
|
||||
target: /workspaces/fluxer/packages/date_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-errors-node-modules
|
||||
target: /workspaces/fluxer/packages/errors/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-geo-utils-node-modules
|
||||
target: /workspaces/fluxer/packages/geo_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-hono-node-modules
|
||||
target: /workspaces/fluxer/packages/hono/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-hono-types-node-modules
|
||||
target: /workspaces/fluxer/packages/hono_types/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-i18n-node-modules
|
||||
target: /workspaces/fluxer/packages/i18n/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-instance-bootstrap-node-modules
|
||||
target: /workspaces/fluxer/packages/instance_bootstrap/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-ip-utils-node-modules
|
||||
target: /workspaces/fluxer/packages/ip_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-limits-node-modules
|
||||
target: /workspaces/fluxer/packages/limits/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-logger-node-modules
|
||||
target: /workspaces/fluxer/packages/logger/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-openapi-node-modules
|
||||
target: /workspaces/fluxer/packages/openapi/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-schema-node-modules
|
||||
target: /workspaces/fluxer/packages/schema/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: package-snowflake-node-modules
|
||||
target: /workspaces/fluxer/packages/snowflake/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-cache-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/cache/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-captcha-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/captcha/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-cassandra-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/cassandra/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-elasticsearch-search-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/elasticsearch_search/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-email-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/email/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-geoip-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/geoip/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-http-client-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/http_client/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-initialization-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/initialization/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-kv-client-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/kv_client/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-locale-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/locale/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-media-proxy-utils-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/media_proxy_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-mime-utils-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/mime_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-nats-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/nats/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-rate-limit-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/rate_limit/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-sms-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/sms/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-virus-scan-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/virus_scan/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-api-worker-node-modules
|
||||
target: /workspaces/fluxer/fluxer_api/pkgs/worker/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-app-list-utils-node-modules
|
||||
target: /workspaces/fluxer/fluxer_app/pkgs/list_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-app-livekit-client-node-modules
|
||||
target: /workspaces/fluxer/fluxer_app/pkgs/livekit-client/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- type: volume
|
||||
source: fluxer-app-number-utils-node-modules
|
||||
target: /workspaces/fluxer/fluxer_app/pkgs/number_utils/node_modules
|
||||
volume:
|
||||
nocopy: true
|
||||
- pnpm-store:/home/vscode/.local/share/pnpm/store
|
||||
- cargo-registry:/home/vscode/.cargo/registry
|
||||
- cargo-git:/home/vscode/.cargo/git
|
||||
- rust-target:/workspaces/fluxer/target
|
||||
- type: bind
|
||||
source: ${FLUXER_DOCKER_SOCKET:-/var/run/docker.sock}
|
||||
target: /var/run/docker.sock
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "3000:3000"
|
||||
- "8088:8088"
|
||||
- "8080:8080"
|
||||
- "8771:8771"
|
||||
- "8082:8082"
|
||||
- "3010:3010"
|
||||
- "3020:3020"
|
||||
- "8100-8125:8100-8125"
|
||||
- "3900:8333"
|
||||
- "8888:8888"
|
||||
- "9333:9333"
|
||||
- "9340:9340"
|
||||
- "23646:23646"
|
||||
depends_on:
|
||||
- cassandra
|
||||
- postgres
|
||||
- valkey
|
||||
- nats
|
||||
- livekit
|
||||
- elasticsearch
|
||||
- mailpit
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
cassandra:
|
||||
image: cassandra:5.0.8
|
||||
environment:
|
||||
CASSANDRA_CLUSTER_NAME: fluxer-dev
|
||||
CASSANDRA_DC: datacenter1
|
||||
CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch
|
||||
HEAP_NEWSIZE: 128M
|
||||
MAX_HEAP_SIZE: 768M
|
||||
volumes:
|
||||
- cassandra-data:/var/lib/cassandra
|
||||
ports:
|
||||
- "9042:9042"
|
||||
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_DB: fluxer
|
||||
POSTGRES_USER: fluxer
|
||||
POSTGRES_PASSWORD: fluxer
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
valkey:
|
||||
image: valkey/valkey:8-alpine
|
||||
restart: unless-stopped
|
||||
command: ['valkey-server', '--appendonly', 'yes', '--save', '60', '1', '--loglevel', 'warning']
|
||||
volumes:
|
||||
- valkey-data:/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'valkey-cli', 'ping']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
image: valkey/valkey:8.1.7-alpine
|
||||
command: ["valkey-server", "--save", "", "--appendonly", "no"]
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.14
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MEILI_NO_ANALYTICS: 'true'
|
||||
MEILI_ENV: development
|
||||
MEILI_MASTER_KEY: fluxer-devcontainer-meili-master-key
|
||||
nats:
|
||||
image: nats:2.14.2-alpine
|
||||
command: ["-js", "-sd", "/data", "-m", "8222"]
|
||||
volumes:
|
||||
- meilisearch-data:/meili_data
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:7700/health']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
- nats-data:/data
|
||||
ports:
|
||||
- "4222:4222"
|
||||
- "8222:8222"
|
||||
|
||||
livekit:
|
||||
image: livekit/livekit-server:v1.9
|
||||
restart: unless-stopped
|
||||
command: --config /etc/livekit.yaml
|
||||
image: livekit/livekit-server:v1.12.0
|
||||
command: ["--config", "/etc/livekit.yaml", "--bind", "0.0.0.0"]
|
||||
volumes:
|
||||
- ./livekit.yaml:/etc/livekit.yaml:ro
|
||||
ports:
|
||||
- "7880:7880"
|
||||
- "7881:7881"
|
||||
- "7882-7892:7882-7892/udp"
|
||||
|
||||
elasticsearch:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:9.3.2
|
||||
environment:
|
||||
discovery.type: single-node
|
||||
xpack.security.enabled: "true"
|
||||
xpack.security.http.ssl.enabled: "false"
|
||||
ELASTIC_PASSWORD: fluxer-dev-elasticsearch
|
||||
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||
volumes:
|
||||
- elasticsearch-data:/usr/share/elasticsearch/data
|
||||
ports:
|
||||
- "9200:9200"
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.12
|
||||
environment:
|
||||
MEILI_NO_ANALYTICS: "true"
|
||||
MEILI_MASTER_KEY: fluxer-dev-meilisearch
|
||||
volumes:
|
||||
- meilisearch-data:/meili_data
|
||||
ports:
|
||||
- "7700:7700"
|
||||
|
||||
mailpit:
|
||||
image: axllent/mailpit:latest
|
||||
restart: unless-stopped
|
||||
command: ['--webroot', '/mailpit/']
|
||||
|
||||
nats-core:
|
||||
image: nats:2-alpine
|
||||
restart: unless-stopped
|
||||
command: ['--port', '4222']
|
||||
|
||||
nats-jetstream:
|
||||
image: nats:2-alpine
|
||||
restart: unless-stopped
|
||||
command: ['--port', '4223', '--jetstream', '--store_dir', '/data']
|
||||
image: axllent/mailpit:v1.30
|
||||
environment:
|
||||
MP_DATABASE: /data/mailpit.db
|
||||
MP_MAX_MESSAGES: 5000
|
||||
MP_SMTP_AUTH_ACCEPT_ANY: "1"
|
||||
MP_SMTP_AUTH_ALLOW_INSECURE: "1"
|
||||
MP_WEBROOT: devmail
|
||||
volumes:
|
||||
- nats-jetstream-data:/data
|
||||
- mailpit-data:/data
|
||||
|
||||
volumes:
|
||||
valkey-data:
|
||||
pnpm-store:
|
||||
root-node-modules:
|
||||
fluxer-api-node-modules:
|
||||
fluxer-app-node-modules:
|
||||
fluxer-desktop-node-modules:
|
||||
fluxer-marketing-node-modules:
|
||||
fluxer-admin-node-modules:
|
||||
package-config-node-modules:
|
||||
package-constants-node-modules:
|
||||
package-date-utils-node-modules:
|
||||
package-errors-node-modules:
|
||||
package-geo-utils-node-modules:
|
||||
package-hono-node-modules:
|
||||
package-hono-types-node-modules:
|
||||
package-i18n-node-modules:
|
||||
package-instance-bootstrap-node-modules:
|
||||
package-ip-utils-node-modules:
|
||||
package-limits-node-modules:
|
||||
package-logger-node-modules:
|
||||
package-openapi-node-modules:
|
||||
package-schema-node-modules:
|
||||
package-snowflake-node-modules:
|
||||
fluxer-api-cache-node-modules:
|
||||
fluxer-api-captcha-node-modules:
|
||||
fluxer-api-cassandra-node-modules:
|
||||
fluxer-api-elasticsearch-search-node-modules:
|
||||
fluxer-api-email-node-modules:
|
||||
fluxer-api-geoip-node-modules:
|
||||
fluxer-api-http-client-node-modules:
|
||||
fluxer-api-initialization-node-modules:
|
||||
fluxer-api-kv-client-node-modules:
|
||||
fluxer-api-locale-node-modules:
|
||||
fluxer-api-media-proxy-utils-node-modules:
|
||||
fluxer-api-mime-utils-node-modules:
|
||||
fluxer-api-nats-node-modules:
|
||||
fluxer-api-rate-limit-node-modules:
|
||||
fluxer-api-sms-node-modules:
|
||||
fluxer-api-virus-scan-node-modules:
|
||||
fluxer-api-worker-node-modules:
|
||||
fluxer-app-list-utils-node-modules:
|
||||
fluxer-app-livekit-client-node-modules:
|
||||
fluxer-app-number-utils-node-modules:
|
||||
cargo-registry:
|
||||
cargo-git:
|
||||
rust-target:
|
||||
cassandra-data:
|
||||
nats-data:
|
||||
elasticsearch-data:
|
||||
meilisearch-data:
|
||||
nats-jetstream-data:
|
||||
mailpit-data:
|
||||
postgres-data:
|
||||
|
||||
@@ -1,30 +1,13 @@
|
||||
# Credentials here must match the values on-create.sh writes to config.json.
|
||||
|
||||
port: 7880
|
||||
|
||||
keys:
|
||||
fluxer-devcontainer-key: fluxer-devcontainer-secret-key-00000000
|
||||
devkey: secret
|
||||
|
||||
rtc:
|
||||
tcp_port: 7881
|
||||
port_range_start: 50000
|
||||
port_range_end: 50100
|
||||
use_external_ip: false
|
||||
udp_port: 7882-7892
|
||||
node_ip: 127.0.0.1
|
||||
|
||||
turn:
|
||||
enabled: true
|
||||
domain: localhost
|
||||
udp_port: 3478
|
||||
|
||||
webhook:
|
||||
api_key: fluxer-devcontainer-key
|
||||
urls:
|
||||
- http://app:49319/api/webhooks/livekit
|
||||
|
||||
room:
|
||||
auto_create: true
|
||||
max_participants: 100
|
||||
empty_timeout: 300
|
||||
|
||||
development: true
|
||||
use_mdns: true
|
||||
stun_servers:
|
||||
- stun.l.google.com:19302
|
||||
- stun1.l.google.com:19302
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Runs once when the container is first created.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
export FLUXER_CONFIG="${FLUXER_CONFIG:-$REPO_ROOT/config/config.json}"
|
||||
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m'
|
||||
info() { printf "%b\n" "${GREEN}[devcontainer]${NC} $1"; }
|
||||
|
||||
info "Installing pnpm dependencies..."
|
||||
pnpm install
|
||||
|
||||
# Codegen outputs (e.g. MasterZodSchema.generated.tsx) are gitignored.
|
||||
info "Generating config schema..."
|
||||
pnpm --filter @fluxer/config generate
|
||||
|
||||
if [ ! -f "$FLUXER_CONFIG" ]; then
|
||||
info "Creating config from development template..."
|
||||
cp "$REPO_ROOT/config/config.dev.template.json" "$FLUXER_CONFIG"
|
||||
fi
|
||||
|
||||
# Point services at Docker Compose hostnames and adjust settings that differ
|
||||
# from the default dev template.
|
||||
info "Patching config for Docker Compose networking..."
|
||||
jq '
|
||||
# rspack defaults public_scheme to "https" when unset
|
||||
.domain.public_scheme = "http" |
|
||||
# Relative path so the app works on any hostname (localhost, 127.0.0.1, etc.)
|
||||
.app_public.bootstrap_api_endpoint = "/api" |
|
||||
|
||||
.internal.kv = "redis://valkey:6379/0" |
|
||||
|
||||
.integrations.search.url = "http://meilisearch:7700" |
|
||||
.integrations.search.api_key = "fluxer-devcontainer-meili-master-key" |
|
||||
|
||||
# Credentials must match .devcontainer/livekit.yaml
|
||||
.integrations.voice.url = "ws://livekit:7880" |
|
||||
.integrations.voice.webhook_url = "http://app:49319/api/webhooks/livekit" |
|
||||
.integrations.voice.api_key = "fluxer-devcontainer-key" |
|
||||
.integrations.voice.api_secret = "fluxer-devcontainer-secret-key-00000000" |
|
||||
|
||||
.integrations.email.smtp.host = "mailpit" |
|
||||
.integrations.email.smtp.port = 1025 |
|
||||
|
||||
.services.nats.core_url = "nats://nats-core:4222" |
|
||||
.services.nats.jetstream_url = "nats://nats-jetstream:4223" |
|
||||
|
||||
# Bluesky OAuth requires HTTPS + loopback IPs (RFC 8252), incompatible with
|
||||
# the HTTP-only devcontainer setup.
|
||||
.auth.bluesky.enabled = false
|
||||
' "$FLUXER_CONFIG" > "$FLUXER_CONFIG.tmp" && mv "$FLUXER_CONFIG.tmp" "$FLUXER_CONFIG"
|
||||
|
||||
info "Running bootstrap..."
|
||||
"$REPO_ROOT/scripts/dev_bootstrap.sh"
|
||||
|
||||
info "Pre-compiling Erlang gateway dependencies..."
|
||||
(cd "$REPO_ROOT/fluxer_gateway" && rebar3 compile) || {
|
||||
info "Gateway pre-compilation failed (non-fatal, will compile on first start)"
|
||||
}
|
||||
|
||||
info "Devcontainer setup complete."
|
||||
info ""
|
||||
info " Start all dev processes: process-compose -f .devcontainer/process-compose.yml up"
|
||||
info " Open the app: http://127.0.0.1:48763"
|
||||
info " Dev email inbox: http://127.0.0.1:48763/mailpit/"
|
||||
info ""
|
||||
@@ -1,57 +0,0 @@
|
||||
# Application processes only — backing services (Valkey, Meilisearch, LiveKit,
|
||||
# Mailpit, NATS) run via Docker Compose.
|
||||
# process-compose -f .devcontainer/process-compose.yml up
|
||||
|
||||
is_tui_disabled: false
|
||||
log_level: info
|
||||
log_configuration:
|
||||
flush_each_line: true
|
||||
|
||||
processes:
|
||||
caddy:
|
||||
command: caddy run --config .devcontainer/Caddyfile.dev --adapter caddyfile
|
||||
log_location: dev/logs/caddy.log
|
||||
readiness_probe:
|
||||
http_get:
|
||||
host: 127.0.0.1
|
||||
port: 48763
|
||||
path: /_caddy_health
|
||||
availability:
|
||||
restart: always
|
||||
|
||||
fluxer_server:
|
||||
command: pnpm --filter fluxer_server dev
|
||||
log_location: dev/logs/fluxer_server.log
|
||||
availability:
|
||||
restart: always
|
||||
|
||||
fluxer_app:
|
||||
command: ./scripts/dev_fluxer_app.sh
|
||||
environment:
|
||||
- FORCE_COLOR=1
|
||||
- FLUXER_APP_DEV_PORT=49427
|
||||
log_location: dev/logs/fluxer_app.log
|
||||
availability:
|
||||
restart: always
|
||||
|
||||
fluxer_gateway:
|
||||
command: ./scripts/dev_gateway.sh
|
||||
environment:
|
||||
- FLUXER_GATEWAY_NO_SHELL=1
|
||||
log_location: dev/logs/fluxer_gateway.log
|
||||
availability:
|
||||
restart: always
|
||||
|
||||
marketing_dev:
|
||||
command: pnpm --filter fluxer_marketing dev
|
||||
environment:
|
||||
- FORCE_COLOR=1
|
||||
log_location: dev/logs/marketing_dev.log
|
||||
availability:
|
||||
restart: always
|
||||
|
||||
css_watch:
|
||||
command: ./scripts/dev_css_watch.sh
|
||||
log_location: dev/logs/css_watch.log
|
||||
availability:
|
||||
restart: always
|
||||
+60
-4
@@ -1,45 +1,101 @@
|
||||
**/*.dump
|
||||
**/*.lock
|
||||
!**/Cargo.lock
|
||||
!fluxer_gateway/rebar.lock
|
||||
**/*.log
|
||||
**/*.swo
|
||||
**/*.swp
|
||||
**/*.tmp
|
||||
**/*~
|
||||
/.claude
|
||||
/.claude/**
|
||||
/.fluxer
|
||||
/.fluxer/**
|
||||
/.git
|
||||
/.git/**
|
||||
/.pnpm-store
|
||||
/.pnpm-store/**
|
||||
/.tmp
|
||||
/.tmp/**
|
||||
/_build
|
||||
/_build/**
|
||||
/node_modules
|
||||
/node_modules/**
|
||||
/target
|
||||
/target/**
|
||||
/tmp
|
||||
/tmp/**
|
||||
/fluxer_admin/node_modules
|
||||
/fluxer_admin/node_modules/**
|
||||
/fluxer_api/node_modules
|
||||
/fluxer_api/node_modules/**
|
||||
/fluxer_app/dist
|
||||
/fluxer_app/dist/**
|
||||
/fluxer_app/node_modules
|
||||
/fluxer_app/node_modules/**
|
||||
/fluxer_desktop
|
||||
/fluxer_desktop/**
|
||||
/fluxer_gateway/_build
|
||||
/fluxer_gateway/_build/**
|
||||
/fluxer_marketing/node_modules
|
||||
/fluxer_marketing/node_modules/**
|
||||
/fluxer_marketing/target
|
||||
/fluxer_marketing/target/**
|
||||
**/.cache
|
||||
**/.claude
|
||||
**/.dev.vars
|
||||
**/.DS_Store
|
||||
**/.env
|
||||
**/.env.*.local
|
||||
**/.env.local
|
||||
**/.fluxer
|
||||
.fluxer
|
||||
.claude
|
||||
.tmp
|
||||
**/.git
|
||||
.git
|
||||
**/.idea
|
||||
**/.pnpm-store
|
||||
**/.rebar
|
||||
**/.rebar3
|
||||
**/.turbo
|
||||
**/.vscode
|
||||
**/.benchmark-cache
|
||||
**/.zig-cache
|
||||
**/_build
|
||||
_build
|
||||
**/_checkouts
|
||||
**/_vendor
|
||||
**/bench-results
|
||||
**/build
|
||||
!fluxer_app/scripts/build
|
||||
!fluxer_app/scripts/build/**
|
||||
**/certificates
|
||||
**/coverage
|
||||
**/dist
|
||||
**/Dockerfile*
|
||||
**/erl_crash.dump
|
||||
**/generated
|
||||
**/log
|
||||
**/logs
|
||||
**/node_modules
|
||||
node_modules
|
||||
**/npm-debug.log*
|
||||
**/pnpm-debug.log*
|
||||
**/rebar3.crashdump
|
||||
**/target
|
||||
**/target-*
|
||||
target
|
||||
target-*
|
||||
tmp
|
||||
**/Thumbs.db
|
||||
**/yarn-debug.log*
|
||||
**/yarn-error.log*
|
||||
/fluxer_app/src/data/emojis.json
|
||||
**/zig-out
|
||||
/fluxer_app/src/locales/*/messages.js
|
||||
/fluxer_app/src/locales/*/messages.mjs
|
||||
dev
|
||||
!fluxer_app/dist
|
||||
!fluxer_app/dist/**
|
||||
.github
|
||||
.next
|
||||
*.md
|
||||
fluxer_desktop
|
||||
!fluxer_devops/cassandra/migrations
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
eval "$(devenv direnvrc)"
|
||||
use devenv
|
||||
dotenv config/env/development.env
|
||||
dotenv_if_exists config/env/local.env
|
||||
dotenv_if_exists .env.local
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
* text=auto
|
||||
fluxer_static/** -text -diff
|
||||
|
||||
@@ -2,32 +2,27 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for the suggestion.
|
||||
|
||||
For larger changes, please align with maintainers before investing time.
|
||||
Security issues should go to https://fluxer.app/security.
|
||||
Search existing discussions before posting.
|
||||
Report security issues at https://fluxer.app/security.
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Problem
|
||||
description: What problem are you trying to solve, and for whom?
|
||||
placeholder: "Right now, users can't ..., which causes ..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: proposal
|
||||
attributes:
|
||||
label: Proposed solution
|
||||
description: What would you like to see happen?
|
||||
placeholder: "Add ..., so that ..."
|
||||
label: Proposal
|
||||
description: What should change?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: notes
|
||||
attributes:
|
||||
label: Notes (optional)
|
||||
description: Constraints, rough plan, or links to relevant code.
|
||||
placeholder: "Notes: ...\nPotential files/areas: ..."
|
||||
label: Notes
|
||||
description: Add constraints, tradeoffs, screenshots, or links.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
@@ -35,5 +30,5 @@ body:
|
||||
attributes:
|
||||
label: Checks
|
||||
options:
|
||||
- label: I searched for existing discussions and didn't find a duplicate.
|
||||
- label: I searched existing discussions.
|
||||
required: true
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
name: Bug report
|
||||
description: Report a reproducible problem in Fluxer
|
||||
labels: ['bug']
|
||||
description: Report a reproducible problem in Fluxer.
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for the report.
|
||||
|
||||
Please check our status page at https://fluxerstatus.com and search for existing issues before filing.
|
||||
Security issues should go to https://fluxer.app/security.
|
||||
Search existing issues before filing.
|
||||
Report security issues at https://fluxer.app/security.
|
||||
Keep AI-generated text out of bug reports, except for direct translation if English is not your native language.
|
||||
- type: textarea
|
||||
id: summary
|
||||
attributes:
|
||||
label: Summary
|
||||
description: What happened, and what did you expect instead?
|
||||
placeholder: "When I ..., the app ..., but I expected ..."
|
||||
placeholder: When I ..., the app ..., but I expected ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: repro
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Provide clear, numbered steps.
|
||||
description: Use numbered steps.
|
||||
placeholder: |
|
||||
1. Go to ...
|
||||
2. Click ...
|
||||
@@ -31,21 +30,20 @@ body:
|
||||
- type: textarea
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment (optional)
|
||||
description: Include versions that matter (commit/tag, OS, runtime, browser/device).
|
||||
label: Environment
|
||||
description: Add versions, OS, browser, device, or commit when relevant.
|
||||
placeholder: |
|
||||
- Commit/Tag:
|
||||
- OS:
|
||||
- Runtime:
|
||||
- Browser (if applicable):
|
||||
Version:
|
||||
OS:
|
||||
Browser:
|
||||
Device:
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: logs
|
||||
id: evidence
|
||||
attributes:
|
||||
label: Logs or screenshots (optional)
|
||||
description: Paste logs (redact secrets) or attach screenshots/recordings.
|
||||
placeholder: "Paste stack traces, console output, network errors, etc."
|
||||
label: Logs or screenshots
|
||||
description: Add logs, screenshots, recordings, or links. Redact secrets.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
@@ -53,5 +51,7 @@ body:
|
||||
attributes:
|
||||
label: Checks
|
||||
options:
|
||||
- label: I searched for existing issues and didn't find a duplicate.
|
||||
- label: I searched existing issues.
|
||||
required: true
|
||||
- label: I wrote this report in my own words, except for direct translation if needed.
|
||||
required: true
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Feature requests
|
||||
- name: Ideas and feature requests
|
||||
url: https://github.com/orgs/fluxerapp/discussions
|
||||
about: Suggest an improvement or new capability.
|
||||
- name: Security vulnerability report
|
||||
- name: Security reports
|
||||
url: https://fluxer.app/security
|
||||
about: Please report security issues privately using our security policy.
|
||||
about: Report vulnerabilities privately.
|
||||
|
||||
@@ -1,36 +1,33 @@
|
||||
name: Documentation
|
||||
description: Report a docs issue or suggest an improvement
|
||||
labels: ['docs']
|
||||
description: Report a docs issue or suggest a docs improvement.
|
||||
labels: ["docs"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks.
|
||||
|
||||
Please check our status page at https://fluxerstatus.com and search for existing issues before filing.
|
||||
Security issues should go to https://fluxer.app/security.
|
||||
Search existing issues before filing.
|
||||
Report security issues at https://fluxer.app/security.
|
||||
Keep AI-generated text out of bug reports, except for direct translation if English is not your native language.
|
||||
- type: textarea
|
||||
id: issue
|
||||
attributes:
|
||||
label: What needs fixing?
|
||||
description: Describe the gap, error, or outdated content.
|
||||
placeholder: "The README says ..., but actually ..."
|
||||
description: Describe the missing, incorrect, or unclear documentation.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
- type: input
|
||||
id: location
|
||||
attributes:
|
||||
label: Where is it? (optional)
|
||||
description: Link the file/section if possible.
|
||||
placeholder: "File: ...\nSection/heading: ...\nLink: ..."
|
||||
label: Location
|
||||
description: Link the page, file, or heading if you can.
|
||||
placeholder: https://...
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: suggestion
|
||||
attributes:
|
||||
label: Suggested wording (optional)
|
||||
description: If you already know how it should read, propose text.
|
||||
placeholder: "Proposed text: ..."
|
||||
label: Suggested change
|
||||
description: Add proposed wording or a short outline if useful.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
@@ -38,5 +35,7 @@ body:
|
||||
attributes:
|
||||
label: Checks
|
||||
options:
|
||||
- label: I searched for existing issues and didn't find a duplicate.
|
||||
- label: I searched existing issues.
|
||||
required: true
|
||||
- label: I wrote this report in my own words, except for direct translation if needed.
|
||||
required: true
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
self-hosted-runner:
|
||||
labels:
|
||||
- blacksmith-4vcpu-ubuntu-2404
|
||||
- blacksmith-4vcpu-ubuntu-2404-arm
|
||||
- blacksmith-32vcpu-ubuntu-2404
|
||||
- blacksmith-32vcpu-ubuntu-2404-arm
|
||||
- blacksmith-32vcpu-windows-2025
|
||||
- fluxer-desktop-macos-arm64
|
||||
|
||||
config-variables: null
|
||||
@@ -1,32 +1,21 @@
|
||||
## Summary
|
||||
|
||||
<!-- A few bullets is perfect: what changed, why it changed, and anything reviewers should pay attention to. -->
|
||||
- What changed:
|
||||
- Why it is correct:
|
||||
- Risk:
|
||||
|
||||
- **What:**
|
||||
- **Why:**
|
||||
- **Notes for reviewers:**
|
||||
## Verification
|
||||
|
||||
## How to verify
|
||||
|
||||
<!-- Concrete steps to validate the change. Include screenshots/recordings for UI changes when helpful. -->
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## Tests
|
||||
|
||||
<!-- List what you ran, or explain why tests weren't added/changed. -->
|
||||
|
||||
- [ ] Added/updated unit tests (where it makes sense)
|
||||
- [ ] Manual verification:
|
||||
- Tests run:
|
||||
- Manual checks:
|
||||
- Screenshots or recordings:
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] PR targets `canary`
|
||||
- [ ] PR title follows Conventional Commits (mostly lowercase)
|
||||
- [ ] CI is green (or I'm actively addressing failures)
|
||||
- [ ] I understand every change in this PR.
|
||||
- [ ] I can explain what it does and why it is correct.
|
||||
- [ ] I disclosed any LLM coding help below.
|
||||
|
||||
## Screenshots / recordings (UI changes)
|
||||
## LLM Disclosure
|
||||
|
||||
<!-- Drag and drop images/videos here. -->
|
||||
- None, or:
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build image (reusable)
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image:
|
||||
description: "Image name under ghcr.io/<owner>/ (for example fluxer-api)"
|
||||
type: string
|
||||
required: true
|
||||
dockerfile:
|
||||
description: "Path to the Dockerfile to build"
|
||||
type: string
|
||||
required: true
|
||||
context:
|
||||
description: "Docker build context"
|
||||
type: string
|
||||
required: false
|
||||
default: "."
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
moving-tags:
|
||||
description: "Comma-separated moving tags to repoint at this build"
|
||||
type: string
|
||||
required: false
|
||||
default: "v1,latest"
|
||||
extra-build-args:
|
||||
description: "Additional Docker build args, one KEY=VALUE entry per line"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_OWNER: ${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: resolve metadata
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
build_version: ${{ steps.vars.outputs.build_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
- name: set variables
|
||||
id: vars
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FLUXER_BUILD_VERSION: ${{ inputs.build-version }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- resolve-calver
|
||||
--github-output
|
||||
|
||||
build:
|
||||
name: build ${{ matrix.platform }}
|
||||
needs: meta
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 75
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: amd64
|
||||
runner: blacksmith-4vcpu-ubuntu-2404
|
||||
- platform: arm64
|
||||
runner: blacksmith-4vcpu-ubuntu-2404-arm
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
|
||||
with:
|
||||
context: ${{ inputs.context }}
|
||||
file: ${{ inputs.dockerfile }}
|
||||
push: true
|
||||
provenance: false
|
||||
platforms: linux/${{ matrix.platform }}
|
||||
tags: ghcr.io/${{ env.GHCR_OWNER }}/${{ inputs.image }}:${{ needs.meta.outputs.build_version }}-${{ matrix.platform }}
|
||||
build-args: |
|
||||
BUILD_VERSION=${{ needs.meta.outputs.build_version }}
|
||||
${{ inputs.extra-build-args }}
|
||||
cache-from: type=gha,scope=${{ inputs.image }}-${{ matrix.platform }}
|
||||
cache-to: type=gha,scope=${{ inputs.image }}-${{ matrix.platform }},mode=max,ignore-error=true
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
merge:
|
||||
name: merge multi-arch manifest
|
||||
needs: [meta, build]
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: create and push multi-arch manifest
|
||||
env:
|
||||
IMAGE: ghcr.io/${{ env.GHCR_OWNER }}/${{ inputs.image }}
|
||||
VERSION: ${{ needs.meta.outputs.build_version }}
|
||||
MOVING_TAGS: ${{ inputs.moving-tags }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tag_args=( "-t" "${IMAGE}:${VERSION}" )
|
||||
IFS=',' read -ra moving <<< "${MOVING_TAGS}"
|
||||
for raw in "${moving[@]}"; do
|
||||
t="$(echo "$raw" | xargs)"
|
||||
[ -n "$t" ] && tag_args+=( "-t" "${IMAGE}:${t}" )
|
||||
done
|
||||
docker buildx imagetools create "${tag_args[@]}" \
|
||||
"${IMAGE}:${VERSION}-amd64" \
|
||||
"${IMAGE}:${VERSION}-arm64"
|
||||
docker buildx imagetools inspect "${IMAGE}:${VERSION}"
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build admin
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-admin
|
||||
dockerfile: fluxer_admin/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build api
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-api
|
||||
dockerfile: fluxer_api/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,33 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build app-proxy self-hosted
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-app-proxy-self-hosted
|
||||
dockerfile: fluxer_app_proxy/Dockerfile
|
||||
build-version: ${{ inputs['build-version'] }}
|
||||
extra-build-args: |
|
||||
FLUXER_APP_PROXY_TIME_FREEZE_ENABLED=false
|
||||
@@ -0,0 +1,162 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build app-proxy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_OWNER: ${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: resolve metadata
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
build_version: ${{ steps.vars.outputs.build_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
- name: set variables
|
||||
id: vars
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
|
||||
--step set_metadata
|
||||
--build-version "${{ inputs['build-version'] }}"
|
||||
|
||||
build:
|
||||
name: build app-proxy (amd64)
|
||||
needs: meta
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
- name: prepare docker config
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
|
||||
--step prepare_docker_config
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
- name: configure ghcr auth
|
||||
env:
|
||||
GHCR_USERNAME: ${{ github.actor }}
|
||||
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
|
||||
--step configure_ghcr_auth
|
||||
|
||||
- name: build and push image + extract assets
|
||||
env:
|
||||
BUILD_VERSION: ${{ needs.meta.outputs.build_version }}
|
||||
PUBLIC_ASSET_BASE_URL: https://fluxerstatic.com
|
||||
CACHE_FROM: type=gha,scope=fluxer-app-proxy
|
||||
CACHE_TO: type=gha,scope=fluxer-app-proxy,mode=max
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
|
||||
--step build_and_extract
|
||||
|
||||
- name: generate asset manifest
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
|
||||
--step generate_asset_manifest
|
||||
|
||||
- name: upload assets to S3 static bucket
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
S3_ENDPOINT: https://ewr1.vultrobjects.com
|
||||
STATIC_BUCKET: fluxer-static
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
|
||||
--step upload_assets
|
||||
|
||||
build-arm64:
|
||||
name: build app-proxy (arm64)
|
||||
needs: meta
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404-arm
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_app_proxy/Dockerfile
|
||||
push: true
|
||||
provenance: false
|
||||
platforms: linux/arm64
|
||||
tags: ghcr.io/${{ env.GHCR_OWNER }}/fluxer-app-proxy:${{ needs.meta.outputs.build_version }}-arm64
|
||||
build-args: |
|
||||
BUILD_VERSION=${{ needs.meta.outputs.build_version }}
|
||||
PUBLIC_ASSET_BASE_URL=https://fluxerstatic.com
|
||||
cache-from: type=gha,scope=fluxer-app-proxy-arm64
|
||||
cache-to: type=gha,scope=fluxer-app-proxy-arm64,mode=max,ignore-error=true
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
merge:
|
||||
name: merge multi-arch manifest
|
||||
needs: [meta, build, build-arm64]
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: fuse amd64 + arm64 into a multi-arch manifest
|
||||
env:
|
||||
IMAGE: ghcr.io/${{ env.GHCR_OWNER }}/fluxer-app-proxy
|
||||
VERSION: ${{ needs.meta.outputs.build_version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
amd64_digest="$(docker buildx imagetools inspect "${IMAGE}:${VERSION}" --format '{{json .Manifest}}' | jq -r '.digest')"
|
||||
echo "amd64 digest: ${amd64_digest}"
|
||||
docker buildx imagetools create \
|
||||
-t "${IMAGE}:${VERSION}" \
|
||||
-t "${IMAGE}:v1" \
|
||||
-t "${IMAGE}:latest" \
|
||||
"${IMAGE}@${amd64_digest}" \
|
||||
"${IMAGE}:${VERSION}-arm64"
|
||||
docker buildx imagetools inspect "${IMAGE}:${VERSION}"
|
||||
@@ -4,202 +4,227 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: Channel to build (stable or canary)
|
||||
description: Release channel label (stable or canary). Source is always this repository's main branch.
|
||||
required: false
|
||||
type: choice
|
||||
options:
|
||||
- stable
|
||||
- canary
|
||||
default: stable
|
||||
ref:
|
||||
description: Git ref to build (branch, tag, or commit SHA)
|
||||
test_build:
|
||||
description: Stash artifacts under desktop-test/ instead of desktop/ (API will not pick these up as a release).
|
||||
required: false
|
||||
default: ''
|
||||
default: false
|
||||
type: boolean
|
||||
build_version:
|
||||
description: Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation.
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
skip_windows:
|
||||
description: Skip Windows builds
|
||||
skip_targets:
|
||||
description: Comma-separated platforms or targets to skip, such as windows, macos-arm64, linux-x64.
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_macos:
|
||||
description: Skip macOS builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_linux:
|
||||
description: Skip Linux builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_windows_x64:
|
||||
description: Skip Windows x64 builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_windows_arm64:
|
||||
description: Skip Windows ARM64 builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_macos_x64:
|
||||
description: Skip macOS x64 builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_macos_arm64:
|
||||
description: Skip macOS ARM64 builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_linux_x64:
|
||||
description: Skip Linux x64 builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
skip_linux_arm64:
|
||||
description: Skip Linux ARM64 builds
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
default: ""
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
actions: read
|
||||
|
||||
concurrency:
|
||||
group: desktop-${{ inputs.channel }}
|
||||
group: desktop-${{ inputs.channel }}-${{ inputs.test_build && 'test' || 'release' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
CHANNEL: ${{ inputs.channel }}
|
||||
BUILD_CHANNEL: ${{ inputs.channel == 'canary' && 'canary' || 'stable' }}
|
||||
TEST_BUILD: ${{ inputs.test_build && 'true' || 'false' }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: Resolve build metadata
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 25
|
||||
outputs:
|
||||
version: ${{ steps.meta.outputs.version }}
|
||||
pub_date: ${{ steps.meta.outputs.pub_date }}
|
||||
channel: ${{ steps.meta.outputs.channel }}
|
||||
build_channel: ${{ steps.meta.outputs.build_channel }}
|
||||
test_build: ${{ steps.meta.outputs.test_build }}
|
||||
s3_prefix: ${{ steps.meta.outputs.s3_prefix }}
|
||||
source_sha: ${{ steps.meta.outputs.source_sha }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
ref: main
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Set metadata
|
||||
id: meta
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FLUXER_BUILD_VERSION: ${{ inputs.build_version }}
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step set_metadata
|
||||
--channel "${{ inputs.channel }}"
|
||||
--ref "${{ inputs.ref }}"
|
||||
--test-build "${{ inputs.test_build }}"
|
||||
|
||||
matrix:
|
||||
name: Resolve build matrix
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 25
|
||||
outputs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
windows_x64: ${{ steps.set-matrix.outputs.windows_x64 }}
|
||||
windows_arm64: ${{ steps.set-matrix.outputs.windows_arm64 }}
|
||||
windows_x64_default: ${{ steps.set-matrix.outputs.windows_x64_default }}
|
||||
windows_arm64_default: ${{ steps.set-matrix.outputs.windows_arm64_default }}
|
||||
windows_game_capture_x64: ${{ steps.set-matrix.outputs.windows_game_capture_x64 }}
|
||||
windows_game_capture_arm64: ${{ steps.set-matrix.outputs.windows_game_capture_arm64 }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Build platform matrix
|
||||
id: set-matrix
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step set_matrix
|
||||
--skip-windows "${{ inputs.skip_windows }}"
|
||||
--skip-windows-x64 "${{ inputs.skip_windows_x64 }}"
|
||||
--skip-windows-arm64 "${{ inputs.skip_windows_arm64 }}"
|
||||
--skip-macos "${{ inputs.skip_macos }}"
|
||||
--skip-macos-x64 "${{ inputs.skip_macos_x64 }}"
|
||||
--skip-macos-arm64 "${{ inputs.skip_macos_arm64 }}"
|
||||
--skip-linux "${{ inputs.skip_linux }}"
|
||||
--skip-linux-x64 "${{ inputs.skip_linux_x64 }}"
|
||||
--skip-linux-arm64 "${{ inputs.skip_linux_arm64 }}"
|
||||
--skip-targets "${{ inputs.skip_targets }}"
|
||||
|
||||
build:
|
||||
name: Build ${{ matrix.platform }} (${{ matrix.arch }})
|
||||
name: Build ${{ matrix.platform }} (${{ matrix.arch }}, ${{ matrix.desktop_variant }})
|
||||
needs:
|
||||
- meta
|
||||
- matrix
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 25
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
|
||||
env:
|
||||
CHANNEL: ${{ needs.meta.outputs.channel }}
|
||||
BUILD_CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
PUBLIC_RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
VERSION: ${{ needs.meta.outputs.version }}
|
||||
BUILD_VERSION: ${{ needs.meta.outputs.version }}
|
||||
PUBLIC_BUILD_VERSION: ${{ needs.meta.outputs.version }}
|
||||
PUB_DATE: ${{ needs.meta.outputs.pub_date }}
|
||||
SOURCE_SHA: ${{ needs.meta.outputs.source_sha }}
|
||||
S3_DESKTOP_PREFIX: ${{ needs.meta.outputs.s3_prefix }}
|
||||
DESKTOP_HANDOFF_PREFIX: _handoff/desktop/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
|
||||
S3_ENDPOINT: https://ewr1.vultrobjects.com
|
||||
S3_BUCKET: fluxer-downloads
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
DESKTOP_PLATFORM: ${{ matrix.platform }}
|
||||
DESKTOP_ARCH: ${{ matrix.arch }}
|
||||
DESKTOP_VARIANT: ${{ matrix.desktop_variant }}
|
||||
FLUXER_DESKTOP_BUILD_VARIANT: ${{ matrix.desktop_variant }}
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
ELECTRON_ARCH: ${{ matrix.electron_arch }}
|
||||
FLUXER_WINDOWS_GAME_CAPTURE_MODULE_ENABLED: ${{ matrix.desktop_variant == 'windows-game-capture' && 'true' || 'false' }}
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout CI helpers
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
ref: ${{ needs.meta.outputs.source_sha }}
|
||||
path: _ci
|
||||
|
||||
- name: Shorten Windows paths (workspace + temp for Squirrel) and pin pnpm store
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_sha }}
|
||||
path: source
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Set up Python (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Ensure python3 command (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step ensure_python3_windows
|
||||
|
||||
- name: Shorten Windows paths and pin pnpm store
|
||||
if: runner.os == 'Windows'
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step windows_paths
|
||||
env:
|
||||
SUBST_TARGET: ${{ github.workspace }}/source
|
||||
|
||||
- name: Set workdir (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
env:
|
||||
SUBST_TARGET: ${{ github.workspace }}/source
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step set_workdir_unix
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Set up pnpm via corepack
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step setup_pnpm_corepack
|
||||
|
||||
- name: Resolve pnpm store path (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step resolve_pnpm_store_windows
|
||||
|
||||
- name: Resolve pnpm store path (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step resolve_pnpm_store_unix
|
||||
|
||||
- name: Cache pnpm store
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae
|
||||
with:
|
||||
path: ${{ env.PNPM_STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
key: ${{ runner.os }}-${{ matrix.arch }}-pnpm-store-${{ hashFiles('source/**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
${{ runner.os }}-${{ matrix.arch }}-pnpm-store-
|
||||
|
||||
- name: Install Python setuptools (Windows ARM64)
|
||||
if: matrix.platform == 'windows' && matrix.arch == 'arm64'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_setuptools_windows_arm64
|
||||
|
||||
- name: Install Python setuptools (macOS)
|
||||
if: matrix.platform == 'macos'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_setuptools_macos
|
||||
|
||||
- name: Install Linux dependencies
|
||||
@@ -207,19 +232,46 @@ jobs:
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_linux_deps
|
||||
|
||||
- name: Set up Rust toolchain (Unix)
|
||||
if: matrix.platform != 'windows'
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
targets: ${{ matrix.platform == 'macos' && (matrix.arch == 'arm64' && 'aarch64-apple-darwin' || 'x86_64-apple-darwin') || (matrix.arch == 'arm64' && 'aarch64-unknown-linux-gnu' || 'x86_64-unknown-linux-gnu') }}
|
||||
|
||||
- name: Install MSVC ARM64 build tools
|
||||
if: matrix.platform == 'windows' && matrix.arch == 'arm64'
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_msvc_arm64_tools
|
||||
|
||||
- name: Set up MSVC env (Windows)
|
||||
if: matrix.platform == 'windows'
|
||||
uses: TheMrMilchmann/setup-msvc-dev@79dac248aac9d0059f86eae9d8b5bfab4e95e97c
|
||||
with:
|
||||
arch: ${{ matrix.arch == 'arm64' && 'amd64_arm64' || 'amd64' }}
|
||||
|
||||
- name: Set up Rust toolchain (Windows)
|
||||
if: matrix.platform == 'windows'
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_rust_windows_targets
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_dependencies
|
||||
|
||||
- name: Update version
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step update_version
|
||||
|
||||
- name: Set build channel
|
||||
@@ -227,20 +279,30 @@ jobs:
|
||||
env:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step set_build_channel
|
||||
|
||||
- name: Build Electron main process
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
env:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_electron_main
|
||||
|
||||
- name: Set up .NET SDK (Windows)
|
||||
if: matrix.platform == 'windows'
|
||||
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Install Velopack CLI
|
||||
if: matrix.platform == 'windows'
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step install_velopack_cli
|
||||
|
||||
- name: Build Electron app (macOS)
|
||||
if: matrix.platform == 'macos'
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
@@ -252,16 +314,16 @@ jobs:
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_app_macos
|
||||
|
||||
- name: Verify macOS bundle ID (fail fast if wrong channel)
|
||||
- name: Verify macOS artifact (bundle ID + profile + signature)
|
||||
if: matrix.platform == 'macos'
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
env:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step verify_bundle_id
|
||||
|
||||
- name: Build Electron app (Windows)
|
||||
@@ -271,22 +333,31 @@ jobs:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
TEMP: C:\t
|
||||
TMP: C:\t
|
||||
SQUIRREL_TEMP: C:\sq
|
||||
ELECTRON_BUILDER_CACHE: C:\ebcache
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_app_windows
|
||||
|
||||
- name: Analyze Squirrel nupkg for long paths
|
||||
- name: Package Windows app with Velopack
|
||||
if: matrix.platform == 'windows'
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
env:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step package_app_windows_velopack
|
||||
|
||||
- name: Analyze Velopack nupkg for long paths
|
||||
if: matrix.platform == 'windows'
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
env:
|
||||
BUILD_VERSION: ${{ env.VERSION }}
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
MAX_WINDOWS_PATH_LEN: 260
|
||||
PATH_HEADROOM: 10
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
--step analyse_squirrel_paths
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step analyse_velopack_paths
|
||||
|
||||
- name: Build Electron app (Linux)
|
||||
if: matrix.platform == 'linux'
|
||||
@@ -295,121 +366,271 @@ jobs:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
USE_SYSTEM_FPM: true
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_app_linux
|
||||
|
||||
- name: Create portable ZIP (Windows)
|
||||
if: matrix.platform == 'windows'
|
||||
working-directory: ${{ env.WORKDIR }}/fluxer_desktop
|
||||
env:
|
||||
BUILD_CHANNEL: ${{ env.BUILD_CHANNEL }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step create_portable_zip_windows
|
||||
|
||||
- name: Prepare artifacts (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step prepare_artifacts_windows
|
||||
|
||||
- name: Prepare artifacts (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step prepare_artifacts_unix
|
||||
|
||||
- name: Normalize updater YAML (arm64)
|
||||
if: matrix.arch == 'arm64'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step normalise_updater_yaml
|
||||
|
||||
- name: Generate SHA256 checksums (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step generate_checksums_unix
|
||||
|
||||
- name: Generate SHA256 checksums (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step generate_checksums_windows
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: Build desktop source tarball
|
||||
if: matrix.platform == 'linux' && matrix.arch == 'x64' && needs.meta.outputs.build_channel == 'canary'
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_source_tarball
|
||||
|
||||
- name: Upload artifacts to S3 handoff
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path ${{ github.workspace }}/_ci/tools/ci/Cargo.toml -- build-desktop
|
||||
--step upload_handoff
|
||||
|
||||
check_signing:
|
||||
name: Check signing secrets
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
enabled: ${{ steps.check.outputs.enabled }}
|
||||
steps:
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
name: fluxer-desktop-${{ env.BUILD_CHANNEL }}-${{ matrix.platform }}-${{ matrix.arch }}
|
||||
path: |
|
||||
upload_staging/*.exe
|
||||
upload_staging/*.exe.blockmap
|
||||
upload_staging/*.exe.sha256
|
||||
upload_staging/*.dmg
|
||||
upload_staging/*.dmg.sha256
|
||||
upload_staging/*.zip
|
||||
upload_staging/*.zip.blockmap
|
||||
upload_staging/*.zip.sha256
|
||||
upload_staging/*.AppImage
|
||||
upload_staging/*.AppImage.sha256
|
||||
upload_staging/*.deb
|
||||
upload_staging/*.deb.sha256
|
||||
upload_staging/*.rpm
|
||||
upload_staging/*.rpm.sha256
|
||||
upload_staging/*.tar.gz
|
||||
upload_staging/*.tar.gz.sha256
|
||||
upload_staging/*.yml
|
||||
upload_staging/*.nupkg
|
||||
upload_staging/*.nupkg.blockmap
|
||||
upload_staging/*.nupkg.sha256
|
||||
upload_staging/RELEASES*
|
||||
retention-days: 30
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Check for Azure signing secrets
|
||||
id: check
|
||||
env:
|
||||
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step check_signing_secrets
|
||||
|
||||
sign_windows:
|
||||
name: Sign Windows artifacts (${{ matrix.arch }}, ${{ matrix.desktop_variant }})
|
||||
if: ${{ needs.check_signing.outputs.enabled == 'true' }}
|
||||
needs:
|
||||
- meta
|
||||
- matrix
|
||||
- build
|
||||
- check_signing
|
||||
runs-on: blacksmith-32vcpu-windows-2025
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
BUILD_CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
DESKTOP_HANDOFF_PREFIX: _handoff/desktop/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
|
||||
S3_ENDPOINT: https://ewr1.vultrobjects.com
|
||||
S3_BUCKET: fluxer-downloads
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
EXPECT_WINDOWS_X64: ${{ needs.matrix.outputs.windows_x64 }}
|
||||
EXPECT_WINDOWS_ARM64: ${{ needs.matrix.outputs.windows_arm64 }}
|
||||
EXPECT_WINDOWS_X64_DEFAULT: ${{ needs.matrix.outputs.windows_x64_default }}
|
||||
EXPECT_WINDOWS_ARM64_DEFAULT: ${{ needs.matrix.outputs.windows_arm64_default }}
|
||||
EXPECT_WINDOWS_GAME_CAPTURE_X64: ${{ needs.matrix.outputs.windows_game_capture_x64 }}
|
||||
EXPECT_WINDOWS_GAME_CAPTURE_ARM64: ${{ needs.matrix.outputs.windows_game_capture_arm64 }}
|
||||
EXPECT_WINDOWS_ARTIFACTS: ${{ (matrix.desktop_variant == 'default' && matrix.arch == 'x64' && needs.matrix.outputs.windows_x64_default == 'true') || (matrix.desktop_variant == 'default' && matrix.arch == 'arm64' && needs.matrix.outputs.windows_arm64_default == 'true') || (matrix.desktop_variant == 'windows-game-capture' && matrix.arch == 'x64' && needs.matrix.outputs.windows_game_capture_x64 == 'true') || (matrix.desktop_variant == 'windows-game-capture' && matrix.arch == 'arm64' && needs.matrix.outputs.windows_game_capture_arm64 == 'true') }}
|
||||
DESKTOP_VARIANT: ${{ matrix.desktop_variant }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x64
|
||||
desktop_variant: default
|
||||
- arch: arm64
|
||||
desktop_variant: default
|
||||
- arch: x64
|
||||
desktop_variant: windows-game-capture
|
||||
- arch: arm64
|
||||
desktop_variant: windows-game-capture
|
||||
steps:
|
||||
- name: Checkout CI helpers
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_sha }}
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Download Windows artifacts from S3 handoff
|
||||
id: download_artifact
|
||||
if: env.EXPECT_WINDOWS_ARTIFACTS == 'true'
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step download_windows_handoff
|
||||
|
||||
- name: Check whether artifacts exist for this arch
|
||||
id: check_artifacts
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step check_windows_artifacts
|
||||
|
||||
- name: Azure login for Artifact Signing
|
||||
if: steps.check_artifacts.outputs.found == 'true'
|
||||
uses: azure/login@1384c340ab2dda50fed2bee3041d1d87018aa5e8
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
||||
|
||||
- name: Sign Windows executables with Artifact Signing
|
||||
if: steps.check_artifacts.outputs.found == 'true'
|
||||
uses: azure/artifact-signing-action@5289deff81257f39600de2188534e17b633ba835
|
||||
with:
|
||||
endpoint: ${{ secrets.AZURE_ARTIFACT_SIGNING_ENDPOINT }}
|
||||
signing-account-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_ACCOUNT_NAME }}
|
||||
certificate-profile-name: ${{ secrets.AZURE_ARTIFACT_SIGNING_CERTIFICATE_PROFILE_NAME }}
|
||||
files-folder: ${{ github.workspace }}\artifacts\windows-${{ matrix.arch }}${{ matrix.desktop_variant == 'windows-game-capture' && '-windows-game-capture' || '' }}
|
||||
files-folder-filter: exe
|
||||
files-folder-recurse: true
|
||||
file-digest: SHA256
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
|
||||
- name: Verify Authenticode signatures
|
||||
if: steps.check_artifacts.outputs.found == 'true'
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step verify_authenticode
|
||||
|
||||
- name: Regenerate SHA256 checksums for signed executables
|
||||
if: steps.check_artifacts.outputs.found == 'true'
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step regenerate_signed_checksums
|
||||
|
||||
- name: Re-upload signed Windows artifacts to S3 handoff
|
||||
if: steps.check_artifacts.outputs.found == 'true'
|
||||
env:
|
||||
DESKTOP_PLATFORM: windows
|
||||
DESKTOP_ARCH: ${{ matrix.arch }}
|
||||
DESKTOP_VARIANT: ${{ matrix.desktop_variant }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step stage_signed_windows_artifacts
|
||||
|
||||
upload:
|
||||
name: Upload to S3 (rclone)
|
||||
name: Upload to S3
|
||||
if: ${{ !failure() && !cancelled() }}
|
||||
needs:
|
||||
- meta
|
||||
- build
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
- sign_windows
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
DISPLAY_CHANNEL: ${{ needs.meta.outputs.channel }}
|
||||
RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
PUBLIC_RELEASE_CHANNEL: ${{ needs.meta.outputs.build_channel }}
|
||||
VERSION: ${{ needs.meta.outputs.version }}
|
||||
BUILD_VERSION: ${{ needs.meta.outputs.version }}
|
||||
PUBLIC_BUILD_VERSION: ${{ needs.meta.outputs.version }}
|
||||
PUB_DATE: ${{ needs.meta.outputs.pub_date }}
|
||||
S3_ENDPOINT: https://s3.us-east-va.io.cloud.ovh.us
|
||||
TEST_BUILD: ${{ needs.meta.outputs.test_build }}
|
||||
SOURCE_SHA: ${{ needs.meta.outputs.source_sha }}
|
||||
S3_DESKTOP_PREFIX: ${{ needs.meta.outputs.s3_prefix }}
|
||||
DESKTOP_HANDOFF_PREFIX: _handoff/desktop/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
|
||||
S3_ENDPOINT: https://ewr1.vultrobjects.com
|
||||
S3_BUCKET: fluxer-downloads
|
||||
PUBLIC_DL_BASE: https://api.fluxer.app/dl
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
ref: ${{ needs.meta.outputs.source_sha }}
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
path: artifacts
|
||||
pattern: fluxer-desktop-${{ needs.meta.outputs.build_channel }}-*
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install rclone
|
||||
- name: Download S3 handoff artifacts
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
--step install_rclone
|
||||
|
||||
- name: Configure rclone (OVH S3)
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
--step configure_rclone
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step download_handoff
|
||||
|
||||
- name: Build S3 payload layout (+ manifest.json)
|
||||
env:
|
||||
VERSION: ${{ needs.meta.outputs.version }}
|
||||
PUB_DATE: ${{ needs.meta.outputs.pub_date }}
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_payload
|
||||
|
||||
- name: Upload payload to S3
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step upload_payload
|
||||
|
||||
- name: Verify uploaded source tarball
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step verify_source_tarball
|
||||
|
||||
- name: Build summary
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/build_desktop.py
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step build_summary
|
||||
|
||||
- name: Notify canary desktop webhook
|
||||
if: ${{ success() && needs.meta.outputs.channel == 'canary' }}
|
||||
env:
|
||||
FLUXER_WEBHOOK_URL: ${{ secrets.FLUXER_WEBHOOK_URL }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step notify_webhook
|
||||
|
||||
- name: Cleanup S3 handoff
|
||||
if: ${{ success() }}
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
|
||||
--step cleanup_handoff
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-docs
|
||||
dockerfile: fluxer_docs/Dockerfile
|
||||
context: fluxer_docs
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build gateway
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-gateway
|
||||
dockerfile: fluxer_gateway/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build marketing
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-marketing
|
||||
dockerfile: fluxer_marketing/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build media-proxy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-media-proxy
|
||||
dockerfile: fluxer_media_proxy/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build messages
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-messages
|
||||
dockerfile: fluxer_messages/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build snowflakes
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-snowflakes
|
||||
dockerfile: fluxer_snowflakes/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build static
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-static
|
||||
dockerfile: fluxer_static/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build unfurl
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-unfurl
|
||||
dockerfile: fluxer_unfurl/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,32 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: build users
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
workflow_call:
|
||||
inputs:
|
||||
build-version:
|
||||
description: "Explicit Fluxer CalVer build version (YYYY.MDD.MICRO, UTC HHMMSS without leading zeroes) to use instead of automatic UTC clock allocation"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
image:
|
||||
uses: ./.github/workflows/_build-image.yaml
|
||||
with:
|
||||
image: fluxer-users
|
||||
dockerfile: fluxer_users/Dockerfile
|
||||
build-version: ${{ inputs.build-version }}
|
||||
secrets: inherit
|
||||
@@ -1,48 +0,0 @@
|
||||
name: channel vars
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
github_event_name:
|
||||
type: string
|
||||
github_ref_name:
|
||||
type: string
|
||||
required: false
|
||||
workflow_dispatch_channel:
|
||||
type: string
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
channel:
|
||||
description: 'Computed release channel (stable|canary)'
|
||||
value: ${{ jobs.emit.outputs.channel }}
|
||||
is_canary:
|
||||
description: 'Whether this is a canary deploy (true|false)'
|
||||
value: ${{ jobs.emit.outputs.is_canary }}
|
||||
stack_suffix:
|
||||
description: "Suffix for stack/image names ('' or '-canary')"
|
||||
value: ${{ jobs.emit.outputs.stack_suffix }}
|
||||
|
||||
jobs:
|
||||
emit:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
outputs:
|
||||
channel: ${{ steps.compute.outputs.channel }}
|
||||
is_canary: ${{ steps.compute.outputs.is_canary }}
|
||||
stack_suffix: ${{ steps.compute.outputs.stack_suffix }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: Determine channel
|
||||
id: compute
|
||||
shell: bash
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/channel_vars.py
|
||||
--event-name "${{ inputs.github_event_name }}"
|
||||
--ref-name "${{ inputs.github_ref_name || '' }}"
|
||||
--dispatch-channel "${{ inputs.workflow_dispatch_channel || '' }}"
|
||||
+251
-50
@@ -1,78 +1,156 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_REGISTRY: ghcr.io/${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
typecheck:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: python3 scripts/ci/workflows/ci.py --step install_dependencies
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step install_dependencies
|
||||
|
||||
- name: Run typecheck
|
||||
run: python3 scripts/ci/workflows/ci.py --step typecheck
|
||||
env:
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step typecheck
|
||||
|
||||
test:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: python3 scripts/ci/workflows/ci.py --step install_dependencies
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step install_dependencies
|
||||
|
||||
- name: Run tests
|
||||
run: python3 scripts/ci/workflows/ci.py --step test
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step test
|
||||
|
||||
rust:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
|
||||
with:
|
||||
toolchain: stable
|
||||
components: clippy, rustfmt
|
||||
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
|
||||
restore-keys: |
|
||||
rust-${{ runner.os }}-
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Clippy (warnings as errors)
|
||||
run: cargo clippy --workspace -- -D warnings
|
||||
|
||||
- name: Run tests
|
||||
run: cargo test --workspace
|
||||
|
||||
marketing-docker:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
|
||||
- name: Build marketing image
|
||||
run: |
|
||||
BUILD_VERSION="$(cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- resolve-calver)"
|
||||
docker build \
|
||||
-f fluxer_marketing/Dockerfile \
|
||||
-t "fluxer-marketing:${BUILD_VERSION}" \
|
||||
--build-arg "BUILD_VERSION=${BUILD_VERSION}" \
|
||||
.
|
||||
env:
|
||||
FLUXER_CONFIG: config/config.test.json
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
gateway:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Set up Erlang
|
||||
uses: erlef/setup-beam@v1
|
||||
uses: erlef/setup-beam@3559ac3b631a9560f28817e8e7fdde1638664336
|
||||
with:
|
||||
otp-version: '28'
|
||||
rebar3-version: '3.24.0'
|
||||
|
||||
- name: Cache rebar3 dependencies
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
|
||||
with:
|
||||
path: |
|
||||
fluxer_gateway/_build
|
||||
@@ -81,57 +159,180 @@ jobs:
|
||||
restore-keys: |
|
||||
rebar3-${{ runner.os }}-
|
||||
|
||||
- name: Check formatting
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step gateway_fmt
|
||||
|
||||
- name: Compile
|
||||
run: python3 scripts/ci/workflows/ci.py --step gateway_compile
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step gateway_compile
|
||||
|
||||
- name: Run dialyzer
|
||||
run: python3 scripts/ci/workflows/ci.py --step gateway_dialyzer
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step gateway_dialyzer
|
||||
|
||||
- name: Run eunit tests
|
||||
run: python3 scripts/ci/workflows/ci.py --step gateway_eunit
|
||||
env:
|
||||
FLUXER_CONFIG: ../config/config.test.json
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step gateway_eunit
|
||||
|
||||
knip:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: python3 scripts/ci/workflows/ci.py --step install_dependencies
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step install_dependencies
|
||||
|
||||
- name: Run knip
|
||||
run: python3 scripts/ci/workflows/ci.py --step knip
|
||||
env:
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step knip
|
||||
|
||||
ci-scripts:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up uv
|
||||
uses: astral-sh/setup-uv@v7
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
|
||||
with:
|
||||
python-version: "3.12"
|
||||
toolchain: stable
|
||||
components: rustfmt
|
||||
|
||||
- name: Sync ci python dependencies
|
||||
run: python3 scripts/ci/workflows/ci_scripts.py --step sync
|
||||
- name: Sync ci helper dependencies
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci-scripts
|
||||
--step sync
|
||||
|
||||
- name: Run ci python tests
|
||||
run: python3 scripts/ci/workflows/ci_scripts.py --step test
|
||||
- name: Run ci helper tests
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci-scripts
|
||||
--step test
|
||||
|
||||
helm-and-scripts:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install helm
|
||||
uses: azure/setup-helm@bf6a7d304bc2fdb57e0331155b7ebf2c504acf0a
|
||||
|
||||
- name: Resolve Helm test build version
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- resolve-calver
|
||||
--github-env
|
||||
--env-name HELM_TEST_BUILD_VERSION
|
||||
|
||||
- name: Helm dependency update (all charts)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for chart_dir in deploy/helm/*/; do
|
||||
if [[ -f "${chart_dir}Chart.yaml" ]]; then
|
||||
helm dependency update "$chart_dir"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Helm lint (all charts)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
FAILED=0
|
||||
for chart_dir in deploy/helm/*/; do
|
||||
if [[ -f "${chart_dir}Chart.yaml" ]]; then
|
||||
echo "--- Linting ${chart_dir} ---"
|
||||
VALUES_ARGS=()
|
||||
if [[ -f "${chart_dir}values.yaml" ]]; then
|
||||
VALUES_ARGS=(-f "${chart_dir}values.yaml")
|
||||
fi
|
||||
EXTRA_SETS=(--set-string "global.registry=${GHCR_REGISTRY}")
|
||||
case "${chart_dir}" in
|
||||
*gateway*)
|
||||
EXTRA_SETS+=(--set-string "gateway.tag=${HELM_TEST_BUILD_VERSION}" --set-string "gateway.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*api*)
|
||||
EXTRA_SETS+=(--set-string app.name=api --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*app-proxy*)
|
||||
EXTRA_SETS+=(--set-string app.name=app-proxy --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*admin*)
|
||||
EXTRA_SETS+=(--set-string app.name=admin --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*marketing*)
|
||||
EXTRA_SETS+=(--set-string app.name=marketing --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*media-proxy*)
|
||||
EXTRA_SETS+=(--set-string "mediaProxy.tag=${HELM_TEST_BUILD_VERSION}" --set-string "staticProxy.tag=${HELM_TEST_BUILD_VERSION}" --set-string "mediaProxy.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "staticProxy.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*uploads*)
|
||||
EXTRA_SETS+=(--set-string app.name=uploads --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*worker*)
|
||||
EXTRA_SETS+=(--set-string "workerRealtime.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerUnfurl.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerLifecycle.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerBatch.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerRealtime.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "workerUnfurl.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "workerLifecycle.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "workerBatch.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*member-lists*|*messages*|*presence*|*snowflakes*|*unfurl*|*users*|*voice-states*)
|
||||
EXTRA_SETS+=(--set-string "svc.tag=${HELM_TEST_BUILD_VERSION}" --set-string "svc.build.version=${HELM_TEST_BUILD_VERSION}" --set-string svc.build.channel=stable)
|
||||
;;
|
||||
esac
|
||||
if ! helm lint "$chart_dir" "${VALUES_ARGS[@]}" "${EXTRA_SETS[@]}" --strict; then
|
||||
FAILED=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [[ "$FAILED" -ne 0 ]]; then
|
||||
echo "::error::One or more Helm charts failed linting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Helm template (gateway)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
helm template fluxer-gateway deploy/helm/gateway \
|
||||
-f deploy/helm/gateway/values.yaml \
|
||||
--set-string "global.registry=${GHCR_REGISTRY}" \
|
||||
--set-string "gateway.tag=${HELM_TEST_BUILD_VERSION}" \
|
||||
--set-string "gateway.build.version=${HELM_TEST_BUILD_VERSION}" \
|
||||
-n fluxer > /dev/null
|
||||
echo "Gateway chart templates render successfully."
|
||||
|
||||
- name: Validate gateway manifests with kubeconform
|
||||
run: |
|
||||
set -euo pipefail
|
||||
helm template fluxer-gateway deploy/helm/gateway \
|
||||
-f deploy/helm/gateway/values.yaml \
|
||||
--set-string "global.registry=${GHCR_REGISTRY}" \
|
||||
--set-string "gateway.tag=${HELM_TEST_BUILD_VERSION}" \
|
||||
--set-string "gateway.build.version=${HELM_TEST_BUILD_VERSION}" \
|
||||
-n fluxer \
|
||||
| docker run -i --rm ghcr.io/yannh/kubeconform:v0.6.7 \
|
||||
-strict -summary -kubernetes-version 1.31.0
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
name: deploy admin
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
paths:
|
||||
- fluxer_admin/**
|
||||
- .github/workflows/deploy-admin.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
type: choice
|
||||
options:
|
||||
- stable
|
||||
- canary
|
||||
default: stable
|
||||
description: Release channel to deploy
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-admin-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
channel-vars:
|
||||
uses: ./.github/workflows/channel-vars.yaml
|
||||
with:
|
||||
github_event_name: ${{ github.event_name }}
|
||||
github_ref_name: ${{ github.ref_name }}
|
||||
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
|
||||
|
||||
deploy:
|
||||
name: Deploy admin
|
||||
needs: channel-vars
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
|
||||
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
|
||||
STACK: ${{ format('fluxer-admin{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
CACHE_SCOPE: ${{ format('deploy-fluxer-admin{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
CADDY_DOMAIN: ${{ needs.channel-vars.outputs.is_canary == 'true' && 'admin.canary.fluxer.app' || 'admin.fluxer.app' }}
|
||||
REPLICAS: ${{ needs.channel-vars.outputs.is_canary == 'true' && 1 || 2 }}
|
||||
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_admin.py --step record_deploy_commit
|
||||
|
||||
- name: Set build timestamp
|
||||
run: python3 scripts/ci/workflows/deploy_admin.py --step set_build_timestamp
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_admin/Dockerfile
|
||||
tags: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.DEPLOY_SHA }}
|
||||
BUILD_NUMBER=${{ github.run_number }}
|
||||
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_admin.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_admin.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
IMAGE_TAG: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
STACK: ${{ env.STACK }}
|
||||
CADDY_DOMAIN: ${{ env.CADDY_DOMAIN }}
|
||||
REPLICAS: ${{ env.REPLICAS }}
|
||||
run: python3 scripts/ci/workflows/deploy_admin.py --step push_and_deploy
|
||||
@@ -1,119 +0,0 @@
|
||||
name: deploy api
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
paths:
|
||||
- fluxer_api/**
|
||||
- .github/workflows/deploy-api.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
type: choice
|
||||
options:
|
||||
- stable
|
||||
- canary
|
||||
default: stable
|
||||
description: Release channel to deploy
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-api-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
channel-vars:
|
||||
uses: ./.github/workflows/channel-vars.yaml
|
||||
with:
|
||||
github_event_name: ${{ github.event_name }}
|
||||
github_ref_name: ${{ github.ref_name }}
|
||||
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
|
||||
|
||||
deploy:
|
||||
name: Deploy api
|
||||
needs: channel-vars
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
|
||||
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
|
||||
|
||||
STACK: ${{ format('fluxer-api{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
WORKER_STACK: fluxer-api-worker
|
||||
CANARY_WORKER_REPLICAS: 3
|
||||
CACHE_SCOPE: ${{ format('deploy-fluxer-api{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
|
||||
CADDY_DOMAIN: ${{ needs.channel-vars.outputs.is_canary == 'true' && 'api.canary.fluxer.app' || 'api.fluxer.app' }}
|
||||
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_api.py --step record_deploy_commit
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build image(s)
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_api/Dockerfile
|
||||
tags: |
|
||||
${{ env.STACK }}:${{ env.DEPLOY_SHA }}
|
||||
${{ env.WORKER_STACK }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.SENTRY_BUILD_SHA }}
|
||||
BUILD_NUMBER=${{ env.SENTRY_BUILD_NUMBER }}
|
||||
BUILD_TIMESTAMP=${{ env.SENTRY_BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_api.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_api.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image(s) and deploy
|
||||
env:
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
IMAGE_TAG_APP: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
|
||||
IMAGE_TAG_WORKER: ${{ env.WORKER_STACK }}:${{ env.DEPLOY_SHA }}
|
||||
CANARY_WORKER_REPLICAS: ${{ env.CANARY_WORKER_REPLICAS }}
|
||||
SENTRY_BUILD_SHA: ${{ env.SENTRY_BUILD_SHA }}
|
||||
SENTRY_BUILD_NUMBER: ${{ env.SENTRY_BUILD_NUMBER }}
|
||||
SENTRY_BUILD_TIMESTAMP: ${{ env.SENTRY_BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL: ${{ env.CHANNEL }}
|
||||
SENTRY_RELEASE: ${{ format('fluxer-api@{0}', env.SENTRY_BUILD_SHA) }}
|
||||
run: python3 scripts/ci/workflows/deploy_api.py --step push_and_deploy
|
||||
@@ -1,191 +0,0 @@
|
||||
name: deploy app
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
paths:
|
||||
- fluxer_app/**
|
||||
- fluxer_app_proxy/**
|
||||
- .github/workflows/deploy-app.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
type: choice
|
||||
options:
|
||||
- stable
|
||||
- canary
|
||||
default: stable
|
||||
description: Release channel to deploy
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-app-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
channel-vars:
|
||||
uses: ./.github/workflows/channel-vars.yaml
|
||||
with:
|
||||
github_event_name: ${{ github.event_name }}
|
||||
github_ref_name: ${{ github.ref_name }}
|
||||
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
|
||||
|
||||
deploy:
|
||||
name: Deploy app
|
||||
needs: channel-vars
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
|
||||
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
|
||||
|
||||
SERVICE_NAME: ${{ format('fluxer-app{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
DOCKERFILE: fluxer_app_proxy/Dockerfile
|
||||
CACHE_SCOPE: ${{ format('fluxer-app{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
|
||||
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
APP_REPLICAS: ${{ needs.channel-vars.outputs.is_canary == 'true' && 1 || 2 }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: pnpm
|
||||
cache-dependency-path: fluxer_app/pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step install_dependencies
|
||||
|
||||
- name: Run Lingui i18n tasks
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step run_lingui
|
||||
env:
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step record_deploy_commit
|
||||
|
||||
- name: Set up Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: wasm32-unknown-unknown
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
fluxer_app/crates/gif_wasm/target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('fluxer_app/crates/gif_wasm/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step install_wasm_pack
|
||||
|
||||
- name: Generate wasm artifacts
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step generate_wasm
|
||||
env:
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Fetch deployment config
|
||||
env:
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
RELEASE_CHANNEL: ${{ env.RELEASE_CHANNEL }}
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step fetch_deployment_config
|
||||
|
||||
- name: Build application
|
||||
env:
|
||||
FLUXER_CONFIG: ${{ github.workspace }}/fluxer_app/config.json
|
||||
TURBO_API: https://turborepo.fluxer.dev
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: team_fluxer
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step build_application
|
||||
|
||||
- name: Install rclone
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step install_rclone
|
||||
|
||||
- name: Upload assets to S3 static bucket
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step upload_assets
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Set build timestamp
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step set_build_timestamp
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ${{ env.DOCKERFILE }}
|
||||
tags: ${{ env.SERVICE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.DEPLOY_SHA }}
|
||||
BUILD_NUMBER=${{ github.run_number }}
|
||||
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step install_docker_pussh
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
IMAGE_TAG: ${{ env.SERVICE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
|
||||
SERVICE_NAME: ${{ env.SERVICE_NAME }}
|
||||
COMPOSE_STACK: ${{ env.SERVICE_NAME }}
|
||||
|
||||
RELEASE_CHANNEL: ${{ env.RELEASE_CHANNEL }}
|
||||
APP_REPLICAS: ${{ env.APP_REPLICAS }}
|
||||
run: python3 scripts/ci/workflows/deploy_app.py --step push_and_deploy
|
||||
@@ -1,62 +0,0 @@
|
||||
name: deploy gateway
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
push:
|
||||
branches:
|
||||
- canary
|
||||
paths:
|
||||
- 'fluxer_gateway/**'
|
||||
|
||||
concurrency:
|
||||
group: deploy-gateway
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy (hot patch)
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
sparse-checkout: |
|
||||
fluxer_gateway
|
||||
scripts/ci
|
||||
|
||||
- name: Set up Erlang
|
||||
uses: erlef/setup-beam@v1
|
||||
with:
|
||||
otp-version: '28'
|
||||
rebar3-version: '3.24.0'
|
||||
|
||||
- name: Compile
|
||||
run: python3 scripts/ci/workflows/deploy_gateway.py --step compile
|
||||
|
||||
- name: Set up SSH
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_gateway.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_gateway.py --step record_deploy_commit
|
||||
|
||||
- name: Deploy
|
||||
env:
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
GATEWAY_ADMIN_SECRET: ${{ secrets.GATEWAY_ADMIN_SECRET }}
|
||||
run: python3 scripts/ci/workflows/deploy_gateway.py --step deploy
|
||||
@@ -1,117 +0,0 @@
|
||||
name: deploy marketing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
paths:
|
||||
- fluxer_marketing/**
|
||||
- .github/workflows/deploy-marketing.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
type: choice
|
||||
options:
|
||||
- stable
|
||||
- canary
|
||||
default: stable
|
||||
description: Release channel to deploy
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-marketing-${{ github.event_name == 'workflow_dispatch' && inputs.channel || (github.ref_name == 'canary' && 'canary') || 'stable' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
channel-vars:
|
||||
uses: ./.github/workflows/channel-vars.yaml
|
||||
with:
|
||||
github_event_name: ${{ github.event_name }}
|
||||
github_ref_name: ${{ github.ref_name }}
|
||||
workflow_dispatch_channel: ${{ github.event_name == 'workflow_dispatch' && inputs.channel || '' }}
|
||||
|
||||
deploy:
|
||||
name: Deploy marketing
|
||||
needs: channel-vars
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
IS_CANARY: ${{ needs.channel-vars.outputs.is_canary }}
|
||||
STACK_SUFFIX: ${{ needs.channel-vars.outputs.stack_suffix }}
|
||||
STACK: ${{ format('fluxer-marketing{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
IMAGE_NAME: ${{ format('fluxer-marketing{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
CACHE_SCOPE: ${{ format('deploy-fluxer-marketing{0}', needs.channel-vars.outputs.stack_suffix) }}
|
||||
APP_REPLICAS: ${{ needs.channel-vars.outputs.is_canary == 'true' && 1 || 2 }}
|
||||
CADDY_DOMAIN: ${{ needs.channel-vars.outputs.is_canary == 'true' && 'canary.fluxer.app' || 'fluxer.app' }}
|
||||
RELEASE_CHANNEL: ${{ needs.channel-vars.outputs.channel }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_marketing.py --step record_deploy_commit
|
||||
|
||||
- name: Set build timestamp
|
||||
run: python3 scripts/ci/workflows/deploy_marketing.py --step set_build_timestamp
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_marketing/Dockerfile
|
||||
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.DEPLOY_SHA }}
|
||||
BUILD_NUMBER=${{ github.run_number }}
|
||||
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_marketing.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_marketing.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
STACK: ${{ env.STACK }}
|
||||
IS_CANARY: ${{ env.IS_CANARY }}
|
||||
CADDY_DOMAIN: ${{ env.CADDY_DOMAIN }}
|
||||
RELEASE_CHANNEL: ${{ env.RELEASE_CHANNEL }}
|
||||
APP_REPLICAS: ${{ env.APP_REPLICAS }}
|
||||
run: python3 scripts/ci/workflows/deploy_marketing.py --step push_and_deploy
|
||||
@@ -1,92 +0,0 @@
|
||||
name: deploy media-proxy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- fluxer_media_proxy/**
|
||||
- .github/workflows/deploy-media-proxy.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-media-proxy
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
SERVICE_NAME: fluxer-media-proxy
|
||||
IMAGE_NAME: fluxer-media-proxy
|
||||
CONTEXT_DIR: fluxer_media_proxy
|
||||
COMPOSE_STACK: fluxer-media-proxy
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy media proxy
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
RELEASE_CHANNEL: stable
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step record_deploy_commit
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Set build timestamp
|
||||
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step set_build_timestamp
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ${{ env.CONTEXT_DIR }}/Dockerfile
|
||||
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.SERVICE_NAME }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.SERVICE_NAME }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.DEPLOY_SHA }}
|
||||
BUILD_NUMBER=${{ github.run_number }}
|
||||
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
run: python3 scripts/ci/workflows/deploy_media_proxy.py --step push_and_deploy
|
||||
@@ -1,91 +0,0 @@
|
||||
name: deploy relay directory
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- canary
|
||||
paths:
|
||||
- fluxer_relay_directory/**
|
||||
- .github/workflows/deploy-relay-directory.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-relay-directory
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy relay directory
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
STACK: fluxer-relay-directory
|
||||
CACHE_SCOPE: deploy-fluxer-relay-directory
|
||||
IS_CANARY: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step record_deploy_commit
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Set build timestamp
|
||||
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step set_build_timestamp
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_relay_directory/Dockerfile
|
||||
tags: |
|
||||
${{ env.STACK }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.DEPLOY_SHA }}
|
||||
BUILD_NUMBER=${{ github.run_number }}
|
||||
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=canary
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
IMAGE_TAG: ${{ env.STACK }}:${{ env.DEPLOY_SHA }}
|
||||
run: python3 scripts/ci/workflows/deploy_relay_directory.py --step push_and_deploy
|
||||
@@ -1,62 +0,0 @@
|
||||
name: deploy relay
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
push:
|
||||
branches:
|
||||
- canary
|
||||
paths:
|
||||
- 'fluxer_relay/**'
|
||||
|
||||
concurrency:
|
||||
group: deploy-relay
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy (hot patch)
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
sparse-checkout: |
|
||||
fluxer_relay
|
||||
scripts/ci
|
||||
|
||||
- name: Set up Erlang
|
||||
uses: erlef/setup-beam@v1
|
||||
with:
|
||||
otp-version: '28'
|
||||
rebar3-version: '3.24.0'
|
||||
|
||||
- name: Compile
|
||||
run: python3 scripts/ci/workflows/deploy_relay.py --step compile
|
||||
|
||||
- name: Set up SSH
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_relay.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_relay.py --step record_deploy_commit
|
||||
|
||||
- name: Deploy
|
||||
env:
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
RELAY_ADMIN_SECRET: ${{ secrets.RELAY_ADMIN_SECRET }}
|
||||
run: python3 scripts/ci/workflows/deploy_relay.py --step deploy
|
||||
@@ -0,0 +1,510 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: deploy service
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
service:
|
||||
description: "Helm chart name to deploy"
|
||||
type: choice
|
||||
required: true
|
||||
options:
|
||||
- api
|
||||
- app-proxy
|
||||
- admin
|
||||
- docs
|
||||
- marketing
|
||||
- media-proxy
|
||||
- gateway
|
||||
- data-service
|
||||
- messages
|
||||
- search
|
||||
- snowflakes
|
||||
- users
|
||||
- unfurl
|
||||
- uploads
|
||||
- worker
|
||||
channel:
|
||||
description: "Release channel (stable or canary)"
|
||||
type: choice
|
||||
required: true
|
||||
options:
|
||||
- stable
|
||||
- canary
|
||||
image-tag:
|
||||
description: "Docker image tag to deploy (Fluxer CalVer: YYYY.MDD.MICRO)"
|
||||
type: string
|
||||
required: true
|
||||
build-version:
|
||||
description: "Fluxer CalVer build version to inject into runtime env vars"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
allow-rollback:
|
||||
description: "Allow deploying an older image tag than the newest GHCR tag"
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
workflow_call:
|
||||
inputs:
|
||||
service:
|
||||
description: "Helm chart name to deploy"
|
||||
type: string
|
||||
required: true
|
||||
channel:
|
||||
description: "Release channel (stable or canary)"
|
||||
type: string
|
||||
required: true
|
||||
image-tag:
|
||||
description: "Docker image tag to deploy (Fluxer CalVer: YYYY.MDD.MICRO)"
|
||||
type: string
|
||||
required: true
|
||||
build-version:
|
||||
description: "Fluxer CalVer build version to inject into runtime env vars"
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
allow-rollback:
|
||||
description: "Allow deploying an older image tag than the newest GHCR tag"
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
secrets:
|
||||
KUBE_CONFIG:
|
||||
required: true
|
||||
GHCR_USERNAME:
|
||||
required: false
|
||||
GHCR_TOKEN:
|
||||
required: false
|
||||
FLUXER_WEBHOOK_URL:
|
||||
required: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_OWNER: ${{ github.repository_owner }}
|
||||
GHCR_REGISTRY: ghcr.io/${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: deploy ${{ inputs.service }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 60
|
||||
environment: ${{ inputs.channel }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
env:
|
||||
GIT_CONFIG_GLOBAL: ${{ runner.temp }}/gitconfig
|
||||
- name: install helm
|
||||
uses: azure/setup-helm@bf6a7d304bc2fdb57e0331155b7ebf2c504acf0a
|
||||
|
||||
- name: configure kubectl
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "$HOME/.kube"
|
||||
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > "$HOME/.kube/config"
|
||||
chmod 600 "$HOME/.kube/config"
|
||||
|
||||
- name: resolve helm args
|
||||
id: helm
|
||||
shell: bash
|
||||
run: |
|
||||
SERVICE="${{ inputs.service }}"
|
||||
CHANNEL="${{ inputs.channel }}"
|
||||
TAG="${{ inputs['image-tag'] }}"
|
||||
BUILD_VERSION="${{ inputs['build-version'] }}"
|
||||
GHCR_REGISTRY="${GHCR_REGISTRY:?GHCR_REGISTRY is required}"
|
||||
if [[ -z "$BUILD_VERSION" ]]; then
|
||||
BUILD_VERSION="$TAG"
|
||||
fi
|
||||
CALVER_RE='^[1-9][0-9]{3}\.[1-9][0-9]{2,3}\.(0|[1-9][0-9]{0,5})$'
|
||||
if [[ ! "$TAG" =~ $CALVER_RE ]]; then
|
||||
echo "::error::image-tag must be a Fluxer CalVer tag (YYYY.MDD.MICRO). Channel tags, latest tags, and suffixed tags are not deployable."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "$BUILD_VERSION" =~ $CALVER_RE ]]; then
|
||||
echo "::error::build-version must be a Fluxer CalVer value (YYYY.MDD.MICRO)."
|
||||
exit 1
|
||||
fi
|
||||
CHART_DIR="./deploy/helm/${SERVICE}"
|
||||
VALUES_ARGS="-f ${CHART_DIR}/values.yaml"
|
||||
SETS=""
|
||||
BUILD_PATHS=""
|
||||
DEPLOY_IMAGE=""
|
||||
SYNC_WORKER_RELEASE=""
|
||||
SYNC_WORKER_CHART_DIR=""
|
||||
SYNC_WORKER_VALUES_ARGS=""
|
||||
SYNC_WORKER_SETS=""
|
||||
case "$SERVICE" in
|
||||
uploads)
|
||||
|
||||
if [[ "$CHANNEL" != "stable" ]]; then
|
||||
echo "::error::uploads deployments are stable-only (single relay serves both channels)."
|
||||
exit 1
|
||||
fi
|
||||
RELEASE="fluxer-uploads"
|
||||
DEPLOY_IMAGE="fluxer-media-proxy"
|
||||
SETS="--set-string app.name=uploads --set-string app.image=fluxer-media-proxy --set-string app.tag=${TAG} --set-string app.config=stable"
|
||||
SETS="${SETS} --set-string app.build.version=${BUILD_VERSION}"
|
||||
SETS="${SETS} --set-string app.build.channel=stable"
|
||||
;;
|
||||
api|app-proxy|admin|docs|marketing)
|
||||
BASE_IMAGE="fluxer-${SERVICE}"
|
||||
if [[ "$SERVICE" == "docs" && "$CHANNEL" != "stable" ]]; then
|
||||
echo "::error::docs deployments are stable-only."
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$CHANNEL" == "canary" ]]; then
|
||||
NAME="${SERVICE}-canary"
|
||||
else
|
||||
NAME="${SERVICE}"
|
||||
fi
|
||||
DEPLOY_IMAGE="${BASE_IMAGE}"
|
||||
RELEASE="fluxer-${SERVICE}-${CHANNEL}"
|
||||
VALUES_ARGS="${VALUES_ARGS} -f ${CHART_DIR}/values.${CHANNEL}.prod.yaml"
|
||||
SETS="--set-string app.name=${NAME} --set-string app.image=${DEPLOY_IMAGE} --set-string app.tag=${TAG}"
|
||||
SETS="${SETS} --set-string app.build.version=${BUILD_VERSION}"
|
||||
SETS="${SETS} --set-string app.build.channel=${CHANNEL}"
|
||||
;;
|
||||
media-proxy)
|
||||
if [[ "$CHANNEL" != "canary" ]]; then
|
||||
echo "::error::Media-proxy deployments are only supported on the canary lane."
|
||||
exit 1
|
||||
fi
|
||||
RELEASE="fluxer-${SERVICE}"
|
||||
DEPLOY_IMAGE="fluxer-media-proxy"
|
||||
VALUES_ARGS="${VALUES_ARGS} -f ${CHART_DIR}/values.prod.yaml"
|
||||
SETS="--set-string mediaProxy.image=fluxer-media-proxy --set-string staticProxy.image=fluxer-media-proxy --set-string mediaProxy.tag=${TAG} --set-string staticProxy.tag=${TAG} --set mediaProxy.replicas=16 --set staticProxy.replicas=4 --set-string mediaProxy.nsfwServiceEndpoint=http://int.flx-nyc-misc1.srv.fluxer.dev:8000"
|
||||
BUILD_PATHS="mediaProxy staticProxy"
|
||||
;;
|
||||
gateway)
|
||||
if [[ "$CHANNEL" != "stable" ]]; then
|
||||
echo "::error::gateway deployments are stable-only."
|
||||
exit 1
|
||||
fi
|
||||
RELEASE="fluxer-${SERVICE}"
|
||||
DEPLOY_IMAGE="fluxer-gateway"
|
||||
VALUES_ARGS="${VALUES_ARGS} -f ${CHART_DIR}/values.prod.yaml"
|
||||
SETS="--set-string gateway.image=${DEPLOY_IMAGE} --set-string gateway.tag=${TAG}"
|
||||
BUILD_PATHS="gateway"
|
||||
;;
|
||||
data-service)
|
||||
DEPLOY_IMAGE="fluxer-data-service"
|
||||
if [[ "$CHANNEL" == "stable" ]]; then
|
||||
echo "::error::data-service stable in-place upgrades are blocked. Deploy channel=canary to create the standby color, mirror writes and invalidations through API grpc_standby_host_template, then promote shards through grpc_promoted_standby_shards."
|
||||
exit 1
|
||||
fi
|
||||
RELEASE="fluxer-${SERVICE}-canary"
|
||||
SETS="--set-string dataService.name=data-service-canary --set-string dataService.image=${DEPLOY_IMAGE} --set-string dataService.tag=${TAG} --set-string dataService.configSecret=fluxer-config-shared"
|
||||
SETS="${SETS} --set-string dataService.rolloutRole=standby --set-string dataService.updateStrategy=RollingUpdate --set rolloutAdmission.enabled=false"
|
||||
BUILD_PATHS="dataService"
|
||||
;;
|
||||
worker)
|
||||
if [[ "$CHANNEL" != "stable" ]]; then
|
||||
echo "::error::Worker deployments are only supported on the stable lane."
|
||||
exit 1
|
||||
fi
|
||||
RELEASE="fluxer-${SERVICE}"
|
||||
DEPLOY_IMAGE="fluxer-api"
|
||||
VALUES_ARGS="${VALUES_ARGS} -f ${CHART_DIR}/values.prod.yaml"
|
||||
SETS="--set-string workerRealtime.image=fluxer-api --set-string workerUnfurl.image=fluxer-api --set-string workerLifecycle.image=fluxer-api --set-string workerBatch.image=fluxer-api --set-string workerRealtime.tag=${TAG} --set-string workerUnfurl.tag=${TAG} --set-string workerLifecycle.tag=${TAG} --set-string workerBatch.tag=${TAG}"
|
||||
BUILD_PATHS="workerRealtime workerUnfurl workerLifecycle workerBatch"
|
||||
;;
|
||||
messages|search|snowflakes|users|unfurl)
|
||||
if [[ "$CHANNEL" != "stable" ]]; then
|
||||
echo "::error::Shared microservice deployments are stable-only; canary traffic selection is done by the callers."
|
||||
exit 1
|
||||
fi
|
||||
DEPLOY_IMAGE="fluxer-${SERVICE}"
|
||||
RELEASE="fluxer-${SERVICE}"
|
||||
VALUES_ARGS="${VALUES_ARGS} -f ${CHART_DIR}/values.prod.yaml"
|
||||
SETS="--set-string svc.image=${DEPLOY_IMAGE} --set-string svc.tag=${TAG}"
|
||||
SETS="${SETS} --set-string svc.build.version=${BUILD_VERSION}"
|
||||
SETS="${SETS} --set-string svc.build.channel=stable"
|
||||
;;
|
||||
*)
|
||||
echo "::error::Unknown service chart: ${SERVICE}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
for BUILD_PATH in $BUILD_PATHS; do
|
||||
SETS="${SETS} --set-string ${BUILD_PATH}.build.version=${BUILD_VERSION}"
|
||||
SETS="${SETS} --set-string ${BUILD_PATH}.build.channel=${CHANNEL}"
|
||||
done
|
||||
SETS="--set-string global.registry=${GHCR_REGISTRY} ${SETS}"
|
||||
if [[ "$SERVICE" == "api" && "$CHANNEL" == "canary" ]]; then
|
||||
SYNC_WORKER_RELEASE="fluxer-worker"
|
||||
SYNC_WORKER_CHART_DIR="./deploy/helm/worker"
|
||||
SYNC_WORKER_VALUES_ARGS="-f ${SYNC_WORKER_CHART_DIR}/values.yaml -f ${SYNC_WORKER_CHART_DIR}/values.prod.yaml"
|
||||
SYNC_WORKER_SETS="--set-string workerRealtime.image=fluxer-api --set-string workerUnfurl.image=fluxer-api --set-string workerLifecycle.image=fluxer-api --set-string workerBatch.image=fluxer-api"
|
||||
SYNC_WORKER_SETS="${SYNC_WORKER_SETS} --set-string workerRealtime.tag=${TAG} --set-string workerUnfurl.tag=${TAG} --set-string workerLifecycle.tag=${TAG} --set-string workerBatch.tag=${TAG}"
|
||||
for BUILD_PATH in workerRealtime workerUnfurl workerLifecycle workerBatch; do
|
||||
SYNC_WORKER_SETS="${SYNC_WORKER_SETS} --set-string ${BUILD_PATH}.build.version=${BUILD_VERSION}"
|
||||
SYNC_WORKER_SETS="${SYNC_WORKER_SETS} --set-string ${BUILD_PATH}.build.channel=${CHANNEL}"
|
||||
done
|
||||
SYNC_WORKER_SETS="--set-string global.registry=${GHCR_REGISTRY} ${SYNC_WORKER_SETS}"
|
||||
fi
|
||||
{
|
||||
echo "chart-dir=${CHART_DIR}"
|
||||
echo "release=${RELEASE}"
|
||||
echo "values-args=${VALUES_ARGS}"
|
||||
echo "sets=${SETS}"
|
||||
echo "deploy-image=${DEPLOY_IMAGE}"
|
||||
echo "deploy-tag=${TAG}"
|
||||
echo "sync-worker-release=${SYNC_WORKER_RELEASE}"
|
||||
echo "sync-worker-chart-dir=${SYNC_WORKER_CHART_DIR}"
|
||||
echo "sync-worker-values-args=${SYNC_WORKER_VALUES_ARGS}"
|
||||
echo "sync-worker-sets=${SYNC_WORKER_SETS}"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: helm dependency update
|
||||
shell: bash
|
||||
run: |
|
||||
helm dependency update "${{ steps.helm.outputs.chart-dir }}"
|
||||
if [[ -n "${{ steps.helm.outputs.sync-worker-chart-dir }}" ]]; then
|
||||
helm dependency update "${{ steps.helm.outputs.sync-worker-chart-dir }}"
|
||||
fi
|
||||
|
||||
- name: prepare docker config
|
||||
if: steps.helm.outputs.deploy-image != ''
|
||||
shell: bash
|
||||
run: |
|
||||
echo "DOCKER_CONFIG=${RUNNER_TEMP}/docker-config" >> "$GITHUB_ENV"
|
||||
mkdir -p "${RUNNER_TEMP}/docker-config"
|
||||
|
||||
- name: configure ghcr auth
|
||||
if: steps.helm.outputs.deploy-image != ''
|
||||
shell: bash
|
||||
env:
|
||||
GHCR_USERNAME: ${{ github.actor }}
|
||||
GHCR_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
auth="$(printf '%s:%s' "$GHCR_USERNAME" "$GHCR_TOKEN" | base64 | tr -d '\n')"
|
||||
printf '{"auths":{"ghcr.io":{"auth":"%s"}}}\n' "$auth" > "$DOCKER_CONFIG/config.json"
|
||||
|
||||
- name: verify deploy image exists
|
||||
if: steps.helm.outputs.deploy-image != ''
|
||||
shell: bash
|
||||
run: |
|
||||
IMAGE_REF="${GHCR_REGISTRY}/${{ steps.helm.outputs.deploy-image }}:${{ steps.helm.outputs.deploy-tag }}"
|
||||
echo "Verifying ${IMAGE_REF}"
|
||||
docker manifest inspect "${IMAGE_REF}" > /dev/null
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: enabled
|
||||
|
||||
- name: verify api deploy uses latest image
|
||||
if: ${{ steps.helm.outputs.deploy-image == 'fluxer-api' && !inputs['allow-rollback'] }}
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GHCR_OWNER: ${{ env.GHCR_OWNER }}
|
||||
DEPLOY_TAG: ${{ steps.helm.outputs.deploy-tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
CALVER_RE='^[1-9][0-9]{3}\.[1-9][0-9]{2,3}\.(0|[1-9][0-9]{0,5})$'
|
||||
OWNER_TYPE="$(
|
||||
curl -fsS \
|
||||
-H "Authorization: Bearer ${GH_TOKEN}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"${GITHUB_API_URL:-https://api.github.com}/repos/${GITHUB_REPOSITORY}" \
|
||||
| jq -r '.owner.type'
|
||||
)"
|
||||
case "$OWNER_TYPE" in
|
||||
Organization) PACKAGE_OWNER_PATH="orgs/${GHCR_OWNER}" ;;
|
||||
User) PACKAGE_OWNER_PATH="users/${GHCR_OWNER}" ;;
|
||||
*)
|
||||
echo "::error::Unsupported GitHub owner type for package lookup: ${OWNER_TYPE}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
LATEST_TAG="$(
|
||||
curl -fsS \
|
||||
-H "Authorization: Bearer ${GH_TOKEN}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"${GITHUB_API_URL:-https://api.github.com}/${PACKAGE_OWNER_PATH}/packages/container/fluxer-api/versions?per_page=100" \
|
||||
| jq -r --arg re "$CALVER_RE" '
|
||||
[.[].metadata.container.tags[]? |
|
||||
select(test($re)) |
|
||||
{tag: ., parts: (split(".") | map(tonumber))}
|
||||
] | max_by(.parts) | .tag // empty
|
||||
'
|
||||
)"
|
||||
|
||||
if [[ -z "$LATEST_TAG" ]]; then
|
||||
echo "::error::Could not resolve the latest fluxer-api CalVer tag from GHCR."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$DEPLOY_TAG" != "$LATEST_TAG" ]]; then
|
||||
echo "::error::Refusing to deploy fluxer-api:${DEPLOY_TAG}; latest GHCR tag is fluxer-api:${LATEST_TAG}. Re-run with allow-rollback=true only for an intentional rollback."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: approve api image for admission policy
|
||||
if: ${{ inputs.service == 'api' }}
|
||||
shell: bash
|
||||
run: |
|
||||
DEPLOYMENT="api"
|
||||
if [[ "${{ inputs.channel }}" == "canary" ]]; then
|
||||
DEPLOYMENT="api-canary"
|
||||
fi
|
||||
IMAGE_REF="${GHCR_REGISTRY}/${{ steps.helm.outputs.deploy-image }}:${{ steps.helm.outputs.deploy-tag }}"
|
||||
PREVIOUS_IMAGE="$(kubectl -n fluxer get deployment "$DEPLOYMENT" -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null || true)"
|
||||
PREVIOUS_TAG=""
|
||||
if [[ -n "$PREVIOUS_IMAGE" && "$PREVIOUS_IMAGE" != "$IMAGE_REF" && "$PREVIOUS_IMAGE" == *:* ]]; then
|
||||
PREVIOUS_TAG="${PREVIOUS_IMAGE##*:}"
|
||||
else
|
||||
PREVIOUS_IMAGE=""
|
||||
fi
|
||||
kubectl -n fluxer create configmap fluxer-api-approved-image \
|
||||
--from-literal=tag="${{ steps.helm.outputs.deploy-tag }}" \
|
||||
--from-literal=image="${IMAGE_REF}" \
|
||||
--from-literal=previousTag="${PREVIOUS_TAG}" \
|
||||
--from-literal=previousImage="${PREVIOUS_IMAGE}" \
|
||||
--dry-run=client -o yaml \
|
||||
| kubectl apply -f -
|
||||
|
||||
- name: ensure api admission policy
|
||||
if: ${{ inputs.service == 'api' }}
|
||||
shell: bash
|
||||
run: kubectl apply -f deploy/k8s/fluxer-api-approved-image-policy.yaml
|
||||
|
||||
- name: helm upgrade
|
||||
shell: bash
|
||||
run: |
|
||||
RELEASE="${{ steps.helm.outputs.release }}"
|
||||
CHART_DIR="${{ steps.helm.outputs.chart-dir }}"
|
||||
VALUES_ARGS="${{ steps.helm.outputs.values-args }}"
|
||||
SETS="${{ steps.helm.outputs.sets }}"
|
||||
wait_for_release_idle() {
|
||||
local release="$1"
|
||||
local max_checks="$2"
|
||||
local check=0
|
||||
local status="unknown"
|
||||
while (( check < max_checks )); do
|
||||
check=$((check + 1))
|
||||
status=$(helm status "$release" -n fluxer -o json 2>/dev/null | jq -r '.info.status // "unknown"' || echo "unknown")
|
||||
if [[ "$status" != pending-* ]]; then
|
||||
echo "Release ${release} is ${status}; continuing."
|
||||
return 0
|
||||
fi
|
||||
echo "Release ${release} is ${status}; waiting 10s (${check}/${max_checks})."
|
||||
sleep 10
|
||||
done
|
||||
echo "::warning::Release ${release} still ${status} after ${max_checks} checks; forcing rollback."
|
||||
if helm rollback "$release" -n fluxer --wait --timeout 5m 2>&1; then
|
||||
echo "Rollback succeeded; continuing."
|
||||
return 0
|
||||
fi
|
||||
echo "::error::Release ${release} is stuck in ${status} and rollback failed."
|
||||
return 1
|
||||
}
|
||||
helm_upgrade_with_retries() {
|
||||
local release="$1"
|
||||
local chart_dir="$2"
|
||||
local values_args="$3"
|
||||
local sets="$4"
|
||||
local values_args_array=()
|
||||
local sets_array=()
|
||||
read -r -a values_args_array <<< "$values_args"
|
||||
read -r -a sets_array <<< "$sets"
|
||||
wait_for_release_idle "$release" 18
|
||||
local max_attempts=4
|
||||
for attempt in $(seq 1 "$max_attempts"); do
|
||||
echo "Running helm upgrade for ${release}, attempt ${attempt}/${max_attempts}."
|
||||
set +e
|
||||
upgrade_output=$(helm upgrade --install "$release" \
|
||||
"$chart_dir" \
|
||||
"${values_args_array[@]}" \
|
||||
-n fluxer \
|
||||
"${sets_array[@]}" \
|
||||
--wait --timeout 20m --atomic --history-max 10 2>&1)
|
||||
exit_code=$?
|
||||
set -e
|
||||
printf '%s\n' "$upgrade_output"
|
||||
if [[ $exit_code -eq 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
if ! grep -q "another operation (install/upgrade/rollback) is in progress" <<< "$upgrade_output"; then
|
||||
return "$exit_code"
|
||||
fi
|
||||
if [[ $attempt -eq $max_attempts ]]; then
|
||||
echo "::error::Helm upgrade failed for ${release} after ${max_attempts} attempts because another operation remained in progress."
|
||||
return "$exit_code"
|
||||
fi
|
||||
wait_for_release_idle "$release" 18
|
||||
done
|
||||
}
|
||||
helm_upgrade_with_retries "$RELEASE" "$CHART_DIR" "$VALUES_ARGS" "$SETS"
|
||||
if [[ -n "${{ steps.helm.outputs.sync-worker-release }}" ]]; then
|
||||
helm_upgrade_with_retries \
|
||||
"${{ steps.helm.outputs.sync-worker-release }}" \
|
||||
"${{ steps.helm.outputs.sync-worker-chart-dir }}" \
|
||||
"${{ steps.helm.outputs.sync-worker-values-args }}" \
|
||||
"${{ steps.helm.outputs.sync-worker-sets }}"
|
||||
fi
|
||||
|
||||
- name: seal api admission approved image
|
||||
if: ${{ success() && inputs.service == 'api' }}
|
||||
shell: bash
|
||||
run: |
|
||||
IMAGE_REF="${GHCR_REGISTRY}/${{ steps.helm.outputs.deploy-image }}:${{ steps.helm.outputs.deploy-tag }}"
|
||||
kubectl -n fluxer create configmap fluxer-api-approved-image \
|
||||
--from-literal=tag="${{ steps.helm.outputs.deploy-tag }}" \
|
||||
--from-literal=image="${IMAGE_REF}" \
|
||||
--from-literal=previousTag="" \
|
||||
--from-literal=previousImage="" \
|
||||
--dry-run=client -o yaml \
|
||||
| kubectl apply -f -
|
||||
|
||||
- name: notify web app canary deploy
|
||||
if: ${{ success() && inputs.service == 'app-proxy' && inputs.channel == 'canary' }}
|
||||
shell: bash
|
||||
env:
|
||||
FLUXER_WEBHOOK_URL: ${{ secrets.FLUXER_WEBHOOK_URL }}
|
||||
IMAGE_TAG: ${{ inputs['image-tag'] }}
|
||||
BUILD_VERSION: ${{ inputs['build-version'] }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -z "${FLUXER_WEBHOOK_URL:-}" ]]; then
|
||||
echo "FLUXER_WEBHOOK_URL is not set; skipping web app canary deploy notification."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
web_app_version="${BUILD_VERSION:-$IMAGE_TAG}"
|
||||
|
||||
markdown_tick=$(printf '\140')
|
||||
content=$(printf '## Canary Web App Deployed\n\nWeb app version: %s%s%s' \
|
||||
"$markdown_tick" "$web_app_version" "$markdown_tick")
|
||||
if [[ "$IMAGE_TAG" != "$web_app_version" ]]; then
|
||||
content=$(printf '%s\nContainer image tag: %s%s%s' "$content" "$markdown_tick" "$IMAGE_TAG" "$markdown_tick")
|
||||
fi
|
||||
|
||||
jq -n --arg content "$content" \
|
||||
'{content: $content, allowed_mentions: {parse: []}}' \
|
||||
| curl -fsS --retry 3 \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @- \
|
||||
"$FLUXER_WEBHOOK_URL"
|
||||
|
||||
- name: recover stuck release on failure
|
||||
if: failure() || cancelled()
|
||||
shell: bash
|
||||
run: |
|
||||
RELEASE="${{ steps.helm.outputs.release }}"
|
||||
for RELEASE in "$RELEASE" "${{ steps.helm.outputs.sync-worker-release }}"; do
|
||||
if [[ -z "$RELEASE" ]]; then
|
||||
continue
|
||||
fi
|
||||
STATUS=$(helm status "$RELEASE" -n fluxer -o json 2>/dev/null | jq -r '.info.status' 2>/dev/null || echo "unknown")
|
||||
if [[ "$STATUS" == "pending-upgrade" || "$STATUS" == "pending-install" || "$STATUS" == "pending-rollback" ]]; then
|
||||
echo "::warning::Release ${RELEASE} stuck in ${STATUS}, rolling back..."
|
||||
helm rollback "$RELEASE" -n fluxer --wait --timeout 5m || true
|
||||
fi
|
||||
done
|
||||
@@ -1,92 +0,0 @@
|
||||
name: deploy static-proxy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- fluxer_media_proxy/**
|
||||
- .github/workflows/deploy-static-proxy.yaml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
type: string
|
||||
required: false
|
||||
default: ''
|
||||
description: Optional git ref (defaults to the triggering branch)
|
||||
|
||||
concurrency:
|
||||
group: deploy-fluxer-static-proxy
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
SERVICE_NAME: fluxer-static-proxy
|
||||
IMAGE_NAME: fluxer-static-proxy
|
||||
CONTEXT_DIR: fluxer_media_proxy
|
||||
COMPOSE_STACK: fluxer-static-proxy
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy static proxy
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
RELEASE_CHANNEL: stable
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step record_deploy_commit
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Set build timestamp
|
||||
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step set_build_timestamp
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ${{ env.CONTEXT_DIR }}/Dockerfile
|
||||
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.SERVICE_NAME }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.SERVICE_NAME }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ env.DEPLOY_SHA }}
|
||||
BUILD_NUMBER=${{ github.run_number }}
|
||||
BUILD_TIMESTAMP=${{ env.BUILD_TIMESTAMP }}
|
||||
RELEASE_CHANNEL=${{ env.RELEASE_CHANNEL }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
run: python3 scripts/ci/workflows/deploy_static_proxy.py --step push_and_deploy
|
||||
@@ -0,0 +1,87 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: i18n source sync
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: i18n-source-sync
|
||||
cancel-in-progress: false
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
SOURCE_BRANCH: automation/i18n-source-catalogs
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: refresh catalogs
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step install_dependencies
|
||||
|
||||
- name: Refresh source catalogs
|
||||
run: pnpm i18n:source-sync
|
||||
|
||||
- name: Format generated catalogs
|
||||
run: pnpm biome format --write package.json packages/i18n/package.json packages/i18n/scripts/SyncStaticI18nCatalogs.ts packages/errors/src/i18n fluxer_api/pkgs/email/src/email_i18n fluxer_api/src/api/content_i18n
|
||||
|
||||
- name: Open source catalog PR
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "$(git status --porcelain -- fluxer_app/src/features/i18n/locales fluxer_marketing/locales packages/errors/src/i18n fluxer_api/pkgs/email/src/email_i18n fluxer_api/src/api/content_i18n)" ]]; then
|
||||
echo "No source catalog changes."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "fluxer-i18n-bot"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git switch -c "$SOURCE_BRANCH"
|
||||
git add fluxer_app/src/features/i18n/locales fluxer_marketing/locales packages/errors/src/i18n fluxer_api/pkgs/email/src/email_i18n fluxer_api/src/api/content_i18n
|
||||
git commit -m "i18n: refresh source catalogs"
|
||||
git fetch origin "$SOURCE_BRANCH" || true
|
||||
git push --force-with-lease="refs/heads/$SOURCE_BRANCH" origin "HEAD:$SOURCE_BRANCH"
|
||||
|
||||
pr_number="$(gh pr list --base main --head "$SOURCE_BRANCH" --state open --json number --jq '.[0].number // empty')"
|
||||
body="$(cat <<'BODY'
|
||||
Refreshes extracted i18n source catalogs and generated locale artifacts after changes on main.
|
||||
|
||||
Weblate will scan these catalog updates after this PR is merged.
|
||||
BODY
|
||||
)"
|
||||
if [[ -z "$pr_number" ]]; then
|
||||
gh pr create --base main --head "$SOURCE_BRANCH" --title "i18n: refresh source catalogs" --body "$body"
|
||||
else
|
||||
gh pr edit "$pr_number" --title "i18n: refresh source catalogs" --body "$body"
|
||||
fi
|
||||
@@ -0,0 +1,94 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: i18n Weblate PR
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: "Weblate branch to compile and open as a PR"
|
||||
required: false
|
||||
default: "weblate/translations"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: i18n-weblate-${{ github.event.inputs.branch || github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
WEBLATE_BRANCH: ${{ github.event.inputs.branch || github.ref_name }}
|
||||
|
||||
jobs:
|
||||
compile:
|
||||
name: compile Weblate catalogs
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout Weblate branch
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
with:
|
||||
ref: ${{ env.WEBLATE_BRANCH }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
|
||||
--step install_dependencies
|
||||
|
||||
- name: Compile translated catalogs
|
||||
run: pnpm i18n:weblate-compile
|
||||
|
||||
- name: Format generated catalogs
|
||||
run: pnpm biome format --write package.json packages/i18n/package.json packages/i18n/scripts/SyncStaticI18nCatalogs.ts packages/errors/src/i18n fluxer_api/pkgs/email/src/email_i18n fluxer_api/src/api/content_i18n
|
||||
|
||||
- name: Commit generated artifacts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "$(git status --porcelain -- fluxer_app/src/features/i18n/locales packages/errors/src/i18n fluxer_api/pkgs/email/src/email_i18n fluxer_api/src/api/content_i18n)" ]]; then
|
||||
echo "No generated catalog changes."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "fluxer-i18n-bot"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git add fluxer_app/src/features/i18n/locales packages/errors/src/i18n fluxer_api/pkgs/email/src/email_i18n fluxer_api/src/api/content_i18n
|
||||
git commit -m "i18n: compile Weblate catalogs"
|
||||
git push origin "HEAD:$WEBLATE_BRANCH"
|
||||
|
||||
- name: Open Weblate PR
|
||||
run: |
|
||||
set -euo pipefail
|
||||
pr_number="$(gh pr list --base main --head "$WEBLATE_BRANCH" --state open --json number --jq '.[0].number // empty')"
|
||||
body="$(cat <<'BODY'
|
||||
Pulls reviewed translation updates from Weblate and includes generated runtime artifacts.
|
||||
|
||||
Weblate project: https://weblate.fluxer.tools/projects/fluxer/
|
||||
BODY
|
||||
)"
|
||||
if [[ -z "$pr_number" ]]; then
|
||||
gh pr create --base main --head "$WEBLATE_BRANCH" --title "i18n: update translations from Weblate" --body "$body"
|
||||
else
|
||||
gh pr edit "$pr_number" --title "i18n: update translations from Weblate" --body "$body"
|
||||
fi
|
||||
@@ -1,67 +0,0 @@
|
||||
name: migrate cassandra
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- canary
|
||||
paths:
|
||||
- fluxer_devops/cassandra/migrations/**/*.cql
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: migrate-cassandra-prod
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
migrate:
|
||||
name: Run database migrations
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: pnpm
|
||||
cache-dependency-path: pnpm-lock.yaml
|
||||
|
||||
- name: Install dependencies
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step install_dependencies
|
||||
|
||||
- name: Validate migrations
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step validate_migrations
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Set up SSH tunnel for Cassandra
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step setup_tunnel --server-user ${{ secrets.SERVER_USER }} --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Test Cassandra connection
|
||||
env:
|
||||
CASSANDRA_USERNAME: ${{ secrets.CASSANDRA_USERNAME }}
|
||||
CASSANDRA_PASSWORD: ${{ secrets.CASSANDRA_PASSWORD }}
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step test_connection
|
||||
|
||||
- name: Run migrations
|
||||
env:
|
||||
CASSANDRA_USERNAME: ${{ secrets.CASSANDRA_USERNAME }}
|
||||
CASSANDRA_PASSWORD: ${{ secrets.CASSANDRA_PASSWORD }}
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step run_migrations
|
||||
|
||||
- name: Close SSH tunnel
|
||||
if: always()
|
||||
run: python3 scripts/ci/workflows/migrate_cassandra.py --step close_tunnel
|
||||
@@ -1,67 +0,0 @@
|
||||
name: promote canary -> main
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
type: boolean
|
||||
default: false
|
||||
description: "Show what would change, but don't push"
|
||||
src:
|
||||
type: string
|
||||
default: canary
|
||||
description: 'Source branch'
|
||||
dst:
|
||||
type: string
|
||||
default: main
|
||||
description: 'Destination branch'
|
||||
|
||||
concurrency:
|
||||
group: promote-${{ inputs.dst }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
promote:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Create GitHub App token
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ secrets.PROMOTE_APP_ID }}
|
||||
private-key: ${{ secrets.PROMOTE_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.src }}
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Verify ff-only + summarize
|
||||
id: verify
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/promote_canary_to_main.py
|
||||
--step verify
|
||||
--src "${{ inputs.src }}"
|
||||
--dst "${{ inputs.dst }}"
|
||||
|
||||
- name: Push fast-forward
|
||||
if: ${{ steps.verify.outputs.ahead != '0' && inputs.dry_run != true }}
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/promote_canary_to_main.py
|
||||
--step push
|
||||
--dst "${{ inputs.dst }}"
|
||||
|
||||
- name: Dry run / no-op
|
||||
if: ${{ steps.verify.outputs.ahead == '0' || inputs.dry_run == true }}
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/promote_canary_to_main.py
|
||||
--step dry_run
|
||||
--dry-run "${{ inputs.dry_run }}"
|
||||
--ahead "${{ steps.verify.outputs.ahead }}"
|
||||
@@ -1,151 +0,0 @@
|
||||
name: release livekitctl
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'livekitctl-v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Version to release (e.g., 1.0.0)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: release-livekitctl
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.24'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.goos }}/${{ matrix.goarch }}
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- goos: linux
|
||||
goarch: amd64
|
||||
- goos: linux
|
||||
goarch: arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache-dependency-path: fluxer_devops/livekitctl/go.sum
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_livekitctl.py
|
||||
--step determine_version
|
||||
--event-name "${{ github.event_name }}"
|
||||
--input-version "${{ inputs.version }}"
|
||||
--ref-name "${{ github.ref_name }}"
|
||||
|
||||
- name: Build binary
|
||||
env:
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
CGO_ENABLED: 0
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
|
||||
--step build_binary
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: livekitctl-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
path: fluxer_devops/livekitctl/livekitctl-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
retention-days: 1
|
||||
|
||||
release:
|
||||
name: Create release
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
needs: build
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Determine version
|
||||
id: version
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_livekitctl.py
|
||||
--step determine_version
|
||||
--event-name "${{ github.event_name }}"
|
||||
--input-version "${{ inputs.version }}"
|
||||
--ref-name "${{ github.ref_name }}"
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Prepare release assets
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
|
||||
--step prepare_release_assets
|
||||
|
||||
- name: Generate checksums
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
|
||||
--step generate_checksums
|
||||
--release-dir release
|
||||
|
||||
- name: Create tag (workflow_dispatch only)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: >-
|
||||
python3 ${{ github.workspace }}/scripts/ci/workflows/release_livekitctl.py
|
||||
--step create_tag
|
||||
--tag "${{ steps.version.outputs.tag }}"
|
||||
--version "${{ steps.version.outputs.version }}"
|
||||
|
||||
- name: Create GitHub release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ steps.version.outputs.tag }}
|
||||
name: livekitctl v${{ steps.version.outputs.version }}
|
||||
body: |
|
||||
## livekitctl v${{ steps.version.outputs.version }}
|
||||
|
||||
Self-hosted LiveKit bootstrap and operations CLI.
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
curl -fsSL https://fluxer.app/get/livekitctl | sudo bash
|
||||
```
|
||||
|
||||
### Manual download
|
||||
|
||||
Download the appropriate binary for your system:
|
||||
- `livekitctl-linux-amd64` - Linux x86_64
|
||||
- `livekitctl-linux-arm64` - Linux ARM64
|
||||
|
||||
Then make it executable and move to your PATH:
|
||||
```bash
|
||||
chmod +x livekitctl-linux-*
|
||||
sudo mv livekitctl-linux-* /usr/local/bin/livekitctl
|
||||
```
|
||||
|
||||
### Checksums
|
||||
|
||||
See `checksums.txt` for SHA256 checksums.
|
||||
files: |
|
||||
release/livekitctl-linux-amd64
|
||||
release/livekitctl-linux-arm64
|
||||
release/checksums.txt
|
||||
draft: false
|
||||
prerelease: false
|
||||
@@ -1,259 +0,0 @@
|
||||
name: release relay directory
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [canary]
|
||||
paths:
|
||||
- fluxer_relay_directory/**
|
||||
- .github/workflows/release-relay-directory.yaml
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: Release channel
|
||||
type: choice
|
||||
options: [stable, nightly]
|
||||
default: nightly
|
||||
required: false
|
||||
|
||||
ref:
|
||||
description: Git ref (branch, tag, or commit SHA)
|
||||
type: string
|
||||
default: ''
|
||||
required: false
|
||||
|
||||
version:
|
||||
description: Stable version (e.g. 1.0.0). Defaults to 0.0.<run_number>
|
||||
type: string
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
concurrency:
|
||||
group: release-relay-directory-${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/fluxer-relay-directory
|
||||
CHANNEL: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
|
||||
SOURCE_REF: >-
|
||||
${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.ref)
|
||||
|| ((github.event_name == 'workflow_dispatch' && github.event.inputs.channel == 'stable') && 'main')
|
||||
|| 'canary' }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: resolve build metadata
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
outputs:
|
||||
version: ${{ steps.meta.outputs.version }}
|
||||
channel: ${{ steps.meta.outputs.channel }}
|
||||
source_ref: ${{ steps.meta.outputs.source_ref }}
|
||||
sha_short: ${{ steps.meta.outputs.sha_short }}
|
||||
timestamp: ${{ steps.meta.outputs.timestamp }}
|
||||
date: ${{ steps.meta.outputs.date }}
|
||||
build_number: ${{ steps.meta.outputs.build_number }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ env.SOURCE_REF }}
|
||||
|
||||
- name: metadata
|
||||
id: meta
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_relay_directory.py
|
||||
--step metadata
|
||||
--version-input "${{ github.event.inputs.version }}"
|
||||
--channel "${{ env.CHANNEL }}"
|
||||
--source-ref "${{ env.SOURCE_REF }}"
|
||||
|
||||
build:
|
||||
name: build fluxer relay directory
|
||||
needs: meta
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
outputs:
|
||||
image_tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
image_digest: ${{ steps.build.outputs.digest }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_ref }}
|
||||
|
||||
- name: set up buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: docker metadata
|
||||
id: docker_meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=nightly,enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=nightly-${{ needs.meta.outputs.date }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=sha-${{ needs.meta.outputs.sha_short }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=stable,enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=raw,value=latest,enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=raw,value=v${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=semver,pattern={{version}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
|
||||
type=semver,pattern={{major}}.{{minor}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
|
||||
|
||||
- name: build and push
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_relay_directory/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: |
|
||||
${{ steps.docker_meta.outputs.labels }}
|
||||
org.opencontainers.image.version=v${{ needs.meta.outputs.version }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.created=${{ needs.meta.outputs.timestamp }}
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
dev.fluxer.build.channel=${{ needs.meta.outputs.channel }}
|
||||
dev.fluxer.build.number=${{ needs.meta.outputs.build_number }}
|
||||
dev.fluxer.build.sha=${{ github.sha }}
|
||||
dev.fluxer.build.short_sha=${{ needs.meta.outputs.sha_short }}
|
||||
dev.fluxer.build.date=${{ needs.meta.outputs.date }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ github.sha }}
|
||||
BUILD_NUMBER=${{ needs.meta.outputs.build_number }}
|
||||
BUILD_TIMESTAMP=${{ needs.meta.outputs.timestamp }}
|
||||
RELEASE_CHANNEL=${{ needs.meta.outputs.channel }}
|
||||
cache-from: type=gha,scope=relay-directory-${{ needs.meta.outputs.channel }}
|
||||
cache-to: type=gha,mode=max,scope=relay-directory-${{ needs.meta.outputs.channel }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
|
||||
- name: attest
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
subject-digest: ${{ steps.build.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
create-release:
|
||||
name: create release
|
||||
needs: [meta, build]
|
||||
if: |
|
||||
always() &&
|
||||
needs.meta.outputs.version != '' &&
|
||||
needs.build.result == 'success'
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_ref }}
|
||||
|
||||
- name: stable release
|
||||
if: needs.meta.outputs.channel == 'stable'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: relay-directory-v${{ needs.meta.outputs.version }}
|
||||
name: Fluxer Relay Directory v${{ needs.meta.outputs.version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
generate_release_notes: true
|
||||
body: |
|
||||
Fluxer Relay Directory
|
||||
|
||||
Pull:
|
||||
```bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${{ needs.meta.outputs.version }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
```
|
||||
|
||||
Build:
|
||||
- version: v${{ needs.meta.outputs.version }}
|
||||
- build: ${{ needs.meta.outputs.build_number }}
|
||||
- sha: ${{ github.sha }}
|
||||
- time: ${{ needs.meta.outputs.timestamp }}
|
||||
- channel: stable
|
||||
|
||||
Docs: https://docs.fluxer.app/federation
|
||||
|
||||
- name: nightly release
|
||||
if: needs.meta.outputs.channel == 'nightly'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: relay-directory-nightly-${{ needs.meta.outputs.date }}-${{ needs.meta.outputs.sha_short }}
|
||||
name: Relay Directory nightly ${{ needs.meta.outputs.date }} (${{ needs.meta.outputs.sha_short }})
|
||||
draft: false
|
||||
prerelease: true
|
||||
generate_release_notes: true
|
||||
body: |
|
||||
Nightly Fluxer Relay Directory image from canary.
|
||||
|
||||
Pull:
|
||||
```bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.meta.outputs.date }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ needs.meta.outputs.sha_short }}
|
||||
```
|
||||
|
||||
Build:
|
||||
- version: v${{ needs.meta.outputs.version }}
|
||||
- build: ${{ needs.meta.outputs.build_number }}
|
||||
- sha: ${{ github.sha }}
|
||||
- time: ${{ needs.meta.outputs.timestamp }}
|
||||
- channel: nightly
|
||||
- branch: canary
|
||||
|
||||
release-summary:
|
||||
name: release summary
|
||||
needs: [meta, build]
|
||||
if: always()
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: summary
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_relay_directory.py
|
||||
--step summary
|
||||
--build-result "${{ needs.build.result }}"
|
||||
--channel "${{ needs.meta.outputs.channel }}"
|
||||
--version "${{ needs.meta.outputs.version }}"
|
||||
--build-number "${{ needs.meta.outputs.build_number }}"
|
||||
--sha-short "${{ needs.meta.outputs.sha_short }}"
|
||||
--timestamp "${{ needs.meta.outputs.timestamp }}"
|
||||
--date-ymd "${{ needs.meta.outputs.date }}"
|
||||
--source-ref "${{ needs.meta.outputs.source_ref }}"
|
||||
--image-tags "${{ needs.build.outputs.image_tags }}"
|
||||
--image-digest "${{ needs.build.outputs.image_digest }}"
|
||||
--registry "${{ env.REGISTRY }}"
|
||||
--image-name "${{ env.IMAGE_NAME }}"
|
||||
@@ -1,259 +0,0 @@
|
||||
name: release relay
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [canary]
|
||||
paths:
|
||||
- fluxer_relay/**
|
||||
- .github/workflows/release-relay.yaml
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: Release channel
|
||||
type: choice
|
||||
options: [stable, nightly]
|
||||
default: nightly
|
||||
required: false
|
||||
|
||||
ref:
|
||||
description: Git ref (branch, tag, or commit SHA)
|
||||
type: string
|
||||
default: ''
|
||||
required: false
|
||||
|
||||
version:
|
||||
description: Stable version (e.g. 1.0.0). Defaults to 0.0.<run_number>
|
||||
type: string
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
concurrency:
|
||||
group: release-relay-${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/fluxer-relay
|
||||
CHANNEL: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
|
||||
SOURCE_REF: >-
|
||||
${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.ref)
|
||||
|| ((github.event_name == 'workflow_dispatch' && github.event.inputs.channel == 'stable') && 'main')
|
||||
|| 'canary' }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: resolve build metadata
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
outputs:
|
||||
version: ${{ steps.meta.outputs.version }}
|
||||
channel: ${{ steps.meta.outputs.channel }}
|
||||
source_ref: ${{ steps.meta.outputs.source_ref }}
|
||||
sha_short: ${{ steps.meta.outputs.sha_short }}
|
||||
timestamp: ${{ steps.meta.outputs.timestamp }}
|
||||
date: ${{ steps.meta.outputs.date }}
|
||||
build_number: ${{ steps.meta.outputs.build_number }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ env.SOURCE_REF }}
|
||||
|
||||
- name: metadata
|
||||
id: meta
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_relay.py
|
||||
--step metadata
|
||||
--version-input "${{ github.event.inputs.version }}"
|
||||
--channel "${{ env.CHANNEL }}"
|
||||
--source-ref "${{ env.SOURCE_REF }}"
|
||||
|
||||
build:
|
||||
name: build fluxer relay
|
||||
needs: meta
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
outputs:
|
||||
image_tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
image_digest: ${{ steps.build.outputs.digest }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_ref }}
|
||||
|
||||
- name: set up buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: docker metadata
|
||||
id: docker_meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=nightly,enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=nightly-${{ needs.meta.outputs.date }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=sha-${{ needs.meta.outputs.sha_short }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=stable,enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=raw,value=latest,enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=raw,value=v${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=semver,pattern={{version}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
|
||||
type=semver,pattern={{major}}.{{minor}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
|
||||
|
||||
- name: build and push
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: fluxer_relay
|
||||
file: fluxer_relay/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: |
|
||||
${{ steps.docker_meta.outputs.labels }}
|
||||
org.opencontainers.image.version=v${{ needs.meta.outputs.version }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.created=${{ needs.meta.outputs.timestamp }}
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
dev.fluxer.build.channel=${{ needs.meta.outputs.channel }}
|
||||
dev.fluxer.build.number=${{ needs.meta.outputs.build_number }}
|
||||
dev.fluxer.build.sha=${{ github.sha }}
|
||||
dev.fluxer.build.short_sha=${{ needs.meta.outputs.sha_short }}
|
||||
dev.fluxer.build.date=${{ needs.meta.outputs.date }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ github.sha }}
|
||||
BUILD_NUMBER=${{ needs.meta.outputs.build_number }}
|
||||
BUILD_TIMESTAMP=${{ needs.meta.outputs.timestamp }}
|
||||
RELEASE_CHANNEL=${{ needs.meta.outputs.channel }}
|
||||
cache-from: type=gha,scope=relay-${{ needs.meta.outputs.channel }}
|
||||
cache-to: type=gha,mode=max,scope=relay-${{ needs.meta.outputs.channel }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
|
||||
- name: attest
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
subject-digest: ${{ steps.build.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
create-release:
|
||||
name: create release
|
||||
needs: [meta, build]
|
||||
if: |
|
||||
always() &&
|
||||
needs.meta.outputs.version != '' &&
|
||||
needs.build.result == 'success'
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_ref }}
|
||||
|
||||
- name: stable release
|
||||
if: needs.meta.outputs.channel == 'stable'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: relay-v${{ needs.meta.outputs.version }}
|
||||
name: Fluxer Relay v${{ needs.meta.outputs.version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
generate_release_notes: true
|
||||
body: |
|
||||
Fluxer Relay
|
||||
|
||||
Pull:
|
||||
```bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:v${{ needs.meta.outputs.version }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
```
|
||||
|
||||
Build:
|
||||
- version: v${{ needs.meta.outputs.version }}
|
||||
- build: ${{ needs.meta.outputs.build_number }}
|
||||
- sha: ${{ github.sha }}
|
||||
- time: ${{ needs.meta.outputs.timestamp }}
|
||||
- channel: stable
|
||||
|
||||
Docs: https://docs.fluxer.app/federation
|
||||
|
||||
- name: nightly release
|
||||
if: needs.meta.outputs.channel == 'nightly'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: relay-nightly-${{ needs.meta.outputs.date }}-${{ needs.meta.outputs.sha_short }}
|
||||
name: Relay nightly ${{ needs.meta.outputs.date }} (${{ needs.meta.outputs.sha_short }})
|
||||
draft: false
|
||||
prerelease: true
|
||||
generate_release_notes: true
|
||||
body: |
|
||||
Nightly Fluxer Relay image from canary.
|
||||
|
||||
Pull:
|
||||
```bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.meta.outputs.date }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ needs.meta.outputs.sha_short }}
|
||||
```
|
||||
|
||||
Build:
|
||||
- version: v${{ needs.meta.outputs.version }}
|
||||
- build: ${{ needs.meta.outputs.build_number }}
|
||||
- sha: ${{ github.sha }}
|
||||
- time: ${{ needs.meta.outputs.timestamp }}
|
||||
- channel: nightly
|
||||
- branch: canary
|
||||
|
||||
release-summary:
|
||||
name: release summary
|
||||
needs: [meta, build]
|
||||
if: always()
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: summary
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_relay.py
|
||||
--step summary
|
||||
--build-result "${{ needs.build.result }}"
|
||||
--channel "${{ needs.meta.outputs.channel }}"
|
||||
--version "${{ needs.meta.outputs.version }}"
|
||||
--build-number "${{ needs.meta.outputs.build_number }}"
|
||||
--sha-short "${{ needs.meta.outputs.sha_short }}"
|
||||
--timestamp "${{ needs.meta.outputs.timestamp }}"
|
||||
--date-ymd "${{ needs.meta.outputs.date }}"
|
||||
--source-ref "${{ needs.meta.outputs.source_ref }}"
|
||||
--image-tags "${{ needs.build.outputs.image_tags }}"
|
||||
--image-digest "${{ needs.build.outputs.image_digest }}"
|
||||
--registry "${{ env.REGISTRY }}"
|
||||
--image-name "${{ env.IMAGE_NAME }}"
|
||||
@@ -1,278 +0,0 @@
|
||||
name: release server
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [canary]
|
||||
paths:
|
||||
- packages/**
|
||||
- fluxer_server/**
|
||||
- fluxer_gateway/**
|
||||
- pnpm-lock.yaml
|
||||
- .github/workflows/release-server.yaml
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
channel:
|
||||
description: Release channel
|
||||
type: choice
|
||||
options: [stable, nightly]
|
||||
default: nightly
|
||||
required: false
|
||||
|
||||
ref:
|
||||
description: Git ref (branch, tag, or commit SHA)
|
||||
type: string
|
||||
default: ''
|
||||
required: false
|
||||
|
||||
version:
|
||||
description: Stable version (e.g. 1.0.0). Defaults to 0.0.<run_number>
|
||||
type: string
|
||||
required: false
|
||||
|
||||
build_server:
|
||||
description: Build Fluxer Server
|
||||
type: boolean
|
||||
default: true
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
|
||||
concurrency:
|
||||
group: release-server-${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME_SERVER: ${{ github.repository_owner }}/fluxer-server
|
||||
CHANNEL: ${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.channel) || 'nightly' }}
|
||||
SOURCE_REF: >-
|
||||
${{ (github.event_name == 'workflow_dispatch' && github.event.inputs.ref)
|
||||
|| ((github.event_name == 'workflow_dispatch' && github.event.inputs.channel == 'stable') && 'main')
|
||||
|| 'canary' }}
|
||||
|
||||
jobs:
|
||||
meta:
|
||||
name: resolve build metadata
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
outputs:
|
||||
version: ${{ steps.meta.outputs.version }}
|
||||
channel: ${{ steps.meta.outputs.channel }}
|
||||
source_ref: ${{ steps.meta.outputs.source_ref }}
|
||||
sha_short: ${{ steps.meta.outputs.sha_short }}
|
||||
timestamp: ${{ steps.meta.outputs.timestamp }}
|
||||
date: ${{ steps.meta.outputs.date }}
|
||||
build_number: ${{ steps.meta.outputs.build_number }}
|
||||
build_server: ${{ steps.should_build.outputs.server }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ env.SOURCE_REF }}
|
||||
|
||||
- name: metadata
|
||||
id: meta
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_server.py
|
||||
--step metadata
|
||||
--version-input "${{ github.event.inputs.version }}"
|
||||
--channel "${{ env.CHANNEL }}"
|
||||
--source-ref "${{ env.SOURCE_REF }}"
|
||||
|
||||
- name: determine build targets
|
||||
id: should_build
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_server.py
|
||||
--step determine_build_targets
|
||||
--event-name "${{ github.event_name }}"
|
||||
--build-server-input "${{ github.event.inputs.build_server }}"
|
||||
|
||||
build-server:
|
||||
name: build fluxer server
|
||||
needs: meta
|
||||
if: needs.meta.outputs.build_server == 'true'
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
outputs:
|
||||
image_tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
image_digest: ${{ steps.build.outputs.digest }}
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_ref }}
|
||||
|
||||
- name: set up buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: docker metadata
|
||||
id: docker_meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}
|
||||
tags: |
|
||||
type=raw,value=nightly,enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=nightly-${{ needs.meta.outputs.date }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=sha-${{ needs.meta.outputs.sha_short }},enable=${{ needs.meta.outputs.channel == 'nightly' }}
|
||||
type=raw,value=stable,enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=raw,value=latest,enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=raw,value=v${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' }}
|
||||
type=semver,pattern={{version}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
|
||||
type=semver,pattern={{major}}.{{minor}},value=${{ needs.meta.outputs.version }},enable=${{ needs.meta.outputs.channel == 'stable' && !startsWith(needs.meta.outputs.version, '0.0.') }}
|
||||
|
||||
- name: build and push
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: fluxer_server/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
labels: |
|
||||
${{ steps.docker_meta.outputs.labels }}
|
||||
org.opencontainers.image.version=v${{ needs.meta.outputs.version }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.created=${{ needs.meta.outputs.timestamp }}
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
dev.fluxer.build.channel=${{ needs.meta.outputs.channel }}
|
||||
dev.fluxer.build.number=${{ needs.meta.outputs.build_number }}
|
||||
dev.fluxer.build.sha=${{ github.sha }}
|
||||
dev.fluxer.build.short_sha=${{ needs.meta.outputs.sha_short }}
|
||||
dev.fluxer.build.date=${{ needs.meta.outputs.date }}
|
||||
build-args: |
|
||||
BUILD_SHA=${{ github.sha }}
|
||||
BUILD_NUMBER=${{ needs.meta.outputs.build_number }}
|
||||
BUILD_TIMESTAMP=${{ needs.meta.outputs.timestamp }}
|
||||
RELEASE_CHANNEL=${{ needs.meta.outputs.channel }}
|
||||
cache-from: type=gha,scope=server-${{ needs.meta.outputs.channel }}
|
||||
cache-to: type=gha,mode=max,scope=server-${{ needs.meta.outputs.channel }}
|
||||
provenance: true
|
||||
sbom: true
|
||||
|
||||
- name: attest
|
||||
uses: actions/attest-build-provenance@v2
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}
|
||||
subject-digest: ${{ steps.build.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
create-release:
|
||||
name: create release
|
||||
needs: [meta, build-server]
|
||||
if: |
|
||||
always() &&
|
||||
needs.meta.outputs.version != '' &&
|
||||
(needs.build-server.result == 'success' || needs.build-server.result == 'skipped')
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ needs.meta.outputs.source_ref }}
|
||||
|
||||
- name: stable release
|
||||
if: needs.meta.outputs.channel == 'stable'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{ needs.meta.outputs.version }}
|
||||
name: Fluxer Server v${{ needs.meta.outputs.version }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
generate_release_notes: true
|
||||
body: |
|
||||
Fluxer Server
|
||||
|
||||
Pull:
|
||||
```bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:v${{ needs.meta.outputs.version }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:latest
|
||||
```
|
||||
|
||||
Build:
|
||||
- version: v${{ needs.meta.outputs.version }}
|
||||
- build: ${{ needs.meta.outputs.build_number }}
|
||||
- sha: ${{ github.sha }}
|
||||
- time: ${{ needs.meta.outputs.timestamp }}
|
||||
- channel: stable
|
||||
|
||||
Docs: https://docs.fluxer.app/self-hosting
|
||||
|
||||
- name: nightly release
|
||||
if: needs.meta.outputs.channel == 'nightly'
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: nightly-${{ needs.meta.outputs.date }}-${{ needs.meta.outputs.sha_short }}
|
||||
name: Nightly build ${{ needs.meta.outputs.date }} (${{ needs.meta.outputs.sha_short }})
|
||||
draft: false
|
||||
prerelease: true
|
||||
generate_release_notes: true
|
||||
body: |
|
||||
Nightly Fluxer Server image from canary.
|
||||
|
||||
Pull:
|
||||
```bash
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:nightly
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:nightly-${{ needs.meta.outputs.date }}
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_SERVER }}:sha-${{ needs.meta.outputs.sha_short }}
|
||||
```
|
||||
|
||||
Build:
|
||||
- version: v${{ needs.meta.outputs.version }}
|
||||
- build: ${{ needs.meta.outputs.build_number }}
|
||||
- sha: ${{ github.sha }}
|
||||
- time: ${{ needs.meta.outputs.timestamp }}
|
||||
- channel: nightly
|
||||
- branch: canary
|
||||
|
||||
release-summary:
|
||||
name: release summary
|
||||
needs: [meta, build-server]
|
||||
if: always()
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: summary
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/release_server.py
|
||||
--step summary
|
||||
--build-result "${{ needs.build-server.result }}"
|
||||
--channel "${{ needs.meta.outputs.channel }}"
|
||||
--version "${{ needs.meta.outputs.version }}"
|
||||
--build-number "${{ needs.meta.outputs.build_number }}"
|
||||
--sha-short "${{ needs.meta.outputs.sha_short }}"
|
||||
--timestamp "${{ needs.meta.outputs.timestamp }}"
|
||||
--date-ymd "${{ needs.meta.outputs.date }}"
|
||||
--source-ref "${{ needs.meta.outputs.source_ref }}"
|
||||
--image-tags "${{ needs.build-server.outputs.image_tags }}"
|
||||
--image-digest "${{ needs.build-server.outputs.image_digest }}"
|
||||
--registry "${{ env.REGISTRY }}"
|
||||
--image-name-server "${{ env.IMAGE_NAME_SERVER }}"
|
||||
@@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: repair static asset metadata
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
prefix:
|
||||
description: "S3 key prefix to repair"
|
||||
type: string
|
||||
required: false
|
||||
default: "assets/"
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
repair:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
STATIC_BUCKET: fluxer-static
|
||||
S3_ENDPOINT: https://ewr1.vultrobjects.com
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust
|
||||
uses: dtolnay/rust-toolchain@a02741459ec5e501b9843ed30b535ca0a0376ae4
|
||||
with:
|
||||
toolchain: 1.93.0
|
||||
|
||||
- name: Repair app asset metadata
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- repair-static-asset-metadata
|
||||
--bucket "${STATIC_BUCKET}"
|
||||
--prefix "${{ inputs.prefix }}"
|
||||
@@ -1,78 +0,0 @@
|
||||
name: restart gateway
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
confirmation:
|
||||
description: this will cause service interruption for all users. type RESTART to confirm.
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: restart-gateway
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
SERVICE_NAME: fluxer-gateway
|
||||
IMAGE_NAME: fluxer-gateway
|
||||
CONTEXT_DIR: fluxer_gateway
|
||||
COMPOSE_STACK: fluxer-gateway
|
||||
RELEASE_CHANNEL: ${{ github.ref_name == 'canary' && 'staging' || 'production' }}
|
||||
|
||||
jobs:
|
||||
restart:
|
||||
name: Restart gateway
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Validate confirmation
|
||||
if: ${{ github.event.inputs.confirmation != 'RESTART' }}
|
||||
run: python3 scripts/ci/workflows/restart_gateway.py --step validate_confirmation --confirmation "${{ github.event.inputs.confirmation }}"
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Record deploy commit
|
||||
run: python3 scripts/ci/workflows/restart_gateway.py --step record_deploy_commit
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Build image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ${{ env.CONTEXT_DIR }}
|
||||
file: ${{ env.CONTEXT_DIR }}/Dockerfile
|
||||
tags: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
load: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=${{ env.SERVICE_NAME }}
|
||||
cache-to: type=gha,mode=max,scope=${{ env.SERVICE_NAME }}
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
- name: Install docker-pussh
|
||||
run: python3 scripts/ci/workflows/restart_gateway.py --step install_docker_pussh
|
||||
|
||||
- name: Set up SSH agent
|
||||
uses: webfactory/ssh-agent@v0.9.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_SERVER }}
|
||||
|
||||
- name: Add server to known hosts
|
||||
run: python3 scripts/ci/workflows/restart_gateway.py --step add_known_hosts --server-ip ${{ secrets.SERVER_IP }}
|
||||
|
||||
- name: Push image and deploy
|
||||
env:
|
||||
IMAGE_TAG: ${{ env.IMAGE_NAME }}:${{ env.DEPLOY_SHA }}
|
||||
SERVER: ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}
|
||||
run: python3 scripts/ci/workflows/restart_gateway.py --step push_and_deploy
|
||||
@@ -1,102 +0,0 @@
|
||||
name: sync desktop
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- canary
|
||||
paths:
|
||||
- 'fluxer_desktop/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: Branch to sync (main or canary)
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: sync-desktop-${{ github.ref_name }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
name: Sync to fluxerapp/fluxer_desktop
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
|
||||
steps:
|
||||
- name: Checkout CI scripts
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
sparse-checkout: scripts/ci
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: Create GitHub App token
|
||||
id: app-token
|
||||
uses: actions/create-github-app-token@v2
|
||||
with:
|
||||
app-id: ${{ secrets.SYNC_APP_ID }}
|
||||
private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }}
|
||||
owner: fluxerapp
|
||||
repositories: fluxer_desktop
|
||||
|
||||
- name: Get GitHub App user ID
|
||||
id: get-user-id
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step get_user_id
|
||||
--app-slug "${{ steps.app-token.outputs.app-slug }}"
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
- name: Checkout source repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: source
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Determine target branch
|
||||
id: branch
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step determine_branch
|
||||
--input-branch "${{ inputs.branch }}"
|
||||
--ref-name "${{ github.ref_name }}"
|
||||
|
||||
- name: Clone target repository
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step clone_target
|
||||
--token "${{ steps.app-token.outputs.token }}"
|
||||
|
||||
- name: Configure git
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step configure_git
|
||||
--app-slug "${{ steps.app-token.outputs.app-slug }}"
|
||||
--user-id "${{ steps.get-user-id.outputs.user-id }}"
|
||||
|
||||
- name: Checkout or create target branch
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step checkout_or_create_branch
|
||||
--branch-name "${{ steps.branch.outputs.name }}"
|
||||
|
||||
- name: Sync files
|
||||
run: python3 scripts/ci/workflows/sync_desktop.py --step sync_files
|
||||
|
||||
- name: Commit and push
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step commit_and_push
|
||||
--branch-name "${{ steps.branch.outputs.name }}"
|
||||
|
||||
- name: Summary
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/sync_desktop.py
|
||||
--step summary
|
||||
--branch-name "${{ steps.branch.outputs.name }}"
|
||||
@@ -0,0 +1,41 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: sync static bucket
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
STATIC_BUCKET: fluxer-static
|
||||
S3_ENDPOINT: https://ewr1.vultrobjects.com
|
||||
S3_WRITE_CONCURRENCY: 8
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust
|
||||
uses: dtolnay/rust-toolchain@a02741459ec5e501b9843ed30b535ca0a0376ae4
|
||||
with:
|
||||
toolchain: 1.93.0
|
||||
|
||||
- name: Append static assets to S3
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- sync-static-bucket
|
||||
--source fluxer_static
|
||||
--bucket "${STATIC_BUCKET}"
|
||||
|
||||
- name: Repair app asset metadata
|
||||
run: >-
|
||||
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- repair-static-asset-metadata
|
||||
--bucket "${STATIC_BUCKET}"
|
||||
--prefix assets/
|
||||
@@ -1,42 +0,0 @@
|
||||
name: sync static-bucket
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'fluxer_static/**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: sync-fluxer-static
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
RCLONE_REMOTE: ovh
|
||||
RCLONE_BUCKET: fluxer-static
|
||||
RCLONE_SOURCE: fluxer_static
|
||||
RCLONE_ENDPOINT: https://s3.us-east-va.io.cloud.ovh.us
|
||||
RCLONE_REGION: us-east-1
|
||||
RCLONE_SOURCE_DIR: fluxer_static
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
lfs: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install rclone
|
||||
run: python3 scripts/ci/workflows/sync_static.py --step install_rclone
|
||||
|
||||
- name: Push repo contents to bucket
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
run: python3 scripts/ci/workflows/sync_static.py --step push
|
||||
@@ -1,90 +0,0 @@
|
||||
name: test cassandra-backup
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 */2 * * *'
|
||||
|
||||
concurrency:
|
||||
group: test-cassandra-backup
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-backup:
|
||||
name: Test latest Cassandra backup
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 45
|
||||
|
||||
env:
|
||||
CASSANDRA_IMAGE: cassandra:5.0.6
|
||||
CASS_CONTAINER: cass-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
UTIL_CONTAINER: cass-util-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
CASS_VOLUME: cassandra-data-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
BACKUP_VOLUME: cassandra-backup-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
MAX_HEAP_SIZE: 2G
|
||||
HEAP_NEWSIZE: 512M
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set temp paths
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step set_temp_paths
|
||||
|
||||
- name: Pre-clean
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step pre_clean
|
||||
|
||||
- name: Install tools
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step install_tools
|
||||
|
||||
- name: Find latest backup, validate freshness, download, decrypt, extract into Docker volume
|
||||
env:
|
||||
B2_KEY_ID: ${{ secrets.B2_KEY_ID }}
|
||||
B2_APPLICATION_KEY: ${{ secrets.B2_APPLICATION_KEY }}
|
||||
AGE_PRIVATE_KEY: ${{ secrets.CASSANDRA_AGE_PRIVATE_KEY }}
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step fetch_backup
|
||||
|
||||
- name: Create data volume
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step create_data_volume
|
||||
|
||||
- name: Restore keyspaces into volume and promote snapshot SSTables
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step restore_keyspaces
|
||||
|
||||
- name: Start Cassandra
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step start_cassandra
|
||||
|
||||
- name: Verify data
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step verify_data
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step cleanup
|
||||
|
||||
- name: Report status
|
||||
if: always()
|
||||
env:
|
||||
JOB_STATUS: ${{ job.status }}
|
||||
run: >-
|
||||
python3 scripts/ci/workflows/test_cassandra_backup.py
|
||||
--step report_status
|
||||
@@ -1,57 +0,0 @@
|
||||
name: update word-lists
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 1 * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-word-lists:
|
||||
runs-on: blacksmith-8vcpu-ubuntu-2404
|
||||
timeout-minutes: 25
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: canary
|
||||
|
||||
- name: Download latest word lists
|
||||
run: python3 scripts/ci/workflows/update_word_lists.py --step download
|
||||
|
||||
- name: Check for changes
|
||||
id: check_changes
|
||||
run: python3 scripts/ci/workflows/update_word_lists.py --step check_changes
|
||||
|
||||
- name: Update word lists
|
||||
if: steps.check_changes.outputs.changes_detected == 'true'
|
||||
run: python3 scripts/ci/workflows/update_word_lists.py --step update
|
||||
|
||||
- name: Create pull request for updated word lists
|
||||
if: steps.check_changes.outputs.changes_detected == 'true'
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: word-lists-update-${{ github.run_id }}
|
||||
base: canary
|
||||
title: 'chore: update word lists from Tailscale upstream'
|
||||
body: |
|
||||
Automated update of scales.txt and tails.txt from the Tailscale repository.
|
||||
|
||||
These files are used to generate connection IDs for voice connections.
|
||||
|
||||
Source:
|
||||
- https://github.com/tailscale/tailscale/blob/main/words/scales.txt
|
||||
- https://github.com/tailscale/tailscale/blob/main/words/tails.txt
|
||||
commit-message: 'chore: update word lists from Tailscale upstream'
|
||||
files: |
|
||||
fluxer_api/src/words/scales.txt
|
||||
fluxer_api/src/words/tails.txt
|
||||
labels: automation
|
||||
|
||||
- name: No changes detected
|
||||
if: steps.check_changes.outputs.changes_detected == 'false'
|
||||
run: python3 scripts/ci/workflows/update_word_lists.py --step no_changes
|
||||
+36
-14
@@ -6,7 +6,12 @@
|
||||
**/*.iml
|
||||
**/*.log
|
||||
**/*.o
|
||||
**/*.node
|
||||
**/*.plt
|
||||
**/*.so
|
||||
**/*.so.*
|
||||
!fluxer_desktop/native/webrtc-sender/vendor/webrtc-sys/src/lazy_load_deps_for/**/*.so.init.c
|
||||
!fluxer_desktop/native/webrtc-sender/vendor/webrtc-sys/src/lazy_load_deps_for/**/*.so.tramp.S
|
||||
**/*.source
|
||||
**/*.swo
|
||||
**/*.swp
|
||||
@@ -41,7 +46,6 @@ devenv.local.nix
|
||||
**/.rebar3
|
||||
**/.source
|
||||
**/.swc
|
||||
**/.turbo
|
||||
**/.vercel
|
||||
**/_build
|
||||
**/_checkouts
|
||||
@@ -51,6 +55,7 @@ devenv.local.nix
|
||||
**/dist
|
||||
**/ebin
|
||||
**/erl_crash.dump
|
||||
/erl_crash.dump
|
||||
**/fluxer.env
|
||||
**/generated
|
||||
**/log
|
||||
@@ -69,27 +74,44 @@ devenv.local.nix
|
||||
/.devserver-cache.json
|
||||
**/.devserver-cache.json
|
||||
/.fluxer/
|
||||
/config/config.json
|
||||
/fluxer_app/src/assets/emoji-sprites/
|
||||
/fluxer_app/src/components/uikit/AvatarStatusGeometry.ts
|
||||
/fluxer_app/src/components/uikit/SVGMasks.tsx
|
||||
/fluxer_app/src/locales/*/messages.js
|
||||
/fluxer_app/src/locales/*/messages.mjs
|
||||
/fluxer_app/src/locales/*/messages.ts
|
||||
/fluxer_admin/public/static/app.css
|
||||
/scripts/remote/hosts.json
|
||||
/config/env/local.env
|
||||
/fluxer_app/src/features/ui/constants/AvatarStatusGeometry.ts
|
||||
/fluxer_app/src/features/ui/components/SVGMasks.tsx
|
||||
/fluxer_app/src/features/i18n/locales/*/messages.js
|
||||
/fluxer_app/src/features/i18n/locales/*/messages.mjs
|
||||
/fluxer_app/src/features/i18n/locales/*/messages.ts
|
||||
/fluxer_app/pkgs/libfluxcore/
|
||||
/fluxer_gateway/config/sys.config
|
||||
/fluxer_gateway/config/vm.args
|
||||
/fluxer_marketing/public/static/app.css
|
||||
/fluxer_server/data/
|
||||
/packages/admin/public/static/app.css
|
||||
/packages/marketing/public/static/app.css
|
||||
/packages/config/src/ConfigSchema.json
|
||||
/packages/config/src/MasterZodSchema.generated.tsx
|
||||
AGENTS.md
|
||||
CLAUDE.md
|
||||
AGENTS.md
|
||||
fluxer.yaml
|
||||
GEMINI.md
|
||||
geoip_data
|
||||
tmp/
|
||||
next-env.d.ts
|
||||
deploy/kubeconfig/
|
||||
/deploy/helm/**/Chart.lock
|
||||
/deploy/helm/**/charts/
|
||||
.github/agents
|
||||
.github/prompts
|
||||
|
||||
**/public/static/app.css
|
||||
**/public/static/app.*.css
|
||||
**/public/static/tailwind.css
|
||||
**/public/static/tailwind.*.css
|
||||
|
||||
**/zig-out/
|
||||
**/.zig-cache/
|
||||
fluxer_media_proxy/bench-results/
|
||||
fluxer_media_proxy/.benchmark-cache/
|
||||
.claude/
|
||||
|
||||
# Generated by tools/ci build-desktop --step set_build_channel
|
||||
fluxer_desktop/src/common/BuildChannel.ts
|
||||
|
||||
# Generated by tools/ci build-markdown-parser-wasm
|
||||
fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[submodule "fluxer_static"]
|
||||
path = fluxer_static
|
||||
url = https://github.com/fluxerapp/static.git
|
||||
@@ -16,6 +16,7 @@
|
||||
**/*~
|
||||
**/.*cache
|
||||
**/.cache
|
||||
**/.claude
|
||||
**/__pycache__
|
||||
**/.dev.vars
|
||||
**/.direnv
|
||||
@@ -34,7 +35,6 @@
|
||||
**/.rebar3
|
||||
**/.source
|
||||
**/.swc
|
||||
**/.turbo
|
||||
**/.vercel
|
||||
**/_build
|
||||
**/_checkouts
|
||||
@@ -65,7 +65,6 @@
|
||||
fluxer.yaml
|
||||
fluxer_app/dist/
|
||||
/fluxer_marketing/public/static/app.css
|
||||
/fluxer_server/data/
|
||||
fluxer_static
|
||||
geoip_data
|
||||
livekit.yaml
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
**/.cache
|
||||
**/.pnpm-store
|
||||
**/.swc
|
||||
**/.turbo
|
||||
**/node_modules
|
||||
**/package-lock.json
|
||||
**/pnpm-lock.yaml
|
||||
|
||||
Vendored
-10
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"TypeScriptTeam.native-preview",
|
||||
"biomejs.biome",
|
||||
"clinyong.vscode-css-modules",
|
||||
"pgourlain.erlang",
|
||||
"golang.go",
|
||||
"rust-lang.rust-analyzer"
|
||||
]
|
||||
}
|
||||
Vendored
-84
@@ -1,84 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug: fluxer_server",
|
||||
"program": "${workspaceFolder}/fluxer_server/src/startServer.tsx",
|
||||
"runtimeArgs": ["--import", "tsx"],
|
||||
"cwd": "${workspaceFolder}/fluxer_server",
|
||||
"env": {
|
||||
"FLUXER_CONFIG": "${workspaceFolder}/config/config.json",
|
||||
"FLUXER_DATABASE": "sqlite"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug: fluxer_api (standalone)",
|
||||
"program": "${workspaceFolder}/fluxer_api/src/AppEntrypoint.tsx",
|
||||
"runtimeArgs": ["--import", "tsx"],
|
||||
"cwd": "${workspaceFolder}/fluxer_api",
|
||||
"env": {
|
||||
"FLUXER_CONFIG": "${workspaceFolder}/config/config.json",
|
||||
"FLUXER_DATABASE": "sqlite"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug: fluxer_marketing",
|
||||
"program": "${workspaceFolder}/fluxer_marketing/src/index.tsx",
|
||||
"runtimeArgs": ["--import", "tsx"],
|
||||
"cwd": "${workspaceFolder}/fluxer_marketing",
|
||||
"env": {
|
||||
"FLUXER_CONFIG": "${workspaceFolder}/config/config.json"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug: fluxer_app (DevServer)",
|
||||
"program": "${workspaceFolder}/fluxer_app/scripts/DevServer.tsx",
|
||||
"runtimeArgs": ["--import", "tsx"],
|
||||
"cwd": "${workspaceFolder}/fluxer_app",
|
||||
"env": {
|
||||
"FLUXER_APP_DEV_PORT": "49427",
|
||||
"FORCE_COLOR": "1"
|
||||
},
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug: Test Current File",
|
||||
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
|
||||
"args": ["run", "--no-coverage", "${relativeFile}"],
|
||||
"autoAttachChildProcesses": true,
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach to Node Process",
|
||||
"port": 9229,
|
||||
"restart": true,
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Debug: Server + App",
|
||||
"configurations": ["Debug: fluxer_server", "Debug: fluxer_app (DevServer)"]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"typescript.preferences.includePackageJsonAutoImports": "auto",
|
||||
"typescript.suggest.autoImports": true,
|
||||
"typescript.experimental.useTsgo": true
|
||||
}
|
||||
+4
-145
@@ -1,148 +1,7 @@
|
||||
# Contributing to Fluxer
|
||||
# Contributing
|
||||
|
||||
Thanks for contributing. This document explains how we work so your changes can land smoothly and nobody wastes time on work we can't merge.
|
||||
Understand every change in your PR. You should be able to explain what it does and why it is correct.
|
||||
|
||||
## Quick rules (please read)
|
||||
Keep AI-generated text out of bug reports, pull request descriptions, and GitHub comments, except for direct translation if English is not your native language.
|
||||
|
||||
### 1) All PRs must target `canary`
|
||||
|
||||
`canary` is our trunk branch. Open all pull requests against `canary`. PRs targeting other branches will be closed or retargeted.
|
||||
|
||||
### 2) All PRs must include a short description
|
||||
|
||||
Every PR must include a short description covering:
|
||||
|
||||
- what changed
|
||||
- why it changed
|
||||
- anything reviewers should pay attention to
|
||||
|
||||
A few bullets is fine.
|
||||
|
||||
### 3) Open an issue before submitting a PR
|
||||
|
||||
We strongly prefer that every PR addresses an existing issue. If one doesn't exist yet, open one describing the problem or improvement and your proposed approach. This gives maintainers a chance to weigh in on direction before you invest time, and avoids the mutual displeasure of:
|
||||
|
||||
- you doing significant work, and
|
||||
- us having to reject or postpone the change because it doesn't align with current goals, or because we aren't ready to maintain what it introduces
|
||||
|
||||
For small, obvious fixes (typos, broken links, trivial one-liners) you can skip the issue and go straight to a PR.
|
||||
|
||||
Ways to coordinate on larger work:
|
||||
|
||||
- open an issue describing the problem and your proposed approach
|
||||
- open a draft PR early to confirm direction
|
||||
- discuss with a maintainer in any channel you already share
|
||||
|
||||
If you're unsure whether something needs an issue first, it probably does.
|
||||
|
||||
### 4) Understand the code you submit
|
||||
|
||||
You should understand every change in your PR well enough to explain and defend it during review. You don’t need to write an essay, but you should be able to give a brief summary of what the patch does and why it’s correct. You may not use AI to generate a bug report, pull request description, or GitHub comment in any form, except for a 1:1 translation if English isn't your native language.
|
||||
|
||||
The maintainer [uses LLMs in a limited capacity](https://blog.fluxer.app/how-i-built-fluxer-a-discord-like-chat-app/#:~:text=The%20LLMephant%20in%20the%20room). That’s how he was able to build the final version of Fluxer largely on his own over five years, with help from a supportive group of early testers. Without limited, controlled LLM use, he likely would have needed more starting capital to achieve the same result and hire a team of engineers.
|
||||
|
||||
If you use LLMs, use them responsibly. They can be helpful for rubber-ducking and for scaffolding boilerplate from thorough specifications, detailed guidance, and test coverage that verifies behaviour rather than implementation. This kind of platform cannot be built via autonomous code generation. Please disclose any LLM usage in your contribution.
|
||||
|
||||
We also ask contributors to treat each other with respect on this topic. People hold a wide range of views on LLMs, often rooted in ethical conviction. A contribution that is reviewable, understandable, and properly tested should be evaluated on its merits.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Fork the repo (or create a branch if you have access).
|
||||
2. Create a feature branch from `canary`.
|
||||
3. Make changes.
|
||||
4. Open a PR into `canary` with a short description.
|
||||
5. Address review feedback and CI results.
|
||||
6. We squash-merge approved PRs into `canary`.
|
||||
|
||||
We strongly prefer small, focused PRs that are easy to review.
|
||||
|
||||
### Commit style and history
|
||||
|
||||
We squash-merge PRs, so the PR title becomes the single commit message on `canary`. For that reason:
|
||||
|
||||
- PR titles must follow Conventional Commits.
|
||||
- Individual commits inside the PR don't need to follow Conventional Commits.
|
||||
|
||||
If you like to commit in small increments, feel free. If you prefer a tidier PR history, force-pushes are welcome (for example, to squash or reorder commits before review). Just avoid rewriting history in a way that makes it hard for reviewers to follow along.
|
||||
|
||||
## Conventional Commits (required for PR titles)
|
||||
|
||||
Because the PR title becomes the squash commit message, we require Conventional Commits for PR titles.
|
||||
|
||||
We prefer type/subject to be mostly lowercase.
|
||||
|
||||
Format:
|
||||
|
||||
- `type(scope optional): short description`
|
||||
|
||||
Examples:
|
||||
|
||||
- `fix: handle empty response from api`
|
||||
- `feat(auth): add passkey login`
|
||||
- `docs: clarify canary workflow`
|
||||
- `refactor: simplify retry logic`
|
||||
- `chore(ci): speed up checks`
|
||||
|
||||
Breaking changes:
|
||||
|
||||
- `feat!: remove legacy auth endpoints`
|
||||
- `refactor(api)!: change pagination shape`
|
||||
|
||||
Common types:
|
||||
`feat`, `fix`, `docs`, `refactor`, `perf`, `test`, `chore`, `ci`, `build`, `revert`
|
||||
|
||||
## Tests (guidance)
|
||||
|
||||
We care about confidence more than ceremony. Add tests when they provide real value.
|
||||
|
||||
### Backend changes
|
||||
|
||||
For backend changes, add a unit test.
|
||||
|
||||
- If a unit test would require heavy mocking to be meaningful, restructure the code so it can be tested cleanly through its interfaces.
|
||||
- If you're unsure how to approach this, discuss it with a maintainer before investing time.
|
||||
|
||||
### Frontend changes
|
||||
|
||||
We don't generally encourage new unit tests for frontend code unless:
|
||||
|
||||
- the area already has unit tests, or
|
||||
- the change is complex or sensitive, and a unit test clearly reduces risk
|
||||
|
||||
In most cases, clear PR notes and practical verification are more valuable.
|
||||
|
||||
## Formatting and linting
|
||||
|
||||
Don't block on formatting or linting before opening a PR. CI enforces required checks and will tell you what needs fixing before merge.
|
||||
|
||||
Open the PR when it's ready for review, then iterate based on CI and feedback.
|
||||
|
||||
## PR checklist
|
||||
|
||||
Before requesting review:
|
||||
|
||||
- [ ] PR targets `canary`
|
||||
- [ ] PR title follows Conventional Commits (mostly lowercase)
|
||||
- [ ] PR includes a short description of what/why
|
||||
- [ ] You understand every change in the PR and can explain it during review
|
||||
- [ ] Tests added or updated where it makes sense (especially backend changes)
|
||||
- [ ] CI is green (or you're actively addressing failures)
|
||||
|
||||
Optional but helpful:
|
||||
|
||||
- screenshots or a short recording for UI changes
|
||||
- manual verification steps
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project follows a Code of Conduct. By participating, you're expected to uphold it:
|
||||
|
||||
- See [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md)
|
||||
|
||||
## Security
|
||||
|
||||
Please don't report security issues via public GitHub issues.
|
||||
|
||||
Use our security policy and reporting instructions here:
|
||||
|
||||
- https://fluxer.app/security
|
||||
If you use LLMs for coding help, disclose it. The contribution still needs to be understandable, reviewable, and tested well.
|
||||
|
||||
Generated
+6732
File diff suppressed because it is too large
Load Diff
+29
@@ -0,0 +1,29 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"fluxer_admin",
|
||||
"fluxer_app_proxy",
|
||||
"fluxer_common",
|
||||
"fluxer_marketing",
|
||||
"fluxer_media_proxy",
|
||||
"fluxer_svc",
|
||||
"fluxer_messages",
|
||||
"fluxer_snowflakes",
|
||||
"tools/ci",
|
||||
"tools/content/update-frozen-snapshot",
|
||||
"tools/dev",
|
||||
"tools/i18n_auto",
|
||||
"tools/marketing/update-gettext-catalogs",
|
||||
"fluxer_users",
|
||||
"fluxer_unfurl",
|
||||
"packages/markdown_parser/rust",
|
||||
]
|
||||
exclude = [
|
||||
"packages/markdown_parser/rust/fuzz",
|
||||
"fluxer_desktop/native/webrtc-sender/vendor/tract-linalg-0.19.16",
|
||||
"fluxer_desktop/native/webrtc-sender/vendor/tract-linalg-0.23.1",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
license = "AGPL-3.0-or-later"
|
||||
@@ -1,43 +0,0 @@
|
||||
# Licensing
|
||||
|
||||
Fluxer is licensed under the **GNU Affero General Public License v3.0 (AGPLv3)**. See [`LICENSE`](./LICENSE).
|
||||
|
||||
AGPLv3 is a strong copyleft licence designed to keep improvements available to the community, including when the software is used over a network.
|
||||
|
||||
## Self-hosting: fully unlocked
|
||||
|
||||
If you self-host Fluxer on your own hardware, all features are available by default. We don't charge to unlock functionality, remove limits, or increase instance caps for deployments you run yourself.
|
||||
|
||||
If Fluxer is useful to you, please consider [donating to support development](https://fluxer.app/donate).
|
||||
|
||||
## Commercial licensing
|
||||
|
||||
Some organisations can't use AGPLv3 due to policy or compliance requirements, or because they don't want to take on AGPL obligations for private modifications.
|
||||
|
||||
In these cases, Fluxer Platform AB can offer Fluxer under a separate commercial licence (sometimes called dual licensing). This is the same software, but the commercial terms remove AGPLv3's copyleft obligations for internal deployments.
|
||||
|
||||
Fluxer remains AGPLv3 and publicly available. The only difference is your obligations for private modifications. Under the commercial licence, you may keep internal modifications private rather than being required to publish them solely because you run the modified software.
|
||||
|
||||
A core requirement of the commercial licence is internal use only. You may not redistribute a modified version (or your modifications) to third parties under the commercial licence.
|
||||
|
||||
If you want to share changes, you can upstream them to this repository under Fluxer's AGPLv3 licence. The commercial licence makes upstreaming optional rather than required, but it doesn't grant permission to distribute modifications under any other licence.
|
||||
|
||||
To request a commercial licence, email [support@fluxer.app](mailto:support@fluxer.app) and include your employee count so we can provide an initial estimate. Commercial licences are offered at a custom price point.
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
Code contributions require a signed contributor licence agreement: see [`CLA.md`](./CLA.md). You will be prompted to sign electronically via CLA Assistant when you open your first pull request.
|
||||
|
||||
Our CLA is based on the widely used Harmony Individual CLA. It is intended to be clear and fair:
|
||||
|
||||
- You keep ownership of your contribution and can still use it elsewhere.
|
||||
- You grant Fluxer Platform AB the rights needed to distribute your contribution as part of Fluxer, including a patent licence to reduce patent-related risk for users.
|
||||
- It includes standard warranty and liability disclaimers that protect contributors.
|
||||
|
||||
It also includes an outbound licensing clause. If Fluxer Platform AB relicenses your contribution (including commercially), Fluxer Platform AB will continue to license your contribution under the project licence(s) that applied when you contributed. Signing the CLA doesn't remove Fluxer from the community.
|
||||
|
||||
## Our FOSS commitment
|
||||
|
||||
Fluxer is committed to remaining 100% FOSS for public development and distribution.
|
||||
|
||||
The CLA doesn't change that. It ensures Fluxer Platform AB has the legal permission to offer a commercial licence to organisations that need different terms, while keeping the community version open, fully featured, and AGPLv3-licensed.
|
||||
@@ -1,29 +1,20 @@
|
||||
> [!CAUTION]
|
||||
> I'm repeating it again: Holy smokes, what a ride. Fluxer is taking off much earlier than I'd expected.
|
||||
> As of this writing (15 June 2026), we are working to finalise the API and self-hosting documentation over the next few days.
|
||||
>
|
||||
> I know it's hard to resist, but please wait a little longer before you dive deep into the current codebase or try to set up self-hosting. I'm aware the current stack isn't very lightweight. I'm working on making self-hosting as straightforward as possible and the development environment likewise.
|
||||
> We apologise for the brief delay in open-source releases. We paused after spam waves created safety concerns while we built out Fluxer's trust and safety infrastructure. During that same stretch, we have been fixing hundreds of bugs, adding new features, and preparing a much improved audio and video system.
|
||||
>
|
||||
> Self-hosted deployments won't include any traces of Plutonium, and nothing is paywalled. You can still configure your own tiers and limits in the admin panel.
|
||||
>
|
||||
> Thanks for bearing with me. Development on Fluxer is about to get much easier, and the project will be made sustainable through community contributions and bounties for development work. Stay tuned – there's not much left now.
|
||||
>
|
||||
> I thought I could take it a bit easier while shipping this stabilising update, but Discord's announcement in Februrary has changed things.
|
||||
>
|
||||
> There's just been a lot of work involved in keeping the production deployment up and running, handling trust & safety concerns, answering support emails, handling billing issues, and working on the refactor at the same time. I'm really excited to open up development and make it easier for others to contribute, and I can't wait to see what the community builds on Fluxer!
|
||||
>
|
||||
> As soon as the refactor is ready (not much longer now!), I'll enable PRs and interact more actively and push updates to this repository more frequently. The remaining parts of the refactor are currently being worked on and being tested live in production that has over 125,000 users (and we're only two full-time employees for now). After that, all work will happen openly in public.
|
||||
>
|
||||
> The team is also growing, though we remain small and can't offer very competitive salaries just yet – but if you want to work part-time or contract on projects, or you think you're a great fit for the roles we're hiring for (though not as actively across all roles at this time, but we'll keep you on file for when we are), check out the [careers page](https://fluxer.app/careers) :D
|
||||
>
|
||||
> ❤️
|
||||
> You can already try that work in the Fluxer Canary client: [download Canary](https://canary.fluxer.app/download) or [open Canary on the web](https://web.canary.fluxer.app). The latest stable client remains out of date for now, but over the coming weeks we are finalising the remaining work needed to stabilise the current latest code out in the open.
|
||||
|
||||
> [!NOTE]
|
||||
> Learn about the developer behind Fluxer, the goals of the project, the tech stack, and what's coming next.
|
||||
>
|
||||
> [Read the launch blog post](https://blog.fluxer.app/how-i-built-fluxer-a-discord-like-chat-app/) · [View full roadmap](https://blog.fluxer.app/roadmap-2026/)
|
||||
> [Read the launch blog post](https://blog.fluxer.app/how-i-built-fluxer-a-discord-like-chat-app/) | [View full roadmap](https://blog.fluxer.app/roadmap-2026/)
|
||||
|
||||
<p align="center">
|
||||
<img src="./media/logo-graphic.png" alt="Fluxer graphic logo" width="400">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="./fluxer_static/marketing/branding/logo-white.svg">
|
||||
<img src="./fluxer_static/marketing/branding/logo-color.svg" alt="Fluxer logo" width="400">
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -37,153 +28,8 @@
|
||||
|
||||
# Fluxer
|
||||
|
||||
Fluxer is a **free and open source instant messaging and VoIP platform** for friends, groups, and communities. Self-host it and every feature is unlocked.
|
||||
Fluxer is a free and open source instant messaging and VoIP chat app built for friends, groups, and communities.
|
||||
|
||||
## Quick links
|
||||
|
||||
- [Self-hosting guide](https://docs.fluxer.app/self-hosting)
|
||||
- [Documentation](https://docs.fluxer.app)
|
||||
- [Donate to support development](https://fluxer.app/donate)
|
||||
- [Security](https://fluxer.app/security)
|
||||
|
||||
## Features
|
||||
|
||||
<img src="./media/app-showcase.png" alt="Fluxer showcase" align="right" width="45%" />
|
||||
|
||||
**Real-time messaging** – typing indicators, reactions, and threaded replies.
|
||||
|
||||
**Voice & video** – calls in communities and DMs with screen sharing, powered by LiveKit.
|
||||
|
||||
**Rich media** – link previews, image and video attachments, and GIF search via KLIPY.
|
||||
|
||||
**Communities and channels** – text and voice channels organised into categories with granular permissions.
|
||||
|
||||
**Custom expressions** – upload custom emojis and stickers for your community.
|
||||
|
||||
**Self-hostable** – run your own instance with full control of your data and no vendor lock-in.
|
||||
|
||||
> [!NOTE]
|
||||
> Native mobile apps and federation are top priorities. If you'd like to support this work, [donations](https://fluxer.app/donate) are greatly appreciated. You can also share feedback by emailing developers@fluxer.app.
|
||||
|
||||
## Self-hosting
|
||||
|
||||
> [!NOTE]
|
||||
> New to Fluxer? Follow the [self-hosting guide](https://docs.fluxer.app/self-hosting) for step-by-step setup instructions.
|
||||
|
||||
TBD
|
||||
|
||||
### Deployment helpers
|
||||
|
||||
- [`livekitctl`](./fluxer_devops/livekitctl/README.md) – bootstrap a LiveKit SFU for voice and video
|
||||
|
||||
## Development
|
||||
|
||||
### Tech stack
|
||||
|
||||
- [TypeScript](https://www.typescriptlang.org/) and [Node.js](https://nodejs.org/) for backend services
|
||||
- [Hono](https://hono.dev/) as the web framework for all HTTP services
|
||||
- [Erlang/OTP](https://www.erlang.org/) for the real-time WebSocket gateway (message routing and presence)
|
||||
- [React](https://react.dev/) and [Electron](https://www.electronjs.org/) for the desktop and web client
|
||||
- [Rust](https://www.rust-lang.org/) compiled to WebAssembly for performance-critical client code
|
||||
- [SQLite](https://www.sqlite.org/) for storage by default, with optional [Cassandra](https://cassandra.apache.org/) for distributed deployments
|
||||
- [Meilisearch](https://www.meilisearch.com/) for full-text search and indexing
|
||||
- [Valkey](https://valkey.io/) (Redis-compatible) for caching, rate limiting, and ephemeral coordination
|
||||
- [LiveKit](https://livekit.io/) for voice and video infrastructure
|
||||
|
||||
### Devenv development environment
|
||||
|
||||
Fluxer supports development through **devenv** only. It provides a reproducible Nix environment and a single, declarative process manager for the dev stack.
|
||||
|
||||
1. Install Nix and devenv using the [devenv getting started guide](https://devenv.sh/getting-started/).
|
||||
2. Enter the environment:
|
||||
|
||||
```bash
|
||||
devenv shell
|
||||
```
|
||||
|
||||
If you use direnv, the repo includes a `.envrc` that loads devenv automatically – run `direnv allow` once.
|
||||
|
||||
### Getting started
|
||||
|
||||
Start all services and the development server with:
|
||||
|
||||
```bash
|
||||
devenv up
|
||||
```
|
||||
|
||||
Open the instance in a browser at your dev server URL (e.g. `http://localhost:48763/`).
|
||||
|
||||
Emails sent during development (verification codes, notifications, etc.) are captured by a local Mailpit instance. Access the inbox at your dev server URL + `/mailpit/` (e.g. `http://localhost:48763/mailpit/`).
|
||||
|
||||
### Voice on a remote VM
|
||||
|
||||
If you develop on a remote VM behind Cloudflare Tunnels (or a similar HTTP-only tunnel), voice and video won't work out of the box. Cloudflare Tunnels only proxy HTTP/WebSocket traffic, so WebRTC media transport needs a direct path to the server. Open these ports on the VM's firewall:
|
||||
|
||||
| Port | Protocol | Purpose |
|
||||
| ----------- | -------- | ---------------- |
|
||||
| 3478 | UDP | TURN/STUN |
|
||||
| 7881 | TCP | ICE-TCP fallback |
|
||||
| 50000-50100 | UDP | RTP/RTCP media |
|
||||
|
||||
The bootstrap script configures LiveKit automatically based on `domain.base_domain` in your `config.json`. When set to a non-localhost domain, it enables external IP discovery so clients can connect directly for media while signaling continues through the tunnel.
|
||||
|
||||
### Devcontainer (experimental)
|
||||
|
||||
There is experimental support for developing in a **VS Code Dev Container** / GitHub Codespace without Nix. The `.devcontainer/` directory provides a Docker Compose setup with all required tooling and backing services.
|
||||
|
||||
```bash
|
||||
# Inside the dev container, start all processes:
|
||||
process-compose -f .devcontainer/process-compose.yml up
|
||||
```
|
||||
|
||||
Open the app at `http://localhost:48763` and the dev email inbox at `http://localhost:48763/mailpit/`. Predefined VS Code debugging targets are available in `.vscode/launch.json`.
|
||||
|
||||
> [!WARNING]
|
||||
> Bluesky OAuth is disabled in the devcontainer because it requires HTTPS. All other features work normally.
|
||||
|
||||
### Documentation
|
||||
|
||||
To develop the documentation site with live preview:
|
||||
|
||||
```bash
|
||||
pnpm dev:docs
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Fluxer is **free and open source software** licensed under **AGPLv3**. Contributions are welcome.
|
||||
|
||||
See [`CONTRIBUTING.md`](./CONTRIBUTING.md) for development processes and how to propose changes, and [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) for community guidelines.
|
||||
|
||||
## Security
|
||||
|
||||
Report vulnerabilities at [fluxer.app/security](https://fluxer.app/security). Do not use public issues for security reports.
|
||||
|
||||
<details>
|
||||
<summary><strong>License</strong></summary>
|
||||
<br>
|
||||
|
||||
Copyright (c) 2026 Fluxer Contributors
|
||||
|
||||
Licensed under the [GNU Affero General Public License v3](./LICENSE):
|
||||
|
||||
```text
|
||||
Copyright (c) 2026 Fluxer Contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU Affero General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License along
|
||||
with this program. If not, see https://www.gnu.org/licenses/
|
||||
```
|
||||
|
||||
See [`LICENSING.md`](./LICENSING.md) for details on commercial licensing and the CLA.
|
||||
|
||||
</details>
|
||||
<p align="center">
|
||||
<img src="./fluxer_static/marketing/screenshots/desktop-1920w.png" alt="Fluxer app showcase" width="900">
|
||||
</p>
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
# Security Policy
|
||||
# Security
|
||||
|
||||
Please **do not** report security vulnerabilities via public GitHub issues.
|
||||
Please report security issues through the Fluxer security page:
|
||||
|
||||
Report security issues here: https://fluxer.app/security
|
||||
https://fluxer.app/security
|
||||
|
||||
+13
-7
@@ -6,7 +6,8 @@
|
||||
"indentStyle": "tab",
|
||||
"lineWidth": 120,
|
||||
"lineEnding": "lf",
|
||||
"bracketSpacing": false
|
||||
"bracketSpacing": false,
|
||||
"includes": ["**", "!**/fluxer_app/src/features/theme/variables/ThemeVariableManifest.ts"]
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
@@ -128,18 +129,23 @@
|
||||
"!**/build",
|
||||
"fluxer_app/scripts/build",
|
||||
"!**/dist",
|
||||
"!**/fluxer_app/src/data/emojis.json",
|
||||
"!**/fluxer_app/src/locales/*/messages.js",
|
||||
"!**/fluxer_app/src/media/data/emojis.json",
|
||||
"!**/fluxer_app/src/features/i18n/locales/*/messages.js",
|
||||
"!**/fluxer_app/src/features/i18n/locales/*/messages.mjs",
|
||||
"!**/fluxer_app/src/env.d.ts",
|
||||
"!**/*.generated.*",
|
||||
"!**/*.pb.*",
|
||||
"!**/*_pb.*",
|
||||
"!**/node_modules",
|
||||
"!packages/schema/src/gen",
|
||||
"!**/tailwind.css",
|
||||
"!**/*.html",
|
||||
"!**/*.module.css.d.ts",
|
||||
"!**/fluxer_app/src/components/uikit/SVGMasks.tsx",
|
||||
"!fluxer_marketing/public/static/app.css",
|
||||
"!packages/marketing/public/static/app.css",
|
||||
"!**/fluxer_app/src/features/ui/components/SVGMasks.tsx",
|
||||
"!fluxer_static",
|
||||
"!fluxer_docs/api-reference/openapi.json"
|
||||
"!fluxer_admin/static/htmx.min.js",
|
||||
"!fluxer_marketing/static/htmx.min.js",
|
||||
"!fluxer_api/src/api/openapi/openapi.json"
|
||||
],
|
||||
"ignoreUnknown": true
|
||||
}
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
x-logging: &default-logging
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: '10m'
|
||||
max-file: '5'
|
||||
|
||||
services:
|
||||
valkey:
|
||||
image: valkey/valkey:8.0.6-alpine
|
||||
container_name: valkey
|
||||
restart: unless-stopped
|
||||
command: ['valkey-server', '--appendonly', 'yes', '--save', '60', '1', '--loglevel', 'warning']
|
||||
volumes:
|
||||
- valkey_data:/data
|
||||
healthcheck:
|
||||
test: ['CMD', 'valkey-cli', 'ping']
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
logging: *default-logging
|
||||
|
||||
fluxer_server:
|
||||
image: ${FLUXER_SERVER_IMAGE:-ghcr.io/fluxerapp/fluxer-server:stable}
|
||||
container_name: fluxer_server
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
environment:
|
||||
FLUXER_CONFIG: /usr/src/app/config/config.json
|
||||
NODE_ENV: production
|
||||
ports:
|
||||
- '${FLUXER_HTTP_PORT:-8080}:8080'
|
||||
depends_on:
|
||||
valkey:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ./config:/usr/src/app/config:ro
|
||||
- fluxer_data:/usr/src/app/data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:8080/_health || exit 1']
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 15s
|
||||
logging: *default-logging
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.14
|
||||
container_name: meilisearch
|
||||
profiles: ['search']
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MEILI_ENV: production
|
||||
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY:?Set MEILI_MASTER_KEY in .env or environment}
|
||||
MEILI_DB_PATH: /meili_data
|
||||
MEILI_HTTP_ADDR: 0.0.0.0:7700
|
||||
ports:
|
||||
- '${MEILI_PORT:-7700}:7700'
|
||||
volumes:
|
||||
- meilisearch_data:/meili_data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:7700/health || exit 1']
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
logging: *default-logging
|
||||
|
||||
elasticsearch:
|
||||
image: elasticsearch:8.19.11
|
||||
container_name: elasticsearch
|
||||
profiles: ['search']
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
discovery.type: single-node
|
||||
xpack.security.enabled: 'false'
|
||||
xpack.security.http.ssl.enabled: 'false'
|
||||
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
|
||||
ports:
|
||||
- '${ELASTICSEARCH_PORT:-9200}:9200'
|
||||
volumes:
|
||||
- elasticsearch_data:/usr/share/elasticsearch/data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'curl -fsS http://127.0.0.1:9200/_cluster/health || exit 1']
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
logging: *default-logging
|
||||
|
||||
livekit:
|
||||
image: livekit/livekit-server:v1.9.11
|
||||
container_name: livekit
|
||||
profiles: ['voice']
|
||||
restart: unless-stopped
|
||||
command: ['--config', '/etc/livekit/livekit.yaml']
|
||||
volumes:
|
||||
- ./config/livekit.yaml:/etc/livekit/livekit.yaml:ro
|
||||
ports:
|
||||
- '${LIVEKIT_PORT:-7880}:7880'
|
||||
- '7881:7881'
|
||||
- '3478:3478/udp'
|
||||
- '50000-50100:50000-50100/udp'
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'wget -qO- http://127.0.0.1:7880 || exit 1']
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
logging: *default-logging
|
||||
|
||||
volumes:
|
||||
valkey_data:
|
||||
fluxer_data:
|
||||
meilisearch_data:
|
||||
elasticsearch_data:
|
||||
@@ -1,116 +0,0 @@
|
||||
{
|
||||
"$schema": "../packages/config/src/ConfigSchema.json",
|
||||
"env": "development",
|
||||
"domain": {
|
||||
"base_domain": "localhost",
|
||||
"public_port": 48763
|
||||
},
|
||||
"database": {
|
||||
"backend": "sqlite",
|
||||
"sqlite_path": "./data/dev.db"
|
||||
},
|
||||
"internal": {
|
||||
"kv": "redis://127.0.0.1:6379/0",
|
||||
"kv_mode": "standalone"
|
||||
},
|
||||
"s3": {
|
||||
"access_key_id": "",
|
||||
"secret_access_key": "",
|
||||
"endpoint": "http://127.0.0.1:49319/s3"
|
||||
},
|
||||
"services": {
|
||||
"server": {
|
||||
"port": 49319,
|
||||
"host": "0.0.0.0"
|
||||
},
|
||||
"media_proxy": {
|
||||
"secret_key": ""
|
||||
},
|
||||
"admin": {
|
||||
"secret_key_base": "",
|
||||
"oauth_client_secret": ""
|
||||
},
|
||||
"marketing": {
|
||||
"enabled": true,
|
||||
"port": 49531,
|
||||
"host": "0.0.0.0",
|
||||
"secret_key_base": ""
|
||||
},
|
||||
"gateway": {
|
||||
"port": 49107,
|
||||
"admin_reload_secret": "",
|
||||
"media_proxy_endpoint": "http://localhost:49319/media",
|
||||
"logger_level": "debug"
|
||||
},
|
||||
"nats": {
|
||||
"core_url": "nats://127.0.0.1:4222",
|
||||
"jetstream_url": "nats://127.0.0.1:4223"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"sudo_mode_secret": "",
|
||||
"connection_initiation_secret": "",
|
||||
"vapid": {
|
||||
"public_key": "",
|
||||
"private_key": ""
|
||||
},
|
||||
"bluesky": {
|
||||
"enabled": true,
|
||||
"keys": []
|
||||
}
|
||||
},
|
||||
"discovery": {
|
||||
"min_member_count": 1
|
||||
},
|
||||
"dev": {
|
||||
"disable_rate_limits": true
|
||||
},
|
||||
"integrations": {
|
||||
"email": {
|
||||
"enabled": true,
|
||||
"provider": "smtp",
|
||||
"from_email": "noreply@localhost",
|
||||
"smtp": {
|
||||
"host": "localhost",
|
||||
"port": 49621,
|
||||
"username": "dev",
|
||||
"password": "",
|
||||
"secure": false
|
||||
}
|
||||
},
|
||||
"gif": {
|
||||
"provider": "klipy"
|
||||
},
|
||||
"klipy": {
|
||||
"api_key": ""
|
||||
},
|
||||
"tenor": {
|
||||
"api_key": ""
|
||||
},
|
||||
"voice": {
|
||||
"enabled": true,
|
||||
"api_key": "",
|
||||
"api_secret": "",
|
||||
"url": "ws://localhost:7880",
|
||||
"webhook_url": "http://localhost:49319/api/webhooks/livekit",
|
||||
"default_region": {
|
||||
"id": "default",
|
||||
"name": "Default",
|
||||
"emoji": "\ud83c\udf10",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"engine": "meilisearch",
|
||||
"url": "http://127.0.0.1:7700",
|
||||
"api_key": ""
|
||||
}
|
||||
},
|
||||
"instance": {
|
||||
"private_key_path": ""
|
||||
},
|
||||
"federation": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"$schema": "../packages/config/src/ConfigSchema.json",
|
||||
"env": "production",
|
||||
"domain": {
|
||||
"base_domain": "chat.example.com",
|
||||
"public_scheme": "https",
|
||||
"public_port": 443
|
||||
},
|
||||
"database": {
|
||||
"backend": "sqlite",
|
||||
"sqlite_path": "./data/fluxer.db"
|
||||
},
|
||||
"internal": {
|
||||
"kv": "redis://valkey:6379/0",
|
||||
"kv_mode": "standalone"
|
||||
},
|
||||
"s3": {
|
||||
"access_key_id": "YOUR_S3_ACCESS_KEY",
|
||||
"secret_access_key": "YOUR_S3_SECRET_KEY",
|
||||
"endpoint": "http://127.0.0.1:8080/s3"
|
||||
},
|
||||
"services": {
|
||||
"server": {
|
||||
"port": 8080,
|
||||
"host": "0.0.0.0"
|
||||
},
|
||||
"media_proxy": {
|
||||
"secret_key": "GENERATE_A_64_CHAR_HEX_SECRET"
|
||||
},
|
||||
"admin": {
|
||||
"secret_key_base": "GENERATE_A_64_CHAR_HEX_SECRET",
|
||||
"oauth_client_secret": "GENERATE_A_64_CHAR_HEX_SECRET"
|
||||
},
|
||||
"marketing": {
|
||||
"enabled": true,
|
||||
"secret_key_base": "GENERATE_A_64_CHAR_HEX_SECRET"
|
||||
},
|
||||
"gateway": {
|
||||
"port": 8082,
|
||||
"admin_reload_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
|
||||
"media_proxy_endpoint": "http://127.0.0.1:8080/media"
|
||||
},
|
||||
"nats": {
|
||||
"core_url": "nats://nats:4222",
|
||||
"jetstream_url": "nats://nats:4222",
|
||||
"auth_token": "GENERATE_A_NATS_AUTH_TOKEN"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"sudo_mode_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
|
||||
"connection_initiation_secret": "GENERATE_A_64_CHAR_HEX_SECRET",
|
||||
"vapid": {
|
||||
"public_key": "YOUR_VAPID_PUBLIC_KEY",
|
||||
"private_key": "YOUR_VAPID_PRIVATE_KEY"
|
||||
}
|
||||
},
|
||||
"integrations": {
|
||||
"search": {
|
||||
"engine": "meilisearch",
|
||||
"url": "http://meilisearch:7700",
|
||||
"api_key": "YOUR_MEILISEARCH_API_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$ref": "../packages/config/src/ConfigSchema.json"
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
{
|
||||
"env": "test",
|
||||
"instance": {
|
||||
"self_hosted": false
|
||||
},
|
||||
"domain": {
|
||||
"base_domain": "localhost"
|
||||
},
|
||||
"database": {
|
||||
"backend": "sqlite",
|
||||
"sqlite_path": "./data/test.db"
|
||||
},
|
||||
"s3": {
|
||||
"access_key_id": "test-access-key",
|
||||
"secret_access_key": "test-secret-key"
|
||||
},
|
||||
"services": {
|
||||
"media_proxy": {
|
||||
"secret_key": "test-media-proxy-secret-key-minimum-32-chars"
|
||||
},
|
||||
"admin": {
|
||||
"secret_key_base": "test-admin-secret-key-base-minimum-32-chars",
|
||||
"oauth_client_secret": "test-oauth-client-secret"
|
||||
},
|
||||
"gateway": {
|
||||
"admin_reload_secret": "test-gateway-admin-reload-secret-32-chars",
|
||||
"media_proxy_endpoint": "http://localhost:8088/media"
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
"sudo_mode_secret": "test-sudo-mode-secret-minimum-32-chars",
|
||||
"connection_initiation_secret": "test-connection-initiation-secret-32ch",
|
||||
"vapid": {
|
||||
"public_key": "test-vapid-public-key",
|
||||
"private_key": "test-vapid-private-key"
|
||||
},
|
||||
"bluesky": {
|
||||
"enabled": true,
|
||||
"keys": []
|
||||
}
|
||||
},
|
||||
"discovery": {
|
||||
"min_member_count": 1
|
||||
},
|
||||
"dev": {
|
||||
"disable_rate_limits": true,
|
||||
"test_mode_enabled": true,
|
||||
"relax_registration_rate_limits": true
|
||||
},
|
||||
"proxy": {
|
||||
"trust_cf_connecting_ip": false
|
||||
},
|
||||
"integrations": {
|
||||
"search": {
|
||||
"url": "http://127.0.0.1:7700",
|
||||
"api_key": "test-meilisearch-master-key"
|
||||
},
|
||||
"photo_dna": {
|
||||
"enabled": true,
|
||||
"hash_service_url": "https://api.microsoftmoderator.com/photodna/v1.0/Hash",
|
||||
"hash_service_timeout_ms": 30000,
|
||||
"match_endpoint": "https://api.microsoftmoderator.com/photodna/v1.0/Match",
|
||||
"subscription_key": "test-subscription-key",
|
||||
"match_enhance": false,
|
||||
"rate_limit_rps": 10
|
||||
},
|
||||
"stripe": {
|
||||
"enabled": true,
|
||||
"secret_key": "sk_test_mock_key_for_testing",
|
||||
"webhook_secret": "whsec_test_mock_webhook_secret"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+146
@@ -0,0 +1,146 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#
|
||||
# Checked-in local development defaults. Private credentials and personal
|
||||
# overrides belong in .env.local or config/env/local.env, both ignored by git.
|
||||
|
||||
FLUXER_ENV=development
|
||||
NODE_ENV=development
|
||||
FLUXER_BASE_DOMAIN=localhost
|
||||
FLUXER_PUBLIC_SCHEME=http
|
||||
FLUXER_PUBLIC_PORT=8088
|
||||
FLUXER_STATIC_CDN_DOMAIN=localhost
|
||||
FLUXER_PUBLIC_URL=http://localhost:8088
|
||||
FLUXER_API_ENDPOINT=http://localhost:8088/api
|
||||
FLUXER_API_CLIENT_ENDPOINT=http://localhost:8088/api
|
||||
FLUXER_APP_ENDPOINT=http://localhost:8088
|
||||
FLUXER_GATEWAY_ENDPOINT=ws://localhost:8088/gateway
|
||||
FLUXER_MEDIA_ENDPOINT=http://localhost:8088/media
|
||||
FLUXER_STATIC_CDN_ENDPOINT=http://localhost:8088
|
||||
FLUXER_ADMIN_ENDPOINT=http://localhost:8088/admin
|
||||
FLUXER_MARKETING_ENDPOINT=http://localhost:8088/marketing
|
||||
FLUXER_TRUST_CLIENT_IP_HEADER=true
|
||||
FLUXER_CLIENT_IP_HEADER_NAME=x-forwarded-for
|
||||
|
||||
FLUXER_DATABASE_BACKEND=postgres
|
||||
FLUXER_POSTGRES_HOST=postgres
|
||||
FLUXER_POSTGRES_PORT=5432
|
||||
FLUXER_POSTGRES_DATABASE=fluxer
|
||||
FLUXER_POSTGRES_USERNAME=fluxer
|
||||
FLUXER_POSTGRES_PASSWORD=fluxer
|
||||
FLUXER_POSTGRES_SSL=false
|
||||
FLUXER_POSTGRES_MAX_CONNECTIONS=20
|
||||
FLUXER_POSTGRES_KV_TABLE=fluxer_kv
|
||||
FLUXER_CASSANDRA_HOSTS=cassandra
|
||||
FLUXER_CASSANDRA_PORT=9042
|
||||
FLUXER_CASSANDRA_KEYSPACE=fluxer
|
||||
FLUXER_CASSANDRA_LOCAL_DC=datacenter1
|
||||
FLUXER_CASSANDRA_USERNAME=fluxer
|
||||
FLUXER_CASSANDRA_PASSWORD=fluxer
|
||||
FLUXER_KV_URL=redis://valkey:6379/0
|
||||
FLUXER_NATS_URL=nats://nats:4222
|
||||
FLUXER_NATS_JETSTREAM_URL=nats://nats:4222
|
||||
FLUXER_INTERNAL_API_ENDPOINT=http://127.0.0.1:8080
|
||||
FLUXER_INTERNAL_GATEWAY_ENDPOINT=http://127.0.0.1:8771
|
||||
FLUXER_INTERNAL_MEDIA_PROXY_ENDPOINT=http://127.0.0.1:8082
|
||||
FLUXER_MEDIA_PROXY_ENDPOINT=http://127.0.0.1:8082
|
||||
FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT=http://localhost:8088/media
|
||||
|
||||
FLUXER_SVC_NATS_URL=nats://nats:4222
|
||||
FLUXER_SVC_SHARD_COUNT=1
|
||||
FLUXER_SVC_CACHE_TTL_MS=30000
|
||||
FLUXER_SVC_CACHE_HARD_TTL_MS=600000
|
||||
FLUXER_SVC_MAX_CONCURRENT_REQUESTS=64
|
||||
|
||||
FLUXER_S3_ENDPOINT=http://127.0.0.1:8333
|
||||
FLUXER_S3_PUBLIC_ENDPOINT=http://localhost:8088
|
||||
FLUXER_S3_REGION=us-east-1
|
||||
FLUXER_S3_ACCESS_KEY_ID=fluxer
|
||||
FLUXER_S3_SECRET_ACCESS_KEY=fluxer-secret
|
||||
FLUXER_S3_FORCE_PATH_STYLE=true
|
||||
FLUXER_S3_BUCKET_CDN=fluxer
|
||||
FLUXER_S3_BUCKET_UPLOADS=fluxer-uploads
|
||||
FLUXER_S3_BUCKET_DOWNLOADS=fluxer-downloads
|
||||
FLUXER_S3_BUCKET_REPORTS=fluxer-reports
|
||||
FLUXER_S3_BUCKET_HARVESTS=fluxer-harvests
|
||||
FLUXER_S3_BUCKET_STATIC=fluxer-static
|
||||
|
||||
FLUXER_LIVEKIT_ENABLED=true
|
||||
FLUXER_LIVEKIT_URL=ws://localhost:8088/livekit
|
||||
FLUXER_LIVEKIT_API_KEY=devkey
|
||||
FLUXER_LIVEKIT_API_SECRET=secret
|
||||
FLUXER_LIVEKIT_WEBHOOK_URL=http://localhost:8088/api/webhooks/livekit
|
||||
FLUXER_LIVEKIT_DEFAULT_REGION={"id":"local","name":"Local","emoji":"LC","latitude":59.3293,"longitude":18.0686}
|
||||
|
||||
FLUXER_API_PORT=8080
|
||||
FLUXER_API_PRESIGNED_ATTACHMENT_UPLOADS_ENABLED=true
|
||||
FLUXER_API_WORKER_MODE=all_lanes
|
||||
FLUXER_API_WORKER_ENABLE_VOICE_RECONCILIATION=true
|
||||
FLUXER_APP_DEV_PORT=3000
|
||||
FLUXER_APP_PROXY_PORT=8773
|
||||
FLUXER_STATIC_DIR=fluxer_app/dist
|
||||
FLUXER_MEDIA_PROXY_HOST=0.0.0.0
|
||||
FLUXER_MEDIA_PROXY_PORT=8082
|
||||
FLUXER_MEDIA_PROXY_SECRET_KEY=dev-media-proxy-secret
|
||||
FLUXER_MEDIA_PROXY_MODE=upload
|
||||
FLUXER_MEDIA_PROXY_STORAGE_BACKEND=s3
|
||||
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_ENDPOINT=http://localhost:8088/media
|
||||
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_KEEP_DIRECT_COUNTRIES=
|
||||
FLUXER_GATEWAY_PORT=8771
|
||||
FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT=http://localhost:8088/media
|
||||
FLUXER_GATEWAY_STATIC_CDN_ENDPOINT=http://localhost:8088
|
||||
FLUXER_GATEWAY_RPC_AUTH_TOKEN=dev-gateway-rpc-token
|
||||
FLUXER_GATEWAY_LOGGER_LEVEL=info
|
||||
FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_ENTRIES=128
|
||||
FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_BYTES=1048576
|
||||
FLUXER_ADMIN_PORT=3020
|
||||
FLUXER_ADMIN_BASE_PATH=/admin
|
||||
FLUXER_ADMIN_SECRET_KEY_BASE=dev-admin-secret-key-base
|
||||
FLUXER_ADMIN_OAUTH_CLIENT_ID=1234567890123456789
|
||||
FLUXER_ADMIN_OAUTH_CLIENT_SECRET=dev-admin-oauth-secret
|
||||
FLUXER_ADMIN_OAUTH_REDIRECT_URI=http://localhost:8088/admin/oauth2_callback
|
||||
FLUXER_MARKETING_PORT=3010
|
||||
FLUXER_MARKETING_HOST=0.0.0.0
|
||||
FLUXER_MARKETING_BASE_PATH=/marketing
|
||||
FLUXER_MARKETING_SECRET_KEY_BASE=dev-marketing-secret-key-base
|
||||
|
||||
FLUXER_SUDO_MODE_SECRET=dev-sudo-secret
|
||||
FLUXER_CONNECTION_INITIATION_SECRET=dev-connection-initiation-secret
|
||||
FLUXER_VAPID_PUBLIC_KEY=dev-vapid-public-key
|
||||
FLUXER_VAPID_PRIVATE_KEY=dev-vapid-private-key
|
||||
FLUXER_VAPID_EMAIL=dev@localhost
|
||||
FLUXER_PASSKEY_RP_NAME=Fluxer Dev
|
||||
FLUXER_PASSKEY_RP_ID=localhost
|
||||
FLUXER_PASSKEY_ADDITIONAL_ALLOWED_ORIGINS=http://localhost,http://localhost:8088
|
||||
FLUXER_EMAIL_ENABLED=true
|
||||
FLUXER_EMAIL_PROVIDER=smtp
|
||||
FLUXER_EMAIL_FROM_EMAIL=dev@localhost
|
||||
FLUXER_EMAIL_FROM_NAME=Fluxer Dev
|
||||
FLUXER_EMAIL_SMTP_HOST=mailpit
|
||||
FLUXER_EMAIL_SMTP_PORT=1025
|
||||
FLUXER_EMAIL_SMTP_USERNAME=dev
|
||||
FLUXER_EMAIL_SMTP_PASSWORD=dev
|
||||
FLUXER_EMAIL_SMTP_SECURE=false
|
||||
FLUXER_SMS_ENABLED=false
|
||||
FLUXER_CAPTCHA_ENABLED=false
|
||||
FLUXER_CAPTCHA_PROVIDER=none
|
||||
FLUXER_SEARCH_ENGINE=elasticsearch
|
||||
FLUXER_SEARCH_URL=http://localhost:9200
|
||||
FLUXER_SEARCH_TLS_REJECT_UNAUTHORIZED=false
|
||||
FLUXER_STRIPE_ENABLED=false
|
||||
FLUXER_NCMEC_ENABLED=false
|
||||
FLUXER_CLAMAV_ENABLED=false
|
||||
FLUXER_GIF_PROVIDER=tenor
|
||||
FLUXER_DISCOVERY_ENABLED=true
|
||||
FLUXER_SELF_HOSTED=true
|
||||
FLUXER_DISABLE_RATE_LIMITS=true
|
||||
FLUXER_TEST_MODE_ENABLED=false
|
||||
|
||||
PUBLIC_BUILD_VERSION=dev
|
||||
PUBLIC_RELEASE_CHANNEL=canary
|
||||
PUBLIC_BOOTSTRAP_API_ENDPOINT=/api
|
||||
PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT=http://localhost:8088/api
|
||||
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64=Zmx1eGVyLWRldi11cGxvYWQtcmVsYXktc2VjcmV0LTAwMDA=
|
||||
AWS_EC2_METADATA_DISABLED=true
|
||||
AWS_ACCESS_KEY_ID=fluxer
|
||||
AWS_SECRET_ACCESS_KEY=fluxer-secret
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
@@ -1,16 +0,0 @@
|
||||
port: 7880
|
||||
|
||||
keys:
|
||||
'<replace-with-api-key>': '<replace-with-api-secret>'
|
||||
|
||||
rtc:
|
||||
tcp_port: 7881
|
||||
|
||||
turn:
|
||||
enabled: true
|
||||
udp_port: 3478
|
||||
|
||||
room:
|
||||
auto_create: true
|
||||
max_participants: 100
|
||||
empty_timeout: 300
|
||||
@@ -0,0 +1,102 @@
|
||||
# cargo-deny configuration for the Fluxer workspace.
|
||||
#
|
||||
# Applies to the root workspace (Cargo.toml at the repo root) AND to every
|
||||
# per-addon crate under fluxer_desktop/native/* (each addon has its own
|
||||
# [workspace], so we invoke cargo-deny with --config pointing here).
|
||||
#
|
||||
# Used by the native desktop security gate in CI.
|
||||
|
||||
[graph]
|
||||
all-features = false
|
||||
no-default-features = false
|
||||
|
||||
[output]
|
||||
feature-depth = 1
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Advisories (RustSec advisory DB)
|
||||
# ---------------------------------------------------------------------------
|
||||
[advisories]
|
||||
version = 2
|
||||
yanked = "deny"
|
||||
unmaintained = "all"
|
||||
# Placeholder for future per-advisory ignores. Prefer fixing/upgrading the
|
||||
# crate before adding an entry here. Each entry should be a string ID, e.g.
|
||||
# "RUSTSEC-2024-0000", optionally as { id = "...", reason = "..." }.
|
||||
ignore = []
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Licenses
|
||||
# ---------------------------------------------------------------------------
|
||||
# This repo is AGPL-3.0-or-later. Dependency licenses below are vetted to be
|
||||
# compatible with AGPL distribution. If a crate is essential and ships under a
|
||||
# license not listed here, add it explicitly (do NOT route around via
|
||||
# [[licenses.exceptions]] or [[licenses.clarify]] without justification in the
|
||||
# commit message).
|
||||
[licenses]
|
||||
version = 2
|
||||
confidence-threshold = 0.93
|
||||
allow = [
|
||||
"MIT",
|
||||
"Apache-2.0",
|
||||
"Apache-2.0 WITH LLVM-exception",
|
||||
"BSD-2-Clause",
|
||||
"BSD-3-Clause",
|
||||
"ISC",
|
||||
"MPL-2.0",
|
||||
"Unicode-DFS-2016",
|
||||
"Unicode-3.0",
|
||||
"Zlib",
|
||||
"CC0-1.0",
|
||||
"AGPL-3.0-or-later",
|
||||
"BSL-1.0",
|
||||
"OpenSSL",
|
||||
"CDLA-Permissive-2.0",
|
||||
]
|
||||
# Explicitly deny GPL-only / strong-copyleft licenses that don't compose with
|
||||
# AGPL-3.0-or-later linking semantics in a library context.
|
||||
exceptions = []
|
||||
|
||||
# ring uses a custom BSD-ish + OpenSSL license combo that cargo-deny can't
|
||||
# auto-classify; clarify it as the ISC/OpenSSL/MIT triple it actually is.
|
||||
[[licenses.clarify]]
|
||||
crate = "ring"
|
||||
expression = "ISC AND MIT AND OpenSSL"
|
||||
license-files = [
|
||||
{ path = "LICENSE", hash = 0xbd0eed23 },
|
||||
]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Bans
|
||||
# ---------------------------------------------------------------------------
|
||||
[bans]
|
||||
multiple-versions = "warn"
|
||||
wildcards = "deny"
|
||||
# Per-addon crates path-depend on ../rust (the shared `fluxer_desktop_native`
|
||||
# crate) without a version. cargo-deny flags that as a wildcard; we allow it
|
||||
# because path deps can't realistically pin a SemVer range, and this only
|
||||
# affects intra-repo workspace links (registry wildcards remain denied).
|
||||
allow-wildcard-paths = true
|
||||
highlight = "all"
|
||||
workspace-default-features = "allow"
|
||||
external-default-features = "allow"
|
||||
# Keep desktop packaging and native addons away from the obsolete libfuse2 stack.
|
||||
# AppImage packaging must use the static electron-builder runtime instead.
|
||||
deny = [
|
||||
{ crate = "fuse", reason = "libfuse2-based Rust wrapper; use a maintained FUSE3-native crate only if Fluxer ever needs FUSE directly" },
|
||||
{ crate = "fuse-sys", reason = "libfuse2 FFI crate; Fluxer AppImages must not reintroduce libfuse2 through native Rust dependencies" },
|
||||
]
|
||||
skip = []
|
||||
skip-tree = []
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Sources
|
||||
# ---------------------------------------------------------------------------
|
||||
[sources]
|
||||
unknown-registry = "deny"
|
||||
unknown-git = "deny"
|
||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||
allow-git = []
|
||||
|
||||
[sources.allow-org]
|
||||
github = []
|
||||
@@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
apiVersion: v2
|
||||
name: admin
|
||||
description: Fluxer admin service
|
||||
type: application
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: common
|
||||
version: 0.1.0
|
||||
repository: file://../common
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
|
||||
@@ -0,0 +1,41 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#
|
||||
# Live user-supplied values for the fluxer-admin-canary release as of 2026-05-17T20:42:36Z.
|
||||
# Captured via: helm -n fluxer get values fluxer-admin-canary
|
||||
# Apply with: helm upgrade fluxer-admin-canary deploy/helm/admin -f deploy/helm/admin/values.yaml -f deploy/helm/admin/values.canary.prod.yaml
|
||||
|
||||
app:
|
||||
build:
|
||||
channel: canary
|
||||
version: ""
|
||||
image: fluxer-admin
|
||||
name: admin-canary
|
||||
port: 8080
|
||||
replicas: 2
|
||||
minReadySeconds: 10
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
terminationGracePeriodSeconds: 60
|
||||
startupProbe:
|
||||
enabled: true
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 24
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
tag: ""
|
||||
global:
|
||||
imagePullSecret: ghcr-pull-secret
|
||||
namespace: fluxer
|
||||
registry: ""
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: fluxer-runtime-env-canary
|
||||
pdb:
|
||||
minAvailable: 50%
|
||||
@@ -0,0 +1,41 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#
|
||||
# Live user-supplied values for the fluxer-admin-stable release as of 2026-06-03T19:37:50Z.
|
||||
# Captured via: helm -n fluxer get values fluxer-admin-stable
|
||||
# Apply with: helm upgrade fluxer-admin-stable deploy/helm/admin -f deploy/helm/admin/values.yaml -f deploy/helm/admin/values.stable.prod.yaml
|
||||
|
||||
app:
|
||||
build:
|
||||
channel: stable
|
||||
version: ""
|
||||
image: fluxer-admin
|
||||
name: admin
|
||||
port: 8080
|
||||
replicas: 2
|
||||
minReadySeconds: 10
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
terminationGracePeriodSeconds: 60
|
||||
startupProbe:
|
||||
enabled: true
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 24
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
tag: ""
|
||||
global:
|
||||
imagePullSecret: ghcr-pull-secret
|
||||
namespace: fluxer
|
||||
registry: ""
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: fluxer-runtime-env-stable
|
||||
pdb:
|
||||
minAvailable: 50%
|
||||
@@ -0,0 +1,34 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
global:
|
||||
namespace: fluxer
|
||||
imagePullSecret: ghcr-pull-secret
|
||||
registry: ""
|
||||
|
||||
app:
|
||||
name: ''
|
||||
image: ''
|
||||
tag: ''
|
||||
replicas: 2
|
||||
port: 8080
|
||||
config: ''
|
||||
minReadySeconds: 10
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
terminationGracePeriodSeconds: 60
|
||||
startupProbe:
|
||||
enabled: true
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 24
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
memory: 512Mi
|
||||
|
||||
pdb:
|
||||
minAvailable: '50%'
|
||||
@@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
apiVersion: v2
|
||||
name: api
|
||||
description: Fluxer API service
|
||||
type: application
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: common
|
||||
version: 0.1.0
|
||||
repository: file://../common
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
|
||||
@@ -0,0 +1,105 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#
|
||||
# Live user-supplied values for the fluxer-api-canary release as of 2026-05-23T21:25:52Z.
|
||||
# Captured via: helm -n fluxer get values fluxer-api-canary
|
||||
# Apply with: helm upgrade fluxer-api-canary deploy/helm/api -f deploy/helm/api/values.yaml -f deploy/helm/api/values.canary.prod.yaml
|
||||
|
||||
app:
|
||||
build:
|
||||
channel: canary
|
||||
version: ""
|
||||
env:
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: "0"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
|
||||
value: "128"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
|
||||
value: "32"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
|
||||
value: "5000"
|
||||
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: relay_secret_base64
|
||||
name: fluxer-upload-relay
|
||||
image: fluxer-api
|
||||
name: api-canary
|
||||
port: 8080
|
||||
replicas: 4
|
||||
minReadySeconds: 15
|
||||
terminationGracePeriodSeconds: 90
|
||||
preStopDrain:
|
||||
enabled: true
|
||||
path: /_health
|
||||
sleepSeconds: 25
|
||||
timeoutSeconds: 2
|
||||
retryCount: 3
|
||||
retryIntervalSeconds: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
startupProbe:
|
||||
enabled: true
|
||||
failureThreshold: 24
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
rollingUpdate:
|
||||
maxSurge: 0
|
||||
maxUnavailable: 1
|
||||
tag: ""
|
||||
canary:
|
||||
env:
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: "0"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
|
||||
value: "128"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
|
||||
value: "32"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
|
||||
value: "5000"
|
||||
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: relay_secret_base64
|
||||
name: fluxer-upload-relay
|
||||
image: fluxer-api
|
||||
port: 8080
|
||||
replicas: 2
|
||||
minReadySeconds: 15
|
||||
terminationGracePeriodSeconds: 90
|
||||
preStopDrain:
|
||||
enabled: true
|
||||
path: /_health
|
||||
sleepSeconds: 25
|
||||
timeoutSeconds: 2
|
||||
retryCount: 3
|
||||
retryIntervalSeconds: 1
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
startupProbe:
|
||||
enabled: true
|
||||
failureThreshold: 24
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
tag: ""
|
||||
global:
|
||||
imagePullSecret: ghcr-pull-secret
|
||||
namespace: fluxer
|
||||
registry: ""
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: fluxer-runtime-env-canary
|
||||
pdb:
|
||||
minAvailable: 75%
|
||||
@@ -0,0 +1,107 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
#
|
||||
# Live user-supplied values for the fluxer-api-stable release as of 2026-06-03T19:37:50Z.
|
||||
# Captured via: helm -n fluxer get values fluxer-api-stable
|
||||
# Apply with: helm upgrade fluxer-api-stable deploy/helm/api -f deploy/helm/api/values.yaml -f deploy/helm/api/values.stable.prod.yaml
|
||||
|
||||
app:
|
||||
build:
|
||||
channel: stable
|
||||
version: ""
|
||||
env:
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: "0"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
|
||||
value: "128"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
|
||||
value: "32"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
|
||||
value: "5000"
|
||||
- name: FLUXER_USERS_SERVICE_TIMEOUT_MS
|
||||
value: "6000"
|
||||
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: relay_secret_base64
|
||||
name: fluxer-upload-relay
|
||||
image: fluxer-api
|
||||
name: api
|
||||
port: 8080
|
||||
replicas: 31
|
||||
minReadySeconds: 15
|
||||
terminationGracePeriodSeconds: 90
|
||||
preStopDrain:
|
||||
enabled: true
|
||||
path: /_health
|
||||
sleepSeconds: 25
|
||||
timeoutSeconds: 2
|
||||
retryCount: 3
|
||||
retryIntervalSeconds: 1
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
startupProbe:
|
||||
enabled: true
|
||||
failureThreshold: 24
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
rollingUpdate:
|
||||
maxSurge: 0
|
||||
maxUnavailable: 1
|
||||
tag: ""
|
||||
canary:
|
||||
env:
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: "0"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
|
||||
value: "128"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
|
||||
value: "32"
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
|
||||
value: "5000"
|
||||
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: relay_secret_base64
|
||||
name: fluxer-upload-relay
|
||||
image: fluxer-api
|
||||
port: 8080
|
||||
replicas: 2
|
||||
minReadySeconds: 15
|
||||
terminationGracePeriodSeconds: 90
|
||||
preStopDrain:
|
||||
enabled: true
|
||||
path: /_health
|
||||
sleepSeconds: 25
|
||||
timeoutSeconds: 2
|
||||
retryCount: 3
|
||||
retryIntervalSeconds: 1
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
resources:
|
||||
limits:
|
||||
memory: 4Gi
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
startupProbe:
|
||||
enabled: true
|
||||
failureThreshold: 24
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
tag: ""
|
||||
global:
|
||||
imagePullSecret: ghcr-pull-secret
|
||||
namespace: fluxer
|
||||
registry: ""
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: fluxer-runtime-env-stable
|
||||
pdb:
|
||||
minAvailable: 75%
|
||||
@@ -0,0 +1,98 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
global:
|
||||
namespace: fluxer
|
||||
imagePullSecret: ghcr-pull-secret
|
||||
registry: ""
|
||||
|
||||
app:
|
||||
name: ''
|
||||
image: ''
|
||||
tag: ''
|
||||
replicas: 2
|
||||
port: 8080
|
||||
minReadySeconds: 15
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
terminationGracePeriodSeconds: 90
|
||||
preStopDrain:
|
||||
enabled: true
|
||||
path: /_health
|
||||
sleepSeconds: 25
|
||||
timeoutSeconds: 2
|
||||
retryCount: 3
|
||||
retryIntervalSeconds: 1
|
||||
startupProbe:
|
||||
enabled: true
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 24
|
||||
env:
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: '0'
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
|
||||
value: '128'
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
|
||||
value: '32'
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
|
||||
value: '5000'
|
||||
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: fluxer-upload-relay
|
||||
key: relay_secret_base64
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 4Gi
|
||||
|
||||
canary:
|
||||
image: fluxer-api
|
||||
tag: ''
|
||||
replicas: 2
|
||||
port: 8080
|
||||
minReadySeconds: 15
|
||||
rollingUpdate:
|
||||
maxSurge: 1
|
||||
maxUnavailable: 0
|
||||
terminationGracePeriodSeconds: 90
|
||||
preStopDrain:
|
||||
enabled: true
|
||||
path: /_health
|
||||
sleepSeconds: 25
|
||||
timeoutSeconds: 2
|
||||
retryCount: 3
|
||||
retryIntervalSeconds: 1
|
||||
startupProbe:
|
||||
enabled: true
|
||||
path: /_health
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 2
|
||||
failureThreshold: 24
|
||||
env:
|
||||
- name: NODE_TLS_REJECT_UNAUTHORIZED
|
||||
value: '0'
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
|
||||
value: '128'
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
|
||||
value: '32'
|
||||
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
|
||||
value: '5000'
|
||||
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: fluxer-upload-relay
|
||||
key: relay_secret_base64
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
memory: 4Gi
|
||||
|
||||
pdb:
|
||||
minAvailable: '75%'
|
||||
@@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
apiVersion: v2
|
||||
name: app-proxy
|
||||
description: Fluxer app proxy service
|
||||
type: application
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: common
|
||||
version: 0.1.0
|
||||
repository: file://../common
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
|
||||
@@ -0,0 +1,3 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user