Skip to content

Merge pull request #780 from seakee/feat/v2-runtime-readiness-observa… #1472

Merge pull request #780 from seakee/feat/v2-runtime-readiness-observa…

Merge pull request #780 from seakee/feat/v2-runtime-readiness-observa… #1472

Workflow file for this run

name: PR Check
on:
pull_request:
branches:
- main
- dev
- v2
types:
- opened
- edited
- reopened
- synchronize
push:
branches:
- main
- dev
- v2
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
changes:
name: Scope
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.classify.outputs.frontend }}
manager_server: ${{ steps.classify.outputs.manager_server }}
runtime_supervisor: ${{ steps.classify.outputs.runtime_supervisor }}
windows_sqlite: ${{ steps.classify.outputs.windows_sqlite }}
native_control: ${{ steps.classify.outputs.native_control }}
docker: ${{ steps.classify.outputs.docker }}
demo_docs: ${{ steps.classify.outputs.demo_docs }}
release_content: ${{ steps.classify.outputs.release_content }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Classify changed paths
id: classify
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
CURRENT_SHA: ${{ github.sha }}
run: |
set -euo pipefail
changed_files="${RUNNER_TEMP}/pr-check-changed-files.bin"
if [ "${EVENT_NAME}" = "pull_request" ]; then
git diff --name-only --no-renames -z "${PR_BASE_SHA}...${PR_HEAD_SHA}" > "${changed_files}"
elif [ -z "${PUSH_BEFORE_SHA}" ] || [[ "${PUSH_BEFORE_SHA}" =~ ^0+$ ]]; then
git show --pretty=format: --name-only --no-renames -z "${CURRENT_SHA}" > "${changed_files}"
else
git diff --name-only --no-renames -z "${PUSH_BEFORE_SHA}..${CURRENT_SHA}" > "${changed_files}"
fi
echo "Changed files:"
while IFS= read -r -d '' file_path; do
printf -- '- %q\n' "${file_path}"
done < "${changed_files}"
node bin/ci/classify-pr-checks.mjs --null < "${changed_files}" >> "${GITHUB_OUTPUT}"
frontend:
name: Frontend
needs: changes
if: needs.changes.outputs.frontend == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci
- name: Type check
run: npm run type-check
- name: Lint
run: npm run lint
- name: Test
run: npm run test
- name: Build
run: npm --workspace apps/web run build:bundle
env:
VERSION: ci
- name: Check demo isolation
run: npm run check:demo-isolation
manager-server:
name: Manager Server
needs: changes
if: needs.changes.outputs.manager_server == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.24.x'
cache-dependency-path: apps/manager-server/go.sum
- name: Test
working-directory: apps/manager-server
run: go test ./...
runtime-supervisor:
name: Runtime Supervisor
needs: changes
if: needs.changes.outputs.runtime_supervisor == 'true'
runs-on: ubuntu-latest
env:
GOWORK: 'off'
GOFLAGS: -mod=readonly
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.24.x'
cache-dependency-path: apps/runtime-supervisor/go.mod
- name: Test
working-directory: apps/runtime-supervisor
run: go test ./...
- name: Vet
working-directory: apps/runtime-supervisor
run: go vet ./...
- name: Portability build
working-directory: apps/runtime-supervisor
shell: bash
run: |
set -euo pipefail
for target in linux/amd64 linux/arm64 windows/amd64; do
echo "Building ${target}"
output="${RUNNER_TEMP}/cpamp-runtime-supervisor-${target%/*}-${target#*/}"
if [ "${target%/*}" = windows ]; then output+=".exe"; fi
CGO_ENABLED=0 GOOS="${target%/*}" GOARCH="${target#*/}" \
go build -trimpath -o "${output}" ./cmd/cpamp-runtime-supervisor
done
- name: Test architecture boundary
run: go test ./bin/ci/runtime-boundary/main.go ./bin/ci/runtime-boundary/main_test.go
- name: Validate architecture boundary
run: go run ./bin/ci/runtime-boundary/main.go
manager-server-windows-sqlite:
name: Manager Server SQLite (Windows)
needs: changes
if: needs.changes.outputs.windows_sqlite == 'true'
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: '1.24.x'
cache-dependency-path: apps/manager-server/go.sum
- name: Test SQLite repository
working-directory: apps/manager-server
run: go test ./internal/repository/sqlite
native-control:
name: Native Control (${{ matrix.os }})
needs: changes
if: needs.changes.outputs.native_control == 'true'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- macos-latest
- ubuntu-latest
- windows-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci
- name: Test native control scripts
run: npx vitest run tests/nativeControlScripts.test.mjs
- name: Validate native packaging script syntax
if: runner.os != 'Windows'
shell: bash
run: bash -n bin/release/package-native.sh
docker-build:
name: Docker Build
runs-on: ubuntu-latest
needs:
- changes
- frontend
- manager-server
if: >-
always() &&
needs.changes.outputs.docker == 'true' &&
(needs.frontend.result == 'success' || needs.frontend.result == 'skipped') &&
(needs['manager-server'].result == 'success' || needs['manager-server'].result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Validate Docker Compose configuration
run: docker compose -f docker-compose.manager.yml config
- name: Build Manager Server image
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: Dockerfile.manager-server
push: false
build-args: |
VERSION=ci
demo-docs:
name: Demo and Docs
needs: changes
if: needs.changes.outputs.demo_docs == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci
- name: Build demo site
run: npm --workspace apps/web run build:demo:bundle
env:
VERSION: ci-demo
- name: Build docs site
run: npm run docs:build
release-content:
name: Release Content
needs: changes
if: needs.changes.outputs.release_content == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Validate changed release content
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PUSH_BEFORE_SHA: ${{ github.event.before }}
CURRENT_SHA: ${{ github.sha }}
run: |
set -euo pipefail
changed_files="${RUNNER_TEMP}/release-content-changed-files.bin"
if [ "${EVENT_NAME}" = "pull_request" ]; then
git diff --name-only --no-renames --diff-filter=A -z "${PR_BASE_SHA}...${PR_HEAD_SHA}" > "${changed_files}"
elif [ -z "${PUSH_BEFORE_SHA}" ] || [[ "${PUSH_BEFORE_SHA}" =~ ^0+$ ]]; then
git show --pretty=format: --name-only --no-renames --diff-filter=A -z "${CURRENT_SHA}" > "${changed_files}"
else
git diff --name-only --no-renames --diff-filter=A -z "${PUSH_BEFORE_SHA}..${CURRENT_SHA}" > "${changed_files}"
fi
npm run --silent release:validate -- --changed-content --null < "${changed_files}"
required:
name: Required checks
needs:
- changes
- frontend
- manager-server
- runtime-supervisor
- manager-server-windows-sqlite
- native-control
- docker-build
- demo-docs
- release-content
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify applicable checks
env:
CHANGES_RESULT: ${{ needs.changes.result }}
FRONTEND_RESULT: ${{ needs.frontend.result }}
MANAGER_SERVER_RESULT: ${{ needs['manager-server'].result }}
RUNTIME_SUPERVISOR_RESULT: ${{ needs['runtime-supervisor'].result }}
WINDOWS_SQLITE_RESULT: ${{ needs['manager-server-windows-sqlite'].result }}
NATIVE_CONTROL_RESULT: ${{ needs['native-control'].result }}
DOCKER_BUILD_RESULT: ${{ needs['docker-build'].result }}
DEMO_DOCS_RESULT: ${{ needs['demo-docs'].result }}
RELEASE_CONTENT_RESULT: ${{ needs['release-content'].result }}
shell: bash
run: |
set -euo pipefail
results=(
"Scope:${CHANGES_RESULT}"
"Frontend:${FRONTEND_RESULT}"
"Manager Server:${MANAGER_SERVER_RESULT}"
"Runtime Supervisor:${RUNTIME_SUPERVISOR_RESULT}"
"Manager Server SQLite (Windows):${WINDOWS_SQLITE_RESULT}"
"Native Control:${NATIVE_CONTROL_RESULT}"
"Docker Build:${DOCKER_BUILD_RESULT}"
"Demo and Docs:${DEMO_DOCS_RESULT}"
"Release Content:${RELEASE_CONTENT_RESULT}"
)
for check in "${results[@]}"; do
name="${check%%:*}"
result="${check#*:}"
case "${result}" in
success|skipped)
echo "${name}: ${result}"
;;
*)
echo "${name} did not complete successfully: ${result:-missing}" >&2
exit 1
;;
esac
done