deploy #4211
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: | |
| workflow_run: | |
| workflows: ["build"] | |
| types: | |
| - completed | |
| env: | |
| BRANCH_NAME: ${{ github.event.workflow_run.head_branch }} | |
| permissions: | |
| deployments: write | |
| jobs: | |
| create_deployment: | |
| name: Create GitHub deployment | |
| runs-on: ubuntu-latest | |
| if: > | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.head_repository.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.workflow_run.head_branch }} | |
| sha: ${{ github.event.workflow_run.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 }} | |
| deploy: | |
| name: Deploy to Netlify | |
| runs-on: ubuntu-latest | |
| if: > | |
| github.event.workflow_run.conclusion == 'success' && | |
| (github.event.workflow_run.event != 'pull_request' || github.event.workflow_run.head_repository.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 | |
| with: | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ github.token }} | |
| - name: Consolidate and deploy to Staging | |
| if: github.event.workflow_run.event == 'push' || github.event.workflow_run.event == '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 | |
| mv rfc site/rfc | |
| echo '/dev/rust /dev/rust/catlog' >> site/_redirects | |
| echo '/dev/core /dev/rust/catlog' >> site/_redirects | |
| echo '/dev/backend /dev/rust/backend' >> 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.workflow_run.event == '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.workflow_run.event == 'push' || github.event.workflow_run.event == '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.workflow_run.event == 'pull_request' && needs.create_deployment.result == 'success' | |
| steps: | |
| - name: Delete old 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: '${{ github.event.workflow_run.head_branch }}', | |
| 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) { | |
| console.log(`Deleting old deployment ${deployment.id}`); | |
| // A deployment must be marked inactive before it can be deleted | |
| await github.rest.repos.createDeploymentStatus({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| deployment_id: deployment.id, | |
| state: 'inactive', | |
| description: 'Superseded by newer deployment' | |
| }); | |
| await github.rest.repos.deleteDeployment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| deployment_id: deployment.id | |
| }); | |
| console.log(`Deleted deployment ${deployment.id}`); | |
| } | |
| } | |
| - name: Update deployment status to success | |
| if: needs.deploy.result == 'success' | |
| uses: chrnorm/deployment-status@v2 | |
| # The deployment may have already been deleted by another run so we need to be ok with errors | |
| continue-on-error: true | |
| 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 | |
| # The deployment may have already been deleted by another run so we need to be ok with errors | |
| continue-on-error: true | |
| 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 }} | |
| create_backend_deployment: | |
| name: Create backend GitHub deployment | |
| runs-on: ubuntu-latest | |
| if: > | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event != 'pull_request' && | |
| github.event.workflow_run.head_branch == 'main' | |
| 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: backend-next | |
| ref: ${{ github.event.workflow_run.head_branch }} | |
| sha: ${{ github.event.workflow_run.head_sha }} | |
| 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: 'Deploying backend to AWS...' | |
| state: 'in_progress' | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| deployment-id: ${{ steps.create_deployment.outputs.deployment_id }} | |
| deploy_backend: | |
| name: Deploy backend to AWS | |
| runs-on: ubuntu-latest | |
| needs: [create_backend_deployment] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Nix | |
| uses: cachix/install-nix-action@v25 | |
| - 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 | |
| - name: Verify deployment | |
| run: | | |
| EXPECTED=$(nix eval --raw .#nixosConfigurations.catcolab-next.config.system.build.toplevel) | |
| ACTUAL=$(ssh catcolab@backend-next.catcolab.org "readlink -f /run/current-system") | |
| if [[ "$ACTUAL" != "$EXPECTED" ]]; then | |
| echo "ERROR: Deployment verification failed, the server is not running the expected nix profile" | |
| echo "Expected: $EXPECTED" | |
| echo "Actual: $ACTUAL" | |
| exit 1 | |
| fi | |
| echo "Deployment verified: $ACTUAL" | |
| # 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 ./ catcolab@backend-next.catcolab.org:~/catcolab | |
| report_backend_deployment_status: | |
| name: Report backend deployment status | |
| runs-on: ubuntu-latest | |
| needs: [create_backend_deployment, deploy_backend] | |
| if: always() && needs.create_backend_deployment.result == 'success' | |
| steps: | |
| - name: Update deployment status to success | |
| if: needs.deploy_backend.result == 'success' | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ github.token }} | |
| environment-url: https://backend-next.catcolab.org | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| description: 'Backend deployed to AWS' | |
| state: 'success' | |
| deployment-id: ${{ needs.create_backend_deployment.outputs.deployment_id }} | |
| - name: Update deployment status to failure | |
| if: needs.deploy_backend.result != 'success' | |
| uses: chrnorm/deployment-status@v2 | |
| with: | |
| token: ${{ github.token }} | |
| log-url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| description: 'Backend deployment failed' | |
| state: 'failure' | |
| deployment-id: ${{ needs.create_backend_deployment.outputs.deployment_id }} |