Redesign of Julia interop, avoiding Jupyter kernel #2814
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: deploy | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| release: | |
| types: [published] | |
| env: | |
| BRANCH_NAME: ${{ github.ref_name }} | |
| permissions: | |
| deployments: write | |
| jobs: | |
| create_deployment: | |
| name: Create GitHub deployment | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'ToposInstitute/CatColab' | |
| outputs: | |
| deployment_id: ${{ steps.create_deployment.outputs.deployment_id }} | |
| steps: | |
| - name: Create new GitHub deployment | |
| id: create_deployment | |
| uses: chrnorm/deployment-action@v2 | |
| with: | |
| token: ${{ github.token }} | |
| environment: netlify-preview | |
| ref: ${{ github.event.pull_request.head.ref }} | |
| sha: ${{ github.event.pull_request.head.sha }} | |
| transient-environment: true | |
| auto-inactive: true | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| - name: Update deployment status to in_progress | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ github.token }} | |
| description: 'Building and deploying...' | |
| state: 'in_progress' | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| deployment-id: ${{ steps.create_deployment.outputs.deployment_id }} | |
| build_dev_docs: | |
| name: Build developer docs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # Need full history for `git log` for cache key | |
| fetch-depth: 0 | |
| - name: Compute cache key | |
| id: cache-key | |
| run: | | |
| hash=$(git log -1 --format="%H" -- dev-docs) | |
| echo "git-hash=${hash}" >> $GITHUB_OUTPUT | |
| echo "Dev docs hash: ${hash}" | |
| - name: Cache dev docs build | |
| id: cache-dev-docs-build | |
| uses: actions/cache@v4 | |
| with: | |
| path: dev-docs/output | |
| key: dev-docs-build-${{ steps.cache-key.outputs.git-hash }} | |
| - name: Setup pnpm | |
| if: steps.cache-dev-docs-build.outputs.cache-hit != 'true' | |
| uses: pnpm/action-setup@v4 | |
| - name: Setup NodeJS | |
| if: steps.cache-dev-docs-build.outputs.cache-hit != 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: "pnpm" | |
| - name: Build developer docs | |
| if: steps.cache-dev-docs-build.outputs.cache-hit != 'true' | |
| run: | | |
| pnpm install | |
| pnpm --filter ./dev-docs run doc | |
| - name: Report cache status | |
| run: | | |
| if [ "${{ steps.cache-dev-docs-build.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ Dev docs restored from cache" | |
| else | |
| echo "🔨 Dev docs built and cached" | |
| fi | |
| - name: Upload developer docs | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dev-docs | |
| path: dev-docs/output | |
| build_frontend: | |
| name: Build frontend | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # Need full history for `git log` for cache key | |
| fetch-depth: 0 | |
| - name: Compute cache key | |
| id: cache-key | |
| run: | | |
| # Get git hash of the most recent commit affecting frontend or any of its dependencies | |
| hash=$(git log -1 --format="%H" -- packages/frontend packages/backend/pkg packages/catlog packages/catlog-wasm packages/notebook-types packages/ui-components Cargo.toml Cargo.lock) | |
| echo "git-hash=${hash}" >> $GITHUB_OUTPUT | |
| echo "Frontend git hash: ${git_hash}" | |
| - name: Cache frontend build | |
| id: cache-frontend-build | |
| # Skip caching for production builds | |
| if: github.event_name != 'release' | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| packages/frontend/dist | |
| key: frontend-build-${{ steps.cache-key.outputs.git-hash }}-${{ github.event_name == 'release' && 'production' || 'staging' }} | |
| - name: Setup pnpm | |
| if: github.event_name == 'release' || steps.cache-frontend-build.outputs.cache-hit != 'true' | |
| uses: pnpm/action-setup@v4 | |
| - name: Setup NodeJS | |
| if: github.event_name == 'release' || steps.cache-frontend-build.outputs.cache-hit != 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: "pnpm" | |
| - name: Install Rust toolchain from file | |
| if: github.event_name == 'release' || steps.cache-frontend-build.outputs.cache-hit != 'true' | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| # Don't override flags in cargo config files. | |
| rustflags: "" | |
| - name: Build for Staging | |
| if: (github.event_name == 'push' || github.event_name == 'pull_request') && steps.cache-frontend-build.outputs.cache-hit != 'true' | |
| run: | | |
| pnpm install | |
| # Uses env from packages/frontend/.env.staging | |
| pnpm --filter ./packages/frontend run build -- --mode staging | |
| - name: Build for Production | |
| if: github.event_name == 'release' | |
| run: | | |
| pnpm install | |
| # Uses env from packages/frontend/.env.production | |
| pnpm --filter ./packages/frontend run build | |
| - name: Report cache status | |
| run: | | |
| if [ "${{ github.event_name }}" = "release" ]; then | |
| echo "🔨 Frontend production build completed (cache disabled)" | |
| elif [ "${{ steps.cache-frontend-build.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ Frontend build restored from cache" | |
| else | |
| echo "🔨 Frontend build completed and cached" | |
| fi | |
| - name: Upload | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: app | |
| path: packages/frontend/dist | |
| - name: Cache frontend docs build | |
| id: cache-frontend-docs | |
| uses: actions/cache@v4 | |
| with: | |
| path: packages/frontend/docs | |
| key: frontend-docs-${{ steps.cache-key.outputs.git-hash }} | |
| - name: Build frontend docs | |
| if: steps.cache-frontend-docs.outputs.cache-hit != 'true' | |
| run: | | |
| pnpm --filter ./packages/frontend run doc | |
| - name: Report frontend docs cache status | |
| run: | | |
| if [ "${{ steps.cache-frontend-docs.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ Frontend docs restored from cache" | |
| else | |
| echo "🔨 Frontend docs built and cached" | |
| fi | |
| - name: Upload frontend docs | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: frontend_docs | |
| path: packages/frontend/docs | |
| build_rust_docs: | |
| name: Build Rust docs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # Need full history for `git log` for cache key | |
| fetch-depth: 0 | |
| - name: Compute cache key | |
| id: cache-key | |
| run: | | |
| # Get git hash for all Rust packages | |
| hash=$(git log -1 --format="%H" -- packages/catlog packages/catlog-wasm packages/backend packages/notebook-types Cargo.toml Cargo.lock) | |
| echo "git-hash=${hash}" >> $GITHUB_OUTPUT | |
| echo "Rust hash: ${hash}" | |
| - name: Cache Rust docs build | |
| id: cache-rust-docs | |
| uses: actions/cache@v4 | |
| with: | |
| path: target/doc | |
| key: rust-docs-${{ steps.cache-key.outputs.git-hash }} | |
| - name: Install Rust toolchain from file | |
| if: steps.cache-rust-docs.outputs.cache-hit != 'true' | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| - name: Build Rust docs | |
| if: steps.cache-rust-docs.outputs.cache-hit != 'true' | |
| run: | | |
| cargo doc --all-features --no-deps --workspace --exclude "migrator" | |
| - name: Report cache status | |
| run: | | |
| if [ "${{ steps.cache-rust-docs.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ Rust docs restored from cache" | |
| else | |
| echo "🔨 Rust docs built and cached" | |
| fi | |
| - name: Upload Rust docs | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: rust_docs | |
| path: target/doc | |
| build_math-docs: | |
| name: Build mathematical docs | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Repository Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| # Need full history for `git log` for cache key | |
| fetch-depth: 0 | |
| - name: Compute cache key | |
| id: cache-key | |
| run: | | |
| hash=$(git log -1 --format="%H" -- math-docs) | |
| echo "git-hash=${hash}" >> $GITHUB_OUTPUT | |
| echo "Math docs hash: ${hash}" | |
| - name: Cache math docs build | |
| id: cache-math-docs | |
| uses: actions/cache@v4 | |
| with: | |
| path: math-docs/output | |
| key: math-docs-${{ steps.cache-key.outputs.git-hash }} | |
| - name: Setup TinyTeX | |
| if: steps.cache-math-docs.outputs.cache-hit != 'true' | |
| uses: r-lib/actions/setup-tinytex@v2 | |
| - name: Install TeX Packages | |
| if: steps.cache-math-docs.outputs.cache-hit != 'true' | |
| run: | | |
| tlmgr update --self | |
| tlmgr install dvisvgm | |
| tlmgr install standalone | |
| tlmgr install pgf | |
| tlmgr install tikz-cd | |
| tlmgr install amsmath | |
| tlmgr install quiver | |
| tlmgr install spath3 | |
| - name: Build mathematical docs | |
| if: steps.cache-math-docs.outputs.cache-hit != 'true' | |
| run: | | |
| cd math-docs | |
| ./forester build | |
| - name: Report cache status | |
| run: | | |
| if [ "${{ steps.cache-math-docs.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ Math docs restored from cache" | |
| else | |
| echo "🔨 Math docs built and cached" | |
| fi | |
| - name: Upload mathematical docs | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: math-docs | |
| path: math-docs/output | |
| build_ui_components: | |
| name: Build ui-components Storybook | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # Need full history for `git log` for cache key | |
| fetch-depth: 0 | |
| - name: Compute cache key | |
| id: cache-key | |
| run: | | |
| hash=$(git log -1 --format="%H" -- packages/ui-components) | |
| echo "git-hash=${hash}" >> $GITHUB_OUTPUT | |
| echo "UI Components hash: ${hash}" | |
| - name: Cache ui-components build | |
| id: cache-ui-components | |
| uses: actions/cache@v4 | |
| with: | |
| path: packages/ui-components/storybook-static | |
| key: ui-components-${{ steps.cache-key.outputs.git-hash }} | |
| - name: Setup pnpm | |
| if: steps.cache-ui-components.outputs.cache-hit != 'true' | |
| uses: pnpm/action-setup@v4 | |
| - name: Setup NodeJS | |
| if: steps.cache-ui-components.outputs.cache-hit != 'true' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: "pnpm" | |
| - name: Install dependencies | |
| if: steps.cache-ui-components.outputs.cache-hit != 'true' | |
| run: pnpm install | |
| - name: Build ui-components Storybook | |
| if: steps.cache-ui-components.outputs.cache-hit != 'true' | |
| run: pnpm --filter ./packages/ui-components run build | |
| - name: Report cache status | |
| run: | | |
| if [ "${{ steps.cache-ui-components.outputs.cache-hit }}" = "true" ]; then | |
| echo "✅ UI Components Storybook restored from cache" | |
| else | |
| echo "🔨 UI Components Storybook built and cached" | |
| fi | |
| - name: Upload ui-components Storybook | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ui-components | |
| path: packages/ui-components/storybook-static | |
| deploy: | |
| name: Deploy to Netlify | |
| runs-on: ubuntu-latest | |
| needs: [build_dev_docs, build_frontend, build_rust_docs, build_math-docs, build_ui_components] | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'ToposInstitute/CatColab' | |
| outputs: | |
| deploy_url: ${{ steps.url_preview.outputs.NETLIFY_PREVIEW_URL }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| - name: Setup NodeJS | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 24 | |
| cache: "pnpm" | |
| - name: Install Netlify | |
| run: | | |
| cd .netlify-env | |
| pnpm install | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v4 | |
| - name: Consolidate and deploy to Staging | |
| if: github.event_name == 'push' || github.event_name == 'pull_request' | |
| id: netlify_deploy | |
| run: | | |
| mv app site/ | |
| mv dev-docs site/dev | |
| mv rust_docs site/dev/rust | |
| mv frontend_docs site/dev/frontend | |
| mv ui-components site/dev/ui-components | |
| mv math-docs site/math | |
| echo '/dev/rust /dev/rust/catlog' >> site/_redirects | |
| echo '/dev/core /dev/rust/catlog' >> site/_redirects | |
| echo '/dev/catcolab_backend /dev/rust/backend' >> site/_redirects | |
| echo '/math /math/index.xml' >> site/_redirects | |
| echo '/maths /math/index.xml' >> site/_redirects | |
| echo '/* /index.html 200' >> site/_redirects | |
| cd .netlify-env | |
| branch_flag="" | |
| if [ "$BRANCH_NAME" = "main" ]; then branch_flag="--prod"; else branch_flag="--alias='branch-$BRANCH_NAME'"; fi | |
| npx netlify deploy --dir ../site --site ${{ secrets.NETLIFY_SITE_ID }} --auth ${{ secrets.NETLIFY_API_TOKEN }} $branch_flag --json > ../deploy_output.json | |
| - name: Consolidate and deploy to Production | |
| if: github.event_name == 'release' | |
| run: | | |
| mv app site/ | |
| echo '/* /index.html 200' >> site/_redirects | |
| cd .netlify-env | |
| npx netlify deploy --dir ../site --site ${{ secrets.NETLIFY_PROD_SITE_ID }} --auth ${{ secrets.NETLIFY_API_TOKEN }} --prod | |
| - name: Generate URL preview | |
| id: url_preview | |
| if: env.BRANCH_NAME != 'main' && (github.event_name == 'push' || github.event_name == 'pull_request') | |
| run: | | |
| NETLIFY_PREVIEW_URL=$(jq -r '.deploy_url' deploy_output.json) | |
| echo "NETLIFY_PREVIEW_URL=$NETLIFY_PREVIEW_URL" >> "$GITHUB_OUTPUT" | |
| report_deployment_status: | |
| name: Report deployment status | |
| runs-on: ubuntu-latest | |
| needs: [create_deployment, deploy] | |
| if: always() && github.event_name == 'pull_request' && needs.create_deployment.result == 'success' | |
| steps: | |
| - name: Invalidate old successful deployments | |
| if: needs.deploy.result == 'success' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { data: deployments } = await github.rest.repos.listDeployments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| ref: context.payload.pull_request.head.ref, | |
| environment: 'netlify-preview' | |
| }); | |
| console.log(`Found ${deployments.length} existing deployment(s)`); | |
| const currentDeploymentId = parseInt('${{ needs.create_deployment.outputs.deployment_id }}'); | |
| for (const deployment of deployments) { | |
| if (deployment.id !== currentDeploymentId) { | |
| // Get the latest status for this deployment | |
| const { data: statuses } = await github.rest.repos.listDeploymentStatuses({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| deployment_id: deployment.id | |
| }); | |
| // Only invalidate if the latest status was 'success' | |
| if (statuses.length > 0 && statuses[0].state === 'success') { | |
| console.log(`Invalidating successful deployment ${deployment.id}`); | |
| await github.rest.repos.createDeploymentStatus({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| deployment_id: deployment.id, | |
| state: 'inactive', | |
| description: 'Superseded by newer deployment' | |
| }); | |
| } else { | |
| console.log(`Skipping deployment ${deployment.id} (not successful)`); | |
| } | |
| } | |
| } | |
| - name: Update deployment status to success | |
| if: needs.deploy.result == 'success' | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ github.token }} | |
| environment-url: ${{ needs.deploy.outputs.deploy_url }} | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| description: 'Netlify preview deployment' | |
| state: 'success' | |
| deployment-id: ${{ needs.create_deployment.outputs.deployment_id }} | |
| - name: Update deployment status to failure | |
| if: needs.deploy.result != 'success' | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ github.token }} | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| description: 'Deployment failed' | |
| state: 'failure' | |
| deployment-id: ${{ needs.create_deployment.outputs.deployment_id }} | |
| deploy_backend: | |
| name: Deploy backend to AWS | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'pull_request' && github.ref_name == 'main' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Nix | |
| uses: cachix/install-nix-action@v25 | |
| with: | |
| nix_path: nixpkgs=channel:25.05 | |
| - name: Configure Cachix | |
| uses: cachix/cachix-action@v14 | |
| with: | |
| name: catcolab-jmoggr | |
| authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' | |
| - name: Set the SSH key for deployment to catcolab-next | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "${{ secrets.CATCOLAB_NEXT_DEPLOYUSER_KEY }}" > ~/.ssh/id_ed25519 | |
| chmod 600 ~/.ssh/id_ed25519 | |
| ssh-keyscan backend-next.catcolab.org >> ~/.ssh/known_hosts | |
| - name: Deploy to catcolab-next | |
| run: | | |
| nix run github:serokell/deploy-rs -- --skip-checks .#catcolab-next | |
| # Ensure that a copy of the deployed repository is on the machine that it was deployed to. This is | |
| # a nice-to-have which enables checking the configuration of the currently deployed system and could | |
| # make recovery slightly less aweful in the event nix commands need to be run on the remote. | |
| - name: Rsync the repo to remote host | |
| run: | | |
| rsync -az --delete ./ [email protected]:~/catcolab |