Skip to content

feat: 2d hypergraph visual polish #6363

feat: 2d hypergraph visual polish

feat: 2d hypergraph visual polish #6363

Workflow file for this run

name: Apps Deployment
on:
workflow_dispatch:
inputs:
skip_build:
required: false
description: "Skip Docker Build"
type: boolean
default: false
push:
pull_request:
types:
- opened
- reopened
- closed
- synchronize
permissions: write-all
jobs:
pr-check:
runs-on: ubicloud-standard-2
outputs:
skip: ${{ github.event_name == 'push' && steps.findPr.outputs.number != '' }}
pr_exists: ${{ steps.findPr.outputs.number != '' }}
steps:
- uses: jwalton/gh-find-current-pr@master
id: findPr
- name: Debug PR info
run: |
echo "PR exists: ${{ steps.findPr.outputs.number != '' }}"
echo "PR number: ${{ steps.findPr.outputs.number }}"
echo "Is push based: ${{ github.event_name == 'push' }}"
find-deployments:
needs: pr-check
if: |
github.event.pull_request.state != 'closed' &&
(github.ref_name == 'main' || github.ref_name == 'dev'
|| needs.pr-check.outputs.skip == 'false')
runs-on: ubicloud-standard-2
outputs:
deploy_matrix: ${{ steps.parse.outputs.deploy_matrix }}
pr_preview_matrix: ${{ steps.parse.outputs.pr_preview_matrix }}
all_apps: ${{ steps.parse.outputs.all_apps }}
preview_domains: ${{ steps.parse.outputs.preview_domains }}
runners: ${{ steps.parse.outputs.runners }}
package_paths: ${{ steps.parse.outputs.package_paths }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install turbo
run: pnpm add turbo@^2.3.3 --global
- name: Get apps list
id: apps
run: |
# List both apps and services directories
apps_list=$(ls -d apps/* 2>/dev/null | sed 's/apps\///' || echo "")
services_list=$(ls -d services/* 2>/dev/null | sed 's/services\///' || echo "")
# Combine both lists
all_apps=$(echo -e "${apps_list}\n${services_list}" | grep -v '^$' | jq -R -s -c 'split("\n")[:-1]')
echo "all_apps=$all_apps" >> $GITHUB_OUTPUT
echo "All apps in workspace:"
echo "$all_apps" | jq '.'
- name: Get build json (PR based)
if: github.event_name == 'pull_request'
run: |
pnpm exec turbo run build --filter="...[origin/${{ github.base_ref }}]" --dry-run=json 2>/dev/null > build.json
- name: Get build json (Push based)
if: github.event_name == 'push'
run: |
if git rev-parse --quiet --verify ${{ github.event.before }}^{commit}; then
BASE_COMMIT="$(git merge-base ${{ github.event.before }} HEAD)"
pnpm exec turbo run build --filter="...[${BASE_COMMIT}]" --dry-run=json 2>/dev/null > build.json
else
pnpm exec turbo run build --dry-run=json 2>/dev/null > build.json
fi
- name: Get changed packages from turbo
id: turbo
run: |
changed_packages=$(cat build.json | jq -c '[.tasks[].package]')
echo "changed_packages=$changed_packages" >> $GITHUB_OUTPUT
echo "Changed packages from turbo:"
echo "$changed_packages" | jq '.'
# Extract package directories mapping (package -> directory parent folder)
# e.g., {"torus-cache": "services", "torus-wallet": "apps"}
package_paths=$(cat build.json | jq -c '
[.tasks[] | {key: .package, value: (.directory | split("/")[0])}]
| unique_by(.key)
| from_entries
')
echo "package_paths=$package_paths" >> $GITHUB_OUTPUT
echo "Package paths:"
echo "$package_paths" | jq '.'
# Get paths for ALL packages
all_package_paths=$(pnpm exec turbo run build --dry-run=json 2>/dev/null | jq -c '
[.tasks[] | {key: .package, value: (.directory | split("/")[0])}]
| unique_by(.key)
| from_entries
')
echo "all_package_paths=$all_package_paths" >> $GITHUB_OUTPUT
echo "All package paths:"
echo "$all_package_paths" | jq '.'
- name: Filter changed apps
id: changed
run: |
set -euo pipefail
all_apps='${{ steps.apps.outputs.all_apps }}'
changed_packages='${{ steps.turbo.outputs.changed_packages }}'
changed_apps=$(echo "$all_apps" | jq -c --argjson changed "$changed_packages" \
'[.[] | select(. as $pkg | $changed | any(. == $pkg))]')
echo "changed_apps=$changed_apps" >> $GITHUB_OUTPUT
echo 'Changed apps:'
echo "$changed_apps" | jq '.'
- name: Parse deployment config
id: parse
run: |
set -euo pipefail
config=$(cat .github/ci-config.json)
changed_apps='${{ steps.changed.outputs.changed_apps }}'
declare -A apps_to_deploy
all_apps=$(echo "$config" | jq -c '[.apps | keys[]]')
# For each app in config, check if it was changed and mark for deploy.
# The deploys list is used to mark what dependency apps should be deployed
# as well.
for app in $(echo "$changed_apps" | jq -r '.[]'); do
apps_to_deploy["$app"]=1
dependent_apps=$(echo "$config" | jq -r ".apps[\"$app\"].deploys[]? // empty")
for dep_app in $dependent_apps; do
apps_to_deploy["$dep_app"]=1
done
done
deploy_apps=()
pr_apps=()
# For all apps marked for deploy, we aggregate
# those that must deploy PR previews and filter prod-only apps on non-main branches.
for app in "${!apps_to_deploy[@]}"; do
# Check if app is prod-only and we're NOT on main branch
prod_only=$(echo "$config" | jq -r ".apps[\"$app\"].prod_only // false")
if [ "$prod_only" == "true" ] && [ "${{ github.ref_name }}" != "main" ]; then
echo "Skipping $app (prod-only, current branch: ${{ github.ref_name }})"
continue
fi
deploy_apps+=("\"$app\"")
pr_preview=$(echo "$config" | jq -r ".apps[\"$app\"].pr_preview // false")
if [ "$pr_preview" == "true" ]; then
pr_apps+=("\"$app\"")
fi
done
# Github matrix shenanigans
if [ ${#deploy_apps[@]} -eq 0 ]; then
deploy_json="[]"
else
deploy_json=$(IFS=,; echo "[${deploy_apps[*]}]")
fi
if [ ${#pr_apps[@]} -eq 0 ]; then
pr_json="[]"
else
pr_json=$(IFS=,; echo "[${pr_apps[*]}]")
fi
preview_domains=$(echo "$config" | jq -c '[.apps | to_entries[] | select(.value.preview_domain != null) | {key: .key, value: .value.preview_domain}] | from_entries')
# Build runners mapping (app -> runner, default to ubicloud-standard-16)
runners=$(echo "$config" | jq -c '[.apps | to_entries[] | {key: .key, value: (.value.runner // "ubicloud-standard-16")}] | from_entries')
# Use complete package paths from turbo
package_paths='${{ steps.turbo.outputs.all_package_paths }}'
echo "deploy_matrix=$deploy_json" >> $GITHUB_OUTPUT
echo "pr_preview_matrix=$pr_json" >> $GITHUB_OUTPUT
echo "all_apps=$all_apps" >> $GITHUB_OUTPUT
echo "preview_domains=$preview_domains" >> $GITHUB_OUTPUT
echo "runners=$runners" >> $GITHUB_OUTPUT
echo "package_paths=$package_paths" >> $GITHUB_OUTPUT
echo "Apps to deploy: $deploy_json"
echo "Apps with PR preview: $pr_json"
echo "Runners: $runners"
echo "Package paths: $package_paths"
###################################
###### REGULAR DEPLOYMENTS #######
###################################
deploy:
needs: find-deployments
if: |
inputs.skip_build ||
contains(github.event.head_commit.message, 'skip build') ||
(needs.find-deployments.outputs.deploy_matrix != '[]' &&
(github.ref_name == 'main' || github.ref_name == 'dev' || github.ref_name == 'cicd'))
strategy:
matrix:
app: ${{ fromJson(needs.find-deployments.outputs.deploy_matrix) }}
fail-fast: false
uses: ./.github/workflows/app-deployment-template.yml
secrets: inherit
with:
app_name: ${{ matrix.app }}
app_path: ${{ fromJson(needs.find-deployments.outputs.package_paths)[matrix.app] }}
skip_build: ${{ inputs.skip_build || false }}
runner: ${{ fromJson(needs.find-deployments.outputs.runners)[matrix.app] }}
###################################
######## DRY RUN BUILDS ##########
###################################
dry-run:
needs: [find-deployments, pr-check]
if: |
github.ref_name != 'main' &&
github.ref_name != 'dev' &&
github.ref_name != 'cicd' &&
needs.find-deployments.outputs.deploy_matrix != '[]' &&
needs.pr-check.outputs.pr_exists == 'false'
strategy:
matrix:
app: ${{ fromJson(needs.find-deployments.outputs.deploy_matrix) }}
fail-fast: false
uses: ./.github/workflows/dry-run-build-template.yml
secrets: inherit
with:
app_name: ${{ matrix.app }}
runner: ${{ fromJson(needs.find-deployments.outputs.runners)[matrix.app] }}
app_path: ${{ fromJson(needs.find-deployments.outputs.package_paths)[matrix.app] }}
###################################
########### PR PREVIEW ############
###################################
pr-preview-deploy:
needs: find-deployments
if: |
github.event.pull_request.state == 'open' && !github.event.repository.fork
&& !github.event.pull_request.draft
&& github.head_ref != 'main' && github.head_ref != 'dev'
&& needs.find-deployments.outputs.pr_preview_matrix != '[]'
strategy:
matrix:
app: ${{ fromJson(needs.find-deployments.outputs.pr_preview_matrix) }}
fail-fast: false
uses: ./.github/workflows/pr-preview-template.yml
secrets: inherit
with:
app_name: ${{ matrix.app }}
runner: ${{ fromJson(needs.find-deployments.outputs.runners)[matrix.app] }}
app_path: ${{ fromJson(needs.find-deployments.outputs.package_paths)[matrix.app] }}
pr-preview-cleanup:
needs: find-deployments
if: |
github.event.pull_request.state == 'closed'
&& github.head_ref != 'main' && github.head_ref != 'dev'
strategy:
matrix:
app: ${{ fromJson(needs.find-deployments.outputs.all_apps) }}
fail-fast: false
uses: ./.github/workflows/pr-preview-template.yml
secrets: inherit
with:
app_name: ${{ matrix.app }}
runner: ${{ fromJson(needs.find-deployments.outputs.runners)[matrix.app] }}
app_path: ${{ fromJson(needs.find-deployments.outputs.package_paths)[matrix.app] }}
cleanup: true
deployment-summary:
if: always()
needs:
[find-deployments, deploy, dry-run, pr-preview-deploy, pr-preview-cleanup]
runs-on: ubicloud-standard-2
steps:
- name: Generate deployment summary
run: |
set -euo pipefail
echo "## 🚀 Deployment Overview" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Environment detection
if [ "${{ github.ref_name }}" == "main" ]; then
ENV_NAME="Production"
ENV_ICON="🏭"
elif [ "${{ github.ref_name }}" == "dev" ]; then
ENV_NAME="Development"
ENV_ICON="🧪"
else
ENV_NAME="Preview/Dry-run"
ENV_ICON="👀"
fi
echo "**Environment:** $ENV_ICON $ENV_NAME (\`${{ github.ref_name }}\`)" >> $GITHUB_STEP_SUMMARY
echo "**Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
all_apps='${{ needs.find-deployments.outputs.all_apps }}'
deploy_apps='${{ needs.find-deployments.outputs.deploy_matrix }}'
# Production/Dev Deployments
if [ "${{ github.ref_name }}" == "main" ] || [ "${{ github.ref_name }}" == "dev" ] || [ "${{ github.ref_name }}" == "cicd" ]; then
echo "### 🏗️ Application Deployments" >> $GITHUB_STEP_SUMMARY
echo "| Application | Changed | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-------------|---------|--------|" >> $GITHUB_STEP_SUMMARY
deploy_result='${{ needs.deploy.result }}'
if [ "$deploy_apps" != "[]" ]; then
for app in $(echo "$deploy_apps" | jq -r '.[]'); do
case "$deploy_result" in
"success") deploy_icon="✅"; deploy_text="Deployed";;
"failure") deploy_icon="❌"; deploy_text="Failed";;
"skipped") deploy_icon="⏭️"; deploy_text="Skipped";;
*) deploy_icon="❓"; deploy_text="Unknown";;
esac
echo "| ${app} | ✅ Yes | ${deploy_icon} ${deploy_text} |" >> $GITHUB_STEP_SUMMARY
done
fi
fi
# PR Previews
if [ "${{ github.event_name }}" == "pull_request" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔍 PR Preview Deployments" >> $GITHUB_STEP_SUMMARY
echo "| Application | Status | Preview URL |" >> $GITHUB_STEP_SUMMARY
echo "|-------------|--------|-------------|" >> $GITHUB_STEP_SUMMARY
preview_domains='${{ needs.find-deployments.outputs.preview_domains }}'
pr_apps='${{ needs.find-deployments.outputs.pr_preview_matrix }}'
deploy_result='${{ needs.pr-preview-deploy.result }}'
cleanup_result='${{ needs.pr-preview-cleanup.result }}'
if [ "$pr_apps" != "[]" ]; then
for app in $(echo "$pr_apps" | jq -r '.[]'); do
if [ "$deploy_result" == "success" ]; then
preview_domain=$(echo "$preview_domains" | jq -r ".[\"$app\"] // empty")
if [ -n "$preview_domain" ]; then
preview_url="https://pr-${{ github.event.number }}.${preview_domain}"
else
preview_url="https://pr-${{ github.event.number }}.${app}.torus.network"
fi
echo "| ${app} | ✅ Deployed | [Preview](${preview_url}) |" >> $GITHUB_STEP_SUMMARY
elif [ "$cleanup_result" == "success" ]; then
echo "| ${app} | 🗑️ Deleted | - |" >> $GITHUB_STEP_SUMMARY
elif [ "$deploy_result" == "skipped" ] && [ "$cleanup_result" == "skipped" ]; then
echo "| ${app} | ⏭️ No Changes | - |" >> $GITHUB_STEP_SUMMARY
else
echo "| ${app} | ❌ Failed | - |" >> $GITHUB_STEP_SUMMARY
fi
done
fi
fi
# Dry Run Builds
if [ "${{ github.ref_name }}" != "main" ] && [ "${{ github.ref_name }}" != "dev" ] && [ "${{ github.ref_name }}" != "cicd" ] && [ "${{ github.event_name }}" != "pull_request" ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔨 Dry Run Builds" >> $GITHUB_STEP_SUMMARY
echo "| Application | Build Status |" >> $GITHUB_STEP_SUMMARY
echo "|-------------|--------------|" >> $GITHUB_STEP_SUMMARY
dry_run_result='${{ needs.dry-run.result }}'
if [ "$deploy_apps" != "[]" ]; then
for app in $(echo "$deploy_apps" | jq -r '.[]'); do
case "$dry_run_result" in
"success") echo "| ${app} | ✅ Build Successful |" >> $GITHUB_STEP_SUMMARY;;
"failure") echo "| ${app} | ❌ Build Failed |" >> $GITHUB_STEP_SUMMARY;;
"skipped") echo "| ${app} | ⏭️ Skipped (No Changes) |" >> $GITHUB_STEP_SUMMARY;;
*) echo "| ${app} | ❓ Unknown |" >> $GITHUB_STEP_SUMMARY;;
esac
done
fi
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Workflow Run:** [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY