merged from gramsrv upstream
This commit is contained in:
parent
79c64ee916
commit
21a0856587
651 changed files with 54774 additions and 4590 deletions
130
.github/workflows/build.yml
vendored
Normal file
130
.github/workflows/build.yml
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
name: Build and Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: build-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
name: CI
|
||||
uses: ./.github/workflows/ci.yml
|
||||
|
||||
build:
|
||||
name: Build ${{ matrix.goos }}/${{ matrix.goarch }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- goos: linux
|
||||
goarch: amd64
|
||||
- goos: linux
|
||||
goarch: arm64
|
||||
- goos: windows
|
||||
goarch: amd64
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v7
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: npm
|
||||
cache-dependency-path: cmd/telesrv-admin/web/package-lock.json
|
||||
|
||||
- name: Build admin web assets
|
||||
working-directory: cmd/telesrv-admin/web
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
|
||||
- name: Download Go modules
|
||||
run: go mod download
|
||||
|
||||
- name: Build binaries
|
||||
env:
|
||||
CGO_ENABLED: '0'
|
||||
GOOS: ${{ matrix.goos }}
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
run: |
|
||||
mkdir -p dist
|
||||
|
||||
suffix=""
|
||||
if [ "${GOOS}" = "windows" ]; then
|
||||
suffix=".exe"
|
||||
fi
|
||||
|
||||
go build \
|
||||
-trimpath \
|
||||
-ldflags="-s -w" \
|
||||
-o "dist/gramsrv-${GOOS}-${GOARCH}${suffix}" \
|
||||
./cmd/telesrv
|
||||
|
||||
go build \
|
||||
-trimpath \
|
||||
-ldflags="-s -w" \
|
||||
-o "dist/gramsrv-admin-${GOOS}-${GOARCH}${suffix}" \
|
||||
./cmd/telesrv-admin
|
||||
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gramsrv-${{ matrix.goos }}-${{ matrix.goarch }}
|
||||
path: dist/*
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
release:
|
||||
name: Publish GitHub Release
|
||||
needs:
|
||||
- ci
|
||||
- build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: gramsrv-*
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
|
||||
- name: Generate combined checksums
|
||||
working-directory: dist
|
||||
run: |
|
||||
sha256sum gramsrv-* > SHA256SUMS
|
||||
|
||||
- name: Publish GitHub Release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
gh release create "${{ github.ref_name }}" \
|
||||
dist/* \
|
||||
--title "${{ github.ref_name }}" \
|
||||
--generate-notes
|
||||
180
.github/workflows/ci.yml
vendored
Normal file
180
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
go-test:
|
||||
name: Go tests
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 45
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v7
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: Download Go modules
|
||||
run: go mod download
|
||||
|
||||
- name: Test
|
||||
run: go test ./... -count=1
|
||||
|
||||
admin-web:
|
||||
name: Admin web build
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: npm
|
||||
cache-dependency-path: cmd/telesrv-admin/web/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: cmd/telesrv-admin/web
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
working-directory: cmd/telesrv-admin/web
|
||||
run: npm run build
|
||||
|
||||
grammystore:
|
||||
name: Grammy store bot
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: npm
|
||||
cache-dependency-path: cmd/bots/grammystore/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: cmd/bots/grammystore
|
||||
run: npm ci
|
||||
|
||||
- name: Check syntax
|
||||
working-directory: cmd/bots/grammystore
|
||||
run: npm run check
|
||||
|
||||
- name: Test
|
||||
working-directory: cmd/bots/grammystore
|
||||
run: npm test
|
||||
|
||||
docker-smoke:
|
||||
name: Docker main topology smoke
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Generate isolated environment
|
||||
run: ./scripts/new-docker-env.sh --advertise-ip 127.0.0.1
|
||||
|
||||
- name: Validate deployment inputs
|
||||
run: |
|
||||
docker compose version
|
||||
sh -n scripts/new-docker-env.sh
|
||||
bash -n scripts/start-docker.sh
|
||||
sh -n deploy/docker/docker-entrypoint.sh
|
||||
compose=(docker compose -p telesrv-main-ci --project-directory deploy/docker --env-file deploy/docker/.env -f deploy/docker/compose.yaml)
|
||||
bridge=("${compose[@]}" -f deploy/docker/compose.bridge-network.yaml)
|
||||
"${compose[@]}" config --quiet
|
||||
"${compose[@]}" config --format json | python3 -c 'import json,sys; s=json.load(sys.stdin)["services"]; assert s["server"].get("network_mode") == "host"; assert s["admin"].get("network_mode") == "host"; assert len(s["server"].get("ports", [])) == 0; assert len(s["admin"].get("ports", [])) == 0; assert str(s["server"]["environment"]["TELESRV_TURN_RELAY_MAX_PORT"]) == "12999"'
|
||||
"${bridge[@]}" config --quiet
|
||||
"${bridge[@]}" config --format json | python3 -c 'import json,sys; c=json.load(sys.stdin); s=c["services"]; assert s["server"].get("network_mode") != "host"; assert s["admin"].get("network_mode") != "host"; assert len(s["server"].get("ports", [])) == 69; assert len(s["admin"].get("ports", [])) == 1; assert "admin_host_access" in s["admin"]["networks"]; assert not c["networks"]["admin_host_access"].get("internal", False); assert str(s["server"]["environment"]["TELESRV_TURN_RELAY_MAX_PORT"]) == "12563"'
|
||||
|
||||
- name: Validate PowerShell launchers
|
||||
shell: pwsh
|
||||
run: |
|
||||
$tokens = $null
|
||||
$errors = $null
|
||||
[void][System.Management.Automation.Language.Parser]::ParseFile("scripts/new-docker-env.ps1", [ref]$tokens, [ref]$errors)
|
||||
if ($errors.Count -gt 0) { $errors | ForEach-Object { Write-Error $_ }; exit 1 }
|
||||
$tokens = $null
|
||||
$errors = $null
|
||||
[void][System.Management.Automation.Language.Parser]::ParseFile("scripts/start-docker.ps1", [ref]$tokens, [ref]$errors)
|
||||
if ($errors.Count -gt 0) { $errors | ForEach-Object { Write-Error $_ }; exit 1 }
|
||||
|
||||
- name: Build application images
|
||||
run: |
|
||||
compose=(docker compose -p telesrv-main-ci --project-directory deploy/docker --env-file deploy/docker/.env -f deploy/docker/compose.yaml)
|
||||
"${compose[@]}" build --pull server admin
|
||||
|
||||
- name: Start and wait for readiness
|
||||
run: docker compose -p telesrv-main-ci --project-directory deploy/docker --env-file deploy/docker/.env -f deploy/docker/compose.yaml up -d --no-build --wait --wait-timeout 600
|
||||
|
||||
- name: Verify runtime and media listeners
|
||||
run: |
|
||||
compose=(docker compose -p telesrv-main-ci --project-directory deploy/docker --env-file deploy/docker/.env -f deploy/docker/compose.yaml)
|
||||
for service in server admin; do
|
||||
container_id="$("${compose[@]}" ps --quiet "$service")"
|
||||
test -n "$container_id"
|
||||
test "$(docker inspect --format '{{.Config.User}}' "$container_id")" = "10001:10001"
|
||||
test "$(docker inspect --format '{{.HostConfig.ReadonlyRootfs}}' "$container_id")" = "true"
|
||||
test "$(docker inspect --format '{{json .HostConfig.CapDrop}}' "$container_id")" = '["ALL"]'
|
||||
test "$(docker inspect --format '{{.HostConfig.PidsLimit}}' "$container_id")" = "1024"
|
||||
test "$(docker inspect --format '{{json .HostConfig.SecurityOpt}}' "$container_id")" = '["no-new-privileges:true"]'
|
||||
test "$(docker inspect --format '{{.HostConfig.NetworkMode}}' "$container_id")" = "host"
|
||||
done
|
||||
curl --fail --silent --show-error http://127.0.0.1:2401/healthz | grep -qx ok
|
||||
curl --fail --silent --show-error http://127.0.0.1:2600/ >/dev/null
|
||||
timeout 5 bash -c 'exec 3<>/dev/tcp/127.0.0.1/2400'
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import socket
|
||||
import struct
|
||||
|
||||
transaction_id = os.urandom(12)
|
||||
request = struct.pack("!HHI12s", 0x0001, 0, 0x2112A442, transaction_id)
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client:
|
||||
client.settimeout(5)
|
||||
client.sendto(request, ("127.0.0.1", 12400))
|
||||
response, _ = client.recvfrom(2048)
|
||||
message_type, _, cookie = struct.unpack("!HHI", response[:8])
|
||||
assert message_type == 0x0101, hex(message_type)
|
||||
assert cookie == 0x2112A442, hex(cookie)
|
||||
assert response[8:20] == transaction_id
|
||||
PY
|
||||
server_logs="$("${compose[@]}" logs --no-color server)"
|
||||
case "$server_logs" in *"sfu listening"*) ;; *) echo "Embedded SFU did not become ready" >&2; exit 1 ;; esac
|
||||
case "$server_logs" in *"turn listening"*) ;; *) echo "Embedded TURN did not become ready" >&2; exit 1 ;; esac
|
||||
case "$server_logs" in *"live stream rtmp ingest listening"*) ;; *) echo "RTMP listener did not become ready" >&2; exit 1 ;; esac
|
||||
|
||||
- name: Show logs on failure
|
||||
if: failure()
|
||||
run: docker compose -p telesrv-main-ci --project-directory deploy/docker --env-file deploy/docker/.env -f deploy/docker/compose.yaml logs --no-color --tail 200
|
||||
|
||||
- name: Remove isolated stack
|
||||
if: always()
|
||||
run: docker compose -p telesrv-main-ci --project-directory deploy/docker --env-file deploy/docker/.env -f deploy/docker/compose.yaml down --volumes --remove-orphans
|
||||
76
.github/workflows/container-images.yml
vendored
Normal file
76
.github/workflows/container-images.yml
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
name: Publish main container images (manual)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
concurrency:
|
||||
group: containers-main-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish ${{ matrix.role }}
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 45
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- role: server
|
||||
target: server-test
|
||||
- role: admin
|
||||
target: admin
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Generate image metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository }}/${{ matrix.role }}
|
||||
tags: |
|
||||
type=raw,value=main
|
||||
type=sha,prefix=sha-
|
||||
|
||||
- name: Set build date
|
||||
id: build
|
||||
shell: bash
|
||||
run: echo "date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build and publish
|
||||
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
target: ${{ matrix.target }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
VCS_REF=${{ github.sha }}
|
||||
VCS_BRANCH=${{ github.ref_name }}
|
||||
VCS_TREE_STATE=clean
|
||||
BUILD_DATE=${{ steps.build.outputs.date }}
|
||||
cache-from: type=gha,scope=main-${{ matrix.role }}
|
||||
cache-to: type=gha,mode=max,scope=main-${{ matrix.role }}
|
||||
Loading…
Add table
Add a link
Reference in a new issue