feat: initial open-source release of Pipely

OTA update server designed for high-concurrency, low-bandwidth deployments.
GORM-backed PostgreSQL, JWT auth, device management, artefact versioning,
deployment rollout with gated rate-limited downloads, and a React admin panel.
This commit is contained in:
2026-07-07 10:29:28 +08:00
commit e070a3fb5f
59 changed files with 6515 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
-- 001_initial_schema.sql
CREATE TABLE IF NOT EXISTS admin_users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(128) NOT NULL UNIQUE,
password_hash VARCHAR(256) NOT NULL,
role VARCHAR(32) NOT NULL DEFAULT 'admin',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS devices (
id BIGSERIAL PRIMARY KEY,
device_id VARCHAR(256) NOT NULL UNIQUE,
ip_address VARCHAR(64) NOT NULL DEFAULT '',
hostname VARCHAR(256) NOT NULL DEFAULT '',
os VARCHAR(64) NOT NULL DEFAULT '',
current_version VARCHAR(128) NOT NULL DEFAULT '0.0.0',
status VARCHAR(32) NOT NULL DEFAULT 'online',
group_name VARCHAR(128) NOT NULL DEFAULT 'default',
last_heartbeat TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_devices_status ON devices(status);
CREATE INDEX IF NOT EXISTS idx_devices_group ON devices(group_name);
CREATE INDEX IF NOT EXISTS idx_devices_heartbeat ON devices(last_heartbeat);
CREATE TABLE IF NOT EXISTS artefacts (
id BIGSERIAL PRIMARY KEY,
version VARCHAR(128) NOT NULL,
file_name VARCHAR(512) NOT NULL,
file_path VARCHAR(1024) NOT NULL,
file_size BIGINT NOT NULL DEFAULT 0,
sha256_hash VARCHAR(128) NOT NULL DEFAULT '',
delta_ref VARCHAR(128) NOT NULL DEFAULT '',
is_delta BOOLEAN NOT NULL DEFAULT FALSE,
metadata TEXT NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_artefacts_version ON artefacts(version);
CREATE TABLE IF NOT EXISTS deployments (
id BIGSERIAL PRIMARY KEY,
artefact_id BIGINT NOT NULL REFERENCES artefacts(id),
name VARCHAR(256) NOT NULL,
description TEXT NOT NULL DEFAULT '',
target_type VARCHAR(32) NOT NULL DEFAULT 'all',
target_spec TEXT NOT NULL DEFAULT '{}',
rollout_strategy VARCHAR(32) NOT NULL DEFAULT 'immediate',
max_concurrent INT NOT NULL DEFAULT 50,
status VARCHAR(32) NOT NULL DEFAULT 'draft',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_deployments_status ON deployments(status);
CREATE TABLE IF NOT EXISTS deployment_devices (
id BIGSERIAL PRIMARY KEY,
deployment_id BIGINT NOT NULL REFERENCES deployments(id) ON DELETE CASCADE,
device_id VARCHAR(256) NOT NULL,
status VARCHAR(32) NOT NULL DEFAULT 'pending',
downloaded_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
error TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(deployment_id, device_id)
);
CREATE INDEX IF NOT EXISTS idx_dd_device ON deployment_devices(device_id);
CREATE INDEX IF NOT EXISTS idx_dd_status ON deployment_devices(status);
CREATE INDEX IF NOT EXISTS idx_dd_deploy ON deployment_devices(deployment_id);