ci: migrate community workflows to gitea
CI / Rust Checks (push) Has been cancelled
CI / UI Checks (push) Has been cancelled
CI / Frontend E2E (push) Has been cancelled
CI / Deployment Manifests (push) Has been cancelled
Deploy / build-images (apps/admin-api/Dockerfile, git.itexp.me/bsodfather/crank-community-admin-api, admin-api) (push) Has been cancelled
Deploy / build-images (apps/mcp-server/Dockerfile, git.itexp.me/bsodfather/crank-community-mcp-server, mcp-server) (push) Has been cancelled
Deploy / build-images (apps/ui/Dockerfile, git.itexp.me/bsodfather/crank-community-ui, ui) (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
CI / Rust Checks (push) Has been cancelled
CI / UI Checks (push) Has been cancelled
CI / Frontend E2E (push) Has been cancelled
CI / Deployment Manifests (push) Has been cancelled
Deploy / build-images (apps/admin-api/Dockerfile, git.itexp.me/bsodfather/crank-community-admin-api, admin-api) (push) Has been cancelled
Deploy / build-images (apps/mcp-server/Dockerfile, git.itexp.me/bsodfather/crank-community-mcp-server, mcp-server) (push) Has been cancelled
Deploy / build-images (apps/ui/Dockerfile, git.itexp.me/bsodfather/crank-community-ui, ui) (push) Has been cancelled
Deploy / deploy (push) Has been cancelled
This commit is contained in:
@@ -7,10 +7,6 @@ on:
|
|||||||
- main
|
- main
|
||||||
- "feat/**"
|
- "feat/**"
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
rust:
|
rust:
|
||||||
name: Rust Checks
|
name: Rust Checks
|
||||||
@@ -36,11 +32,12 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Verify runner toolchain
|
||||||
uses: dtolnay/rust-toolchain@master
|
run: |
|
||||||
with:
|
rustc --version
|
||||||
toolchain: 1.85.0
|
cargo --version
|
||||||
components: rustfmt, clippy
|
rustfmt --version
|
||||||
|
cargo clippy --version
|
||||||
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: cargo fmt --all --check
|
run: cargo fmt --all --check
|
||||||
@@ -62,10 +59,11 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Verify runner toolchain
|
||||||
uses: actions/setup-node@v4
|
run: |
|
||||||
with:
|
node --version
|
||||||
node-version: 22
|
npm --version
|
||||||
|
docker --version
|
||||||
|
|
||||||
- name: Install UI dependencies
|
- name: Install UI dependencies
|
||||||
working-directory: apps/ui
|
working-directory: apps/ui
|
||||||
@@ -86,15 +84,12 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Verify runner toolchain
|
||||||
uses: dtolnay/rust-toolchain@master
|
run: |
|
||||||
with:
|
rustc --version
|
||||||
toolchain: 1.85.0
|
cargo --version
|
||||||
|
node --version
|
||||||
- name: Setup Node.js
|
npm --version
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 22
|
|
||||||
|
|
||||||
- name: Install UI dependencies
|
- name: Install UI dependencies
|
||||||
working-directory: apps/ui
|
working-directory: apps/ui
|
||||||
@@ -108,22 +103,6 @@ jobs:
|
|||||||
working-directory: apps/ui
|
working-directory: apps/ui
|
||||||
run: npx playwright test
|
run: npx playwright test
|
||||||
|
|
||||||
- name: Upload Playwright report
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: playwright-report
|
|
||||||
path: apps/ui/playwright-report
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
- name: Upload Playwright test results
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: playwright-test-results
|
|
||||||
path: apps/ui/test-results
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
deployment:
|
deployment:
|
||||||
name: Deployment Manifests
|
name: Deployment Manifests
|
||||||
runs-on: [self-hosted, linux, x64]
|
runs-on: [self-hosted, linux, x64]
|
||||||
@@ -1,36 +1,20 @@
|
|||||||
name: Deploy
|
name: Deploy
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
push:
|
||||||
workflows:
|
branches:
|
||||||
- CI
|
- main
|
||||||
types:
|
|
||||||
- completed
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: deploy-${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_branch || github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IMAGE_TAG: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }}
|
REGISTRY: git.itexp.me
|
||||||
ADMIN_API_IMAGE: ghcr.io/${{ github.repository_owner }}/crank-admin-api
|
IMAGE_TAG: ${{ gitea.sha }}
|
||||||
MCP_SERVER_IMAGE: ghcr.io/${{ github.repository_owner }}/crank-mcp-server
|
ADMIN_API_IMAGE: git.itexp.me/bsodfather/crank-community-admin-api
|
||||||
UI_IMAGE: ghcr.io/${{ github.repository_owner }}/crank-ui
|
MCP_SERVER_IMAGE: git.itexp.me/bsodfather/crank-community-mcp-server
|
||||||
|
UI_IMAGE: git.itexp.me/bsodfather/crank-community-ui
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-images:
|
build-images:
|
||||||
if: >
|
|
||||||
github.event_name == 'workflow_dispatch' ||
|
|
||||||
(
|
|
||||||
github.event_name == 'workflow_run' &&
|
|
||||||
github.event.workflow_run.conclusion == 'success' &&
|
|
||||||
github.event.workflow_run.head_branch == 'main'
|
|
||||||
)
|
|
||||||
runs-on: [self-hosted, linux, x64]
|
runs-on: [self-hosted, linux, x64]
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -38,82 +22,61 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- name: admin-api
|
- name: admin-api
|
||||||
dockerfile: apps/admin-api/Dockerfile
|
dockerfile: apps/admin-api/Dockerfile
|
||||||
|
image: git.itexp.me/bsodfather/crank-community-admin-api
|
||||||
- name: mcp-server
|
- name: mcp-server
|
||||||
dockerfile: apps/mcp-server/Dockerfile
|
dockerfile: apps/mcp-server/Dockerfile
|
||||||
|
image: git.itexp.me/bsodfather/crank-community-mcp-server
|
||||||
- name: ui
|
- name: ui
|
||||||
dockerfile: apps/ui/Dockerfile
|
dockerfile: apps/ui/Dockerfile
|
||||||
|
image: git.itexp.me/bsodfather/crank-community-ui
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
with:
|
|
||||||
ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }}
|
|
||||||
|
|
||||||
- name: Resolve image name
|
- name: Verify runner toolchain
|
||||||
id: image
|
run: docker --version
|
||||||
|
|
||||||
|
- name: Login to registry
|
||||||
run: |
|
run: |
|
||||||
case "${{ matrix.name }}" in
|
printf '%s' '${{ secrets.DEPLOY_REGISTRY_TOKEN }}' | \
|
||||||
admin-api) echo "name=${ADMIN_API_IMAGE}" >> "$GITHUB_OUTPUT" ;;
|
docker login '${{ env.REGISTRY }}' -u '${{ secrets.DEPLOY_REGISTRY_USER }}' --password-stdin
|
||||||
mcp-server) echo "name=${MCP_SERVER_IMAGE}" >> "$GITHUB_OUTPUT" ;;
|
|
||||||
ui) echo "name=${UI_IMAGE}" >> "$GITHUB_OUTPUT" ;;
|
|
||||||
*) exit 1 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v4
|
|
||||||
|
|
||||||
- name: Log in to GHCR
|
|
||||||
uses: docker/login-action@v4
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push ${{ matrix.name }}
|
- name: Build and push ${{ matrix.name }}
|
||||||
uses: docker/build-push-action@v7
|
run: |
|
||||||
with:
|
docker build -f '${{ matrix.dockerfile }}' \
|
||||||
context: .
|
-t '${{ matrix.image }}:${{ env.IMAGE_TAG }}' \
|
||||||
file: ${{ matrix.dockerfile }}
|
-t '${{ matrix.image }}:main' \
|
||||||
push: true
|
.
|
||||||
tags: |
|
docker push '${{ matrix.image }}:${{ env.IMAGE_TAG }}'
|
||||||
${{ steps.image.outputs.name }}:${{ env.IMAGE_TAG }}
|
docker push '${{ matrix.image }}:main'
|
||||||
${{ steps.image.outputs.name }}:main
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
needs: build-images
|
needs: build-images
|
||||||
if: >
|
|
||||||
github.event_name == 'workflow_dispatch' ||
|
|
||||||
(
|
|
||||||
github.event_name == 'workflow_run' &&
|
|
||||||
github.event.workflow_run.conclusion == 'success' &&
|
|
||||||
github.event.workflow_run.head_branch == 'main'
|
|
||||||
)
|
|
||||||
runs-on: [self-hosted, linux, x64]
|
runs-on: [self-hosted, linux, x64]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
with:
|
|
||||||
ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }}
|
|
||||||
|
|
||||||
- name: Configure SSH key
|
- name: Configure SSH key
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
chmod 700 ~/.ssh
|
chmod 700 ~/.ssh
|
||||||
printf '%s\n' "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_ed25519
|
printf '%s\n' '${{ secrets.DEPLOY_SSH_KEY }}' > ~/.ssh/id_ed25519
|
||||||
chmod 600 ~/.ssh/id_ed25519
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
|
|
||||||
- name: Configure known hosts
|
- name: Configure known hosts
|
||||||
run: |
|
run: |
|
||||||
printf '%s\n' "${{ secrets.DEPLOY_KNOWN_HOSTS }}" > ~/.ssh/known_hosts
|
printf '%s\n' '${{ secrets.DEPLOY_KNOWN_HOSTS }}' > ~/.ssh/known_hosts
|
||||||
chmod 644 ~/.ssh/known_hosts
|
chmod 644 ~/.ssh/known_hosts
|
||||||
|
|
||||||
- name: Sync deployment files to server
|
- name: Sync deployment files to server
|
||||||
run: |
|
run: |
|
||||||
ssh -p "${{ secrets.DEPLOY_PORT }}" "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" \
|
ssh -p '${{ secrets.DEPLOY_PORT }}' '${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}' \
|
||||||
"mkdir -p '${{ secrets.DEPLOY_PATH }}'"
|
"mkdir -p '${{ secrets.DEPLOY_PATH }}'"
|
||||||
rsync -az -e "ssh -p ${{ secrets.DEPLOY_PORT }}" deploy/community/docker-compose.yml \
|
rsync -az -e "ssh -p ${{ secrets.DEPLOY_PORT }}" deploy/community/docker-compose.yml \
|
||||||
"${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}/docker-compose.yml"
|
'${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}/docker-compose.yml'
|
||||||
|
|
||||||
- name: Write environment file
|
- name: Write environment file
|
||||||
env:
|
env:
|
||||||
@@ -130,6 +93,9 @@ jobs:
|
|||||||
CRANK_LOG_LEVEL: ${{ secrets.CRANK_LOG_LEVEL }}
|
CRANK_LOG_LEVEL: ${{ secrets.CRANK_LOG_LEVEL }}
|
||||||
CRANK_MASTER_KEY: ${{ secrets.CRANK_MASTER_KEY }}
|
CRANK_MASTER_KEY: ${{ secrets.CRANK_MASTER_KEY }}
|
||||||
CRANK_BASE_URL: ${{ secrets.CRANK_BASE_URL }}
|
CRANK_BASE_URL: ${{ secrets.CRANK_BASE_URL }}
|
||||||
|
CRANK_CACHE_BACKEND: ${{ secrets.CRANK_CACHE_BACKEND }}
|
||||||
|
CRANK_CACHE_URL: ${{ secrets.CRANK_CACHE_URL }}
|
||||||
|
CRANK_CACHE_DEFAULT_TTL_MS: ${{ secrets.CRANK_CACHE_DEFAULT_TTL_MS }}
|
||||||
CRANK_SESSION_SECRET: ${{ secrets.CRANK_SESSION_SECRET }}
|
CRANK_SESSION_SECRET: ${{ secrets.CRANK_SESSION_SECRET }}
|
||||||
CRANK_PASSWORD_PEPPER: ${{ secrets.CRANK_PASSWORD_PEPPER }}
|
CRANK_PASSWORD_PEPPER: ${{ secrets.CRANK_PASSWORD_PEPPER }}
|
||||||
CRANK_SESSION_TTL_HOURS: ${{ secrets.CRANK_SESSION_TTL_HOURS }}
|
CRANK_SESSION_TTL_HOURS: ${{ secrets.CRANK_SESSION_TTL_HOURS }}
|
||||||
@@ -158,6 +124,9 @@ jobs:
|
|||||||
append_if_set CRANK_LOG_LEVEL "$CRANK_LOG_LEVEL"
|
append_if_set CRANK_LOG_LEVEL "$CRANK_LOG_LEVEL"
|
||||||
append_if_set CRANK_MASTER_KEY "$CRANK_MASTER_KEY"
|
append_if_set CRANK_MASTER_KEY "$CRANK_MASTER_KEY"
|
||||||
append_if_set CRANK_BASE_URL "$CRANK_BASE_URL"
|
append_if_set CRANK_BASE_URL "$CRANK_BASE_URL"
|
||||||
|
append_if_set CRANK_CACHE_BACKEND "$CRANK_CACHE_BACKEND"
|
||||||
|
append_if_set CRANK_CACHE_URL "$CRANK_CACHE_URL"
|
||||||
|
append_if_set CRANK_CACHE_DEFAULT_TTL_MS "$CRANK_CACHE_DEFAULT_TTL_MS"
|
||||||
append_if_set CRANK_SESSION_SECRET "$CRANK_SESSION_SECRET"
|
append_if_set CRANK_SESSION_SECRET "$CRANK_SESSION_SECRET"
|
||||||
append_if_set CRANK_PASSWORD_PEPPER "$CRANK_PASSWORD_PEPPER"
|
append_if_set CRANK_PASSWORD_PEPPER "$CRANK_PASSWORD_PEPPER"
|
||||||
append_if_set CRANK_SESSION_TTL_HOURS "$CRANK_SESSION_TTL_HOURS"
|
append_if_set CRANK_SESSION_TTL_HOURS "$CRANK_SESSION_TTL_HOURS"
|
||||||
@@ -166,17 +135,17 @@ jobs:
|
|||||||
append_if_set CRANK_BOOTSTRAP_ADMIN_DISPLAY_NAME "$CRANK_BOOTSTRAP_ADMIN_DISPLAY_NAME"
|
append_if_set CRANK_BOOTSTRAP_ADMIN_DISPLAY_NAME "$CRANK_BOOTSTRAP_ADMIN_DISPLAY_NAME"
|
||||||
append_if_set CRANK_DEMO_SEED "$CRANK_DEMO_SEED"
|
append_if_set CRANK_DEMO_SEED "$CRANK_DEMO_SEED"
|
||||||
{
|
{
|
||||||
printf 'CRANK_ADMIN_API_IMAGE=%s:%s\n' "${{ env.ADMIN_API_IMAGE }}" "${{ env.IMAGE_TAG }}"
|
printf 'CRANK_ADMIN_API_IMAGE=%s:%s\n' '${{ env.ADMIN_API_IMAGE }}' '${{ env.IMAGE_TAG }}'
|
||||||
printf 'CRANK_MCP_SERVER_IMAGE=%s:%s\n' "${{ env.MCP_SERVER_IMAGE }}" "${{ env.IMAGE_TAG }}"
|
printf 'CRANK_MCP_SERVER_IMAGE=%s:%s\n' '${{ env.MCP_SERVER_IMAGE }}' '${{ env.IMAGE_TAG }}'
|
||||||
printf 'CRANK_UI_IMAGE=%s:%s\n' "${{ env.UI_IMAGE }}" "${{ env.IMAGE_TAG }}"
|
printf 'CRANK_UI_IMAGE=%s:%s\n' '${{ env.UI_IMAGE }}' '${{ env.IMAGE_TAG }}'
|
||||||
} >> "$tmp_env"
|
} >> "$tmp_env"
|
||||||
cat "$tmp_env" | ssh -p "${{ secrets.DEPLOY_PORT }}" "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" \
|
cat "$tmp_env" | ssh -p '${{ secrets.DEPLOY_PORT }}' '${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}' \
|
||||||
"mkdir -p '${{ secrets.DEPLOY_PATH }}' && cat > '${{ secrets.DEPLOY_PATH }}/.env'"
|
"mkdir -p '${{ secrets.DEPLOY_PATH }}' && cat > '${{ secrets.DEPLOY_PATH }}/.env'"
|
||||||
rm -f "$tmp_env"
|
rm -f "$tmp_env"
|
||||||
|
|
||||||
- name: Validate required environment variables
|
- name: Validate required environment variables
|
||||||
run: |
|
run: |
|
||||||
ssh -p "${{ secrets.DEPLOY_PORT }}" "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" "
|
ssh -p '${{ secrets.DEPLOY_PORT }}' '${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}' "
|
||||||
set -e
|
set -e
|
||||||
cd '${{ secrets.DEPLOY_PATH }}'
|
cd '${{ secrets.DEPLOY_PATH }}'
|
||||||
required_vars='
|
required_vars='
|
||||||
@@ -203,10 +172,10 @@ jobs:
|
|||||||
|
|
||||||
- name: Deploy with Docker Compose
|
- name: Deploy with Docker Compose
|
||||||
run: |
|
run: |
|
||||||
ssh -p "${{ secrets.DEPLOY_PORT }}" "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" "
|
ssh -p '${{ secrets.DEPLOY_PORT }}' '${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}' "
|
||||||
set -e
|
set -e
|
||||||
cd '${{ secrets.DEPLOY_PATH }}'
|
cd '${{ secrets.DEPLOY_PATH }}'
|
||||||
echo '${{ secrets.DEPLOY_REGISTRY_TOKEN }}' | docker login ghcr.io -u '${{ secrets.DEPLOY_REGISTRY_USER }}' --password-stdin
|
echo '${{ secrets.DEPLOY_REGISTRY_TOKEN }}' | docker login '${{ env.REGISTRY }}' -u '${{ secrets.DEPLOY_REGISTRY_USER }}' --password-stdin
|
||||||
docker compose config -q
|
docker compose config -q
|
||||||
docker compose pull admin-api mcp-server ui
|
docker compose pull admin-api mcp-server ui
|
||||||
docker compose up -d --remove-orphans
|
docker compose up -d --remove-orphans
|
||||||
@@ -214,7 +183,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Verify health endpoints
|
- name: Verify health endpoints
|
||||||
run: |
|
run: |
|
||||||
ssh -p "${{ secrets.DEPLOY_PORT }}" "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" "
|
ssh -p '${{ secrets.DEPLOY_PORT }}' '${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}' "
|
||||||
set -e
|
set -e
|
||||||
cd '${{ secrets.DEPLOY_PATH }}'
|
cd '${{ secrets.DEPLOY_PATH }}'
|
||||||
for attempt in \$(seq 1 30); do
|
for attempt in \$(seq 1 30); do
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
name: Community Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: git.itexp.me
|
||||||
|
IMAGE_TAG: ${{ gitea.ref_name }}
|
||||||
|
ADMIN_API_IMAGE: git.itexp.me/bsodfather/crank-community-admin-api
|
||||||
|
MCP_SERVER_IMAGE: git.itexp.me/bsodfather/crank-community-mcp-server
|
||||||
|
UI_IMAGE: git.itexp.me/bsodfather/crank-community-ui
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: [self-hosted, linux, x64]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Verify runner toolchain
|
||||||
|
run: |
|
||||||
|
rustc --version
|
||||||
|
cargo --version
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
docker --version
|
||||||
|
|
||||||
|
- name: Build release binaries
|
||||||
|
run: cargo build --release -p admin-api -p mcp-server
|
||||||
|
|
||||||
|
- name: Install UI dependencies
|
||||||
|
working-directory: apps/ui
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build UI dist
|
||||||
|
working-directory: apps/ui
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Package release artifacts
|
||||||
|
run: |
|
||||||
|
mkdir -p dist/release
|
||||||
|
cp target/release/admin-api dist/release/admin-api
|
||||||
|
cp target/release/mcp-server dist/release/mcp-server
|
||||||
|
tar -C dist/release -czf dist/crank-community-admin-api-${IMAGE_TAG}.tar.gz admin-api
|
||||||
|
tar -C dist/release -czf dist/crank-community-mcp-server-${IMAGE_TAG}.tar.gz mcp-server
|
||||||
|
tar -C apps/ui/dist -czf dist/crank-community-ui-${IMAGE_TAG}.tar.gz .
|
||||||
|
sha256sum \
|
||||||
|
dist/crank-community-admin-api-${IMAGE_TAG}.tar.gz \
|
||||||
|
dist/crank-community-mcp-server-${IMAGE_TAG}.tar.gz \
|
||||||
|
dist/crank-community-ui-${IMAGE_TAG}.tar.gz \
|
||||||
|
> dist/crank-community-${IMAGE_TAG}-checksums.txt
|
||||||
|
|
||||||
|
- name: Generate SBOM
|
||||||
|
run: |
|
||||||
|
docker run --rm -v "$PWD:/workspace" anchore/syft:latest \
|
||||||
|
dir:/workspace -o spdx-json \
|
||||||
|
> dist/crank-community-${IMAGE_TAG}-sbom.spdx.json
|
||||||
|
|
||||||
|
- name: Login to registry
|
||||||
|
run: |
|
||||||
|
printf '%s' '${{ secrets.DEPLOY_REGISTRY_TOKEN }}' | \
|
||||||
|
docker login '${{ env.REGISTRY }}' -u '${{ secrets.DEPLOY_REGISTRY_USER }}' --password-stdin
|
||||||
|
|
||||||
|
- name: Build and push release images
|
||||||
|
run: |
|
||||||
|
docker build -f apps/admin-api/Dockerfile \
|
||||||
|
-t '${{ env.ADMIN_API_IMAGE }}:${{ env.IMAGE_TAG }}' \
|
||||||
|
-t '${{ env.ADMIN_API_IMAGE }}:latest' .
|
||||||
|
docker build -f apps/mcp-server/Dockerfile \
|
||||||
|
-t '${{ env.MCP_SERVER_IMAGE }}:${{ env.IMAGE_TAG }}' \
|
||||||
|
-t '${{ env.MCP_SERVER_IMAGE }}:latest' .
|
||||||
|
docker build -f apps/ui/Dockerfile \
|
||||||
|
-t '${{ env.UI_IMAGE }}:${{ env.IMAGE_TAG }}' \
|
||||||
|
-t '${{ env.UI_IMAGE }}:latest' .
|
||||||
|
docker push '${{ env.ADMIN_API_IMAGE }}:${{ env.IMAGE_TAG }}'
|
||||||
|
docker push '${{ env.ADMIN_API_IMAGE }}:latest'
|
||||||
|
docker push '${{ env.MCP_SERVER_IMAGE }}:${{ env.IMAGE_TAG }}'
|
||||||
|
docker push '${{ env.MCP_SERVER_IMAGE }}:latest'
|
||||||
|
docker push '${{ env.UI_IMAGE }}:${{ env.IMAGE_TAG }}'
|
||||||
|
docker push '${{ env.UI_IMAGE }}:latest'
|
||||||
|
|
||||||
|
- name: Show release bundle summary
|
||||||
|
run: |
|
||||||
|
ls -lh dist
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
name: Community Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: release-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
IMAGE_TAG: ${{ github.ref_name }}
|
|
||||||
ADMIN_API_IMAGE: ghcr.io/${{ github.repository_owner }}/crank-community-admin-api
|
|
||||||
MCP_SERVER_IMAGE: ghcr.io/${{ github.repository_owner }}/crank-community-mcp-server
|
|
||||||
UI_IMAGE: ghcr.io/${{ github.repository_owner }}/crank-community-ui
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-release-assets:
|
|
||||||
runs-on: [self-hosted, linux, x64]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
|
||||||
uses: dtolnay/rust-toolchain@master
|
|
||||||
with:
|
|
||||||
toolchain: 1.85.0
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: 22
|
|
||||||
|
|
||||||
- name: Build release binaries
|
|
||||||
run: cargo build --release -p admin-api -p mcp-server
|
|
||||||
|
|
||||||
- name: Install UI dependencies
|
|
||||||
working-directory: apps/ui
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Build UI dist
|
|
||||||
working-directory: apps/ui
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
- name: Package release artifacts
|
|
||||||
run: |
|
|
||||||
mkdir -p dist/release
|
|
||||||
cp target/release/admin-api dist/release/admin-api
|
|
||||||
cp target/release/mcp-server dist/release/mcp-server
|
|
||||||
tar -C dist/release -czf dist/crank-community-admin-api-${IMAGE_TAG}.tar.gz admin-api
|
|
||||||
tar -C dist/release -czf dist/crank-community-mcp-server-${IMAGE_TAG}.tar.gz mcp-server
|
|
||||||
tar -C apps/ui/dist -czf dist/crank-community-ui-${IMAGE_TAG}.tar.gz .
|
|
||||||
sha256sum \
|
|
||||||
dist/crank-community-admin-api-${IMAGE_TAG}.tar.gz \
|
|
||||||
dist/crank-community-mcp-server-${IMAGE_TAG}.tar.gz \
|
|
||||||
dist/crank-community-ui-${IMAGE_TAG}.tar.gz \
|
|
||||||
> dist/crank-community-${IMAGE_TAG}-checksums.txt
|
|
||||||
|
|
||||||
- name: Generate SBOM
|
|
||||||
run: |
|
|
||||||
docker run --rm -v "$PWD:/workspace" anchore/syft:latest \
|
|
||||||
dir:/workspace -o spdx-json \
|
|
||||||
> dist/crank-community-${IMAGE_TAG}-sbom.spdx.json
|
|
||||||
|
|
||||||
- name: Upload release artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: community-release-artifacts
|
|
||||||
path: |
|
|
||||||
dist/crank-community-admin-api-${{ env.IMAGE_TAG }}.tar.gz
|
|
||||||
dist/crank-community-mcp-server-${{ env.IMAGE_TAG }}.tar.gz
|
|
||||||
dist/crank-community-ui-${{ env.IMAGE_TAG }}.tar.gz
|
|
||||||
dist/crank-community-${{ env.IMAGE_TAG }}-checksums.txt
|
|
||||||
dist/crank-community-${{ env.IMAGE_TAG }}-sbom.spdx.json
|
|
||||||
|
|
||||||
publish-images:
|
|
||||||
runs-on: [self-hosted, linux, x64]
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- name: admin-api
|
|
||||||
dockerfile: apps/admin-api/Dockerfile
|
|
||||||
image: ghcr.io/${{ github.repository_owner }}/crank-community-admin-api
|
|
||||||
- name: mcp-server
|
|
||||||
dockerfile: apps/mcp-server/Dockerfile
|
|
||||||
image: ghcr.io/${{ github.repository_owner }}/crank-community-mcp-server
|
|
||||||
- name: ui
|
|
||||||
dockerfile: apps/ui/Dockerfile
|
|
||||||
image: ghcr.io/${{ github.repository_owner }}/crank-community-ui
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v4
|
|
||||||
|
|
||||||
- name: Log in to GHCR
|
|
||||||
uses: docker/login-action@v4
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build and push ${{ matrix.name }}
|
|
||||||
uses: docker/build-push-action@v7
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ${{ matrix.dockerfile }}
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
${{ matrix.image }}:${{ env.IMAGE_TAG }}
|
|
||||||
${{ matrix.image }}:latest
|
|
||||||
|
|
||||||
github-release:
|
|
||||||
needs:
|
|
||||||
- build-release-assets
|
|
||||||
- publish-images
|
|
||||||
runs-on: [self-hosted, linux, x64]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Download release artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: community-release-artifacts
|
|
||||||
path: dist
|
|
||||||
|
|
||||||
- name: Publish GitHub Release
|
|
||||||
uses: softprops/action-gh-release@v2
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
dist/crank-community-admin-api-${{ env.IMAGE_TAG }}.tar.gz
|
|
||||||
dist/crank-community-mcp-server-${{ env.IMAGE_TAG }}.tar.gz
|
|
||||||
dist/crank-community-ui-${{ env.IMAGE_TAG }}.tar.gz
|
|
||||||
dist/crank-community-${{ env.IMAGE_TAG }}-checksums.txt
|
|
||||||
dist/crank-community-${{ env.IMAGE_TAG }}-sbom.spdx.json
|
|
||||||
@@ -93,13 +93,15 @@ Crank - платформа для публикации внешних API в в
|
|||||||
В репозитории настроены:
|
В репозитории настроены:
|
||||||
|
|
||||||
- `CI` для Rust, UI и deployment manifests;
|
- `CI` для Rust, UI и deployment manifests;
|
||||||
- `CD`, который после успешного `CI` на `main` собирает versioned images, пушит их в `GHCR` и деплоит Community через `deploy/community/docker-compose.yml`;
|
- `CD`, который на `push` в `main` собирает versioned images, пушит их в registry Gitea и деплоит Community через `deploy/community/docker-compose.yml`;
|
||||||
|
- tag-based release workflow для сборки release bundle и versioned images;
|
||||||
- containerized Community deployment через `deploy/community/docker-compose.yml`.
|
- containerized Community deployment через `deploy/community/docker-compose.yml`.
|
||||||
|
|
||||||
Важно:
|
Важно:
|
||||||
|
|
||||||
- GitHub Actions в этом репозитории рассчитаны только на `self-hosted` runner;
|
- workflows лежат в `.gitea/workflows`;
|
||||||
- `ubuntu-latest`, `actions/cache` и `type=gha` intentionally не используются, чтобы не тратить платные GitHub-hosted минуты и cache quota на private repository.
|
- Gitea Actions в этом репозитории рассчитаны только на `self-hosted` runner;
|
||||||
|
- внешние GitHub-specific механики вроде `workflow_run`, `actions/upload-artifact`, `softprops/action-gh-release` и `ghcr.io` intentionally не используются.
|
||||||
|
|
||||||
## Поддерживаемые протоколы
|
## Поддерживаемые протоколы
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
- `deploy/community/docker-compose.yml`
|
- `deploy/community/docker-compose.yml`
|
||||||
- `deploy/community/.env.example`
|
- `deploy/community/.env.example`
|
||||||
- `.github/workflows/ci.yml`
|
- `.gitea/workflows/ci.yml`
|
||||||
- `.github/workflows/deploy.yml`
|
- `.gitea/workflows/deploy.yml`
|
||||||
- `docs/deployment.md`
|
- `docs/deployment.md`
|
||||||
- `docs/deploy-and-staging-smoke.md`
|
- `docs/deploy-and-staging-smoke.md`
|
||||||
- `docs/authenticated-staging-pass.md`
|
- `docs/authenticated-staging-pass.md`
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
- задеплоенный стек `ui`, `admin-api`, `mcp-server`, `postgres`;
|
- задеплоенный стек `ui`, `admin-api`, `mcp-server`, `postgres`;
|
||||||
- корректный `.env` на сервере;
|
- корректный `.env` на сервере;
|
||||||
- валидный deploy через `.github/workflows/deploy.yml`;
|
- валидный deploy через `.gitea/workflows/deploy.yml`;
|
||||||
- server deployment path, собранный из `deploy/community/docker-compose.yml`;
|
- server deployment path, собранный из `deploy/community/docker-compose.yml`;
|
||||||
- `CRANK_DEMO_SEED=true`, если нужен предзаполненный smoke state;
|
- `CRANK_DEMO_SEED=true`, если нужен предзаполненный smoke state;
|
||||||
- bootstrap admin credentials для входа в UI.
|
- bootstrap admin credentials для входа в UI.
|
||||||
|
|||||||
+5
-5
@@ -38,8 +38,8 @@
|
|||||||
- `deploy/community/docker-compose.yml` как canonical Community deployment manifest;
|
- `deploy/community/docker-compose.yml` как canonical Community deployment manifest;
|
||||||
- `deploy/community/.env.example` как canonical Community runtime env template;
|
- `deploy/community/.env.example` как canonical Community runtime env template;
|
||||||
- `docker-compose.yml` и root `.env.example` только как local development convenience layers, а не как future private delivery boundary;
|
- `docker-compose.yml` и root `.env.example` только как local development convenience layers, а не как future private delivery boundary;
|
||||||
- `.github/workflows/ci.yml`;
|
- `.gitea/workflows/ci.yml`;
|
||||||
- `.github/workflows/deploy.yml`;
|
- `.gitea/workflows/deploy.yml`;
|
||||||
- примеры reverse proxy конфигураций.
|
- примеры reverse proxy конфигураций.
|
||||||
|
|
||||||
Рекомендуемое стартовое распределение портов:
|
Рекомендуемое стартовое распределение портов:
|
||||||
@@ -236,9 +236,9 @@ CD для MVP должен:
|
|||||||
|
|
||||||
Для текущего проекта базовая рекомендуемая схема:
|
Для текущего проекта базовая рекомендуемая схема:
|
||||||
|
|
||||||
- `GHCR` как registry;
|
- registry на том же Gitea instance;
|
||||||
- versioned tags по `git sha`;
|
- versioned tags по `git sha`;
|
||||||
- `docker/buildx` cache в GitHub Actions;
|
- self-hosted Gitea Actions runner;
|
||||||
- на сервере только `pull + restart`, без `docker compose up --build`.
|
- на сервере только `pull + restart`, без `docker compose up --build`.
|
||||||
|
|
||||||
Для private registry на сервере нужны отдельные deployment secrets:
|
Для private registry на сервере нужны отдельные deployment secrets:
|
||||||
@@ -251,7 +251,7 @@ CD для MVP должен:
|
|||||||
Монолитный `DEPLOY_ENV_FILE` больше не используется.
|
Монолитный `DEPLOY_ENV_FILE` больше не используется.
|
||||||
|
|
||||||
Workflow доставляет именно `deploy/community/docker-compose.yml` как public Community deployment manifest
|
Workflow доставляет именно `deploy/community/docker-compose.yml` как public Community deployment manifest
|
||||||
и собирает `.env` на сервере из отдельных GitHub secrets. Для runtime-переменных нужно
|
и собирает `.env` на сервере из отдельных Gitea secrets. Для runtime-переменных нужно
|
||||||
создавать secrets с теми же именами, что и у приложений:
|
создавать secrets с теми же именами, что и у приложений:
|
||||||
|
|
||||||
- `POSTGRES_HOST`
|
- `POSTGRES_HOST`
|
||||||
|
|||||||
@@ -1570,22 +1570,22 @@
|
|||||||
|
|
||||||
<task id="6.1" parallel="false" location="crank-community">
|
<task id="6.1" parallel="false" location="crank-community">
|
||||||
<name>Community release pipeline</name>
|
<name>Community release pipeline</name>
|
||||||
<create path=".github/workflows/release.yml">
|
<create path=".gitea/workflows/release.yml">
|
||||||
Trigger: push tag v*.
|
Trigger: push tag v*.
|
||||||
Steps: build admin-api, mcp-server, UI dist; build Docker images; push to ghcr.io/<owner>/crank-community-{admin-api,mcp-server}; attach checksums + SBOM; create GitHub Release.
|
Steps: build admin-api, mcp-server, UI dist; build Docker images; push to the Gitea container registry; assemble checksums + SBOM on the self-hosted runner.
|
||||||
</create>
|
</create>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task id="6.2" parallel="false" location="crank-enterprise">
|
<task id="6.2" parallel="false" location="crank-enterprise">
|
||||||
<name>Enterprise release pipeline</name>
|
<name>Enterprise release pipeline</name>
|
||||||
<create path=".github/workflows/release.yml">
|
<create path=".gitea/workflows/release.yml">
|
||||||
Push tag v* triggers: fetch submodule at the pinned community tag; build enterprise-admin-api / enterprise-mcp-server / enterprise-ui-overlay; build Docker images; push to private registry; sign with cosign; produce SBOM.
|
Push tag v* triggers: fetch submodule at the pinned community tag; build enterprise-admin-api / enterprise-mcp-server / enterprise-ui-overlay; build Docker images; push to private registry; sign with cosign; produce SBOM.
|
||||||
</create>
|
</create>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task id="6.3" parallel="false" location="crank-cloud">
|
<task id="6.3" parallel="false" location="crank-cloud">
|
||||||
<name>Cloud release pipeline + control-plane rollout</name>
|
<name>Cloud release pipeline + control-plane rollout</name>
|
||||||
<create path=".github/workflows/release.yml">
|
<create path=".gitea/workflows/release.yml">
|
||||||
Build cloud-admin-api / cloud-mcp-server / cloud-control-plane; push to managed registry; trigger blue/green rollout in hosted environment.
|
Build cloud-admin-api / cloud-mcp-server / cloud-control-plane; push to managed registry; trigger blue/green rollout in hosted environment.
|
||||||
</create>
|
</create>
|
||||||
</task>
|
</task>
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ Demo/deployment:
|
|||||||
- стабильный `Streamable HTTP` endpoint для MCP.
|
- стабильный `Streamable HTTP` endpoint для MCP.
|
||||||
- containerized runtime через `Docker` и `docker-compose`.
|
- containerized runtime через `Docker` и `docker-compose`.
|
||||||
- optional shared cache layer через `Valkey/Redis`.
|
- optional shared cache layer через `Valkey/Redis`.
|
||||||
- registry-backed image rollout через `GHCR` или совместимый registry.
|
- registry-backed image rollout через Gitea Container Registry или совместимый registry.
|
||||||
|
|
||||||
### Cache env
|
### Cache env
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user