Deploying to staging triggered by naanci #29
Workflow file for this run
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: Deploying to staging | |
| run-name: Deploying to staging triggered by ${{ inputs.author }} | |
| concurrency: | |
| group: deploy-staging-pr-${{ inputs.prId }} | |
| cancel-in-progress: true | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| prId: | |
| description: "PR to deploy" | |
| required: true | |
| repository: | |
| description: "The repository from which the slash command was dispatched" | |
| required: true | |
| comment-id: | |
| description: "The comment-id of the slash command" | |
| required: true | |
| author: | |
| description: "The author that triggered this actions" | |
| required: true | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| statuses: write | |
| jobs: | |
| getPRHead: | |
| name: Get PR head SHA | |
| runs-on: ubuntu-latest | |
| outputs: | |
| sha: ${{ steps.pr-head.outputs.result }} | |
| steps: | |
| - name: Get PR head SHA | |
| id: pr-head | |
| uses: actions/github-script@v7 | |
| with: | |
| result-encoding: string | |
| script: | | |
| const prId = ${{ inputs.prId }}; | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: parseInt(prId, 10) | |
| }); | |
| return pr.head.sha; | |
| sendMessage: | |
| name: Send deploying to staging message | |
| runs-on: ubuntu-latest | |
| needs: getPRHead | |
| steps: | |
| - name: Comment on PR | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prId = ${{ inputs.prId }}; | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const commitHash = '${{ needs.getPRHead.outputs.sha }}'; | |
| await github.rest.repos.createCommitStatus({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| sha: commitHash, | |
| state: 'pending', | |
| target_url: runUrl, | |
| context: 'Deploy to staging', | |
| description: 'Deployment to staging in progress...', | |
| }); | |
| checkExistingImage: | |
| name: Check if image already exists | |
| runs-on: ubuntu-latest | |
| needs: [getPRHead, sendMessage] | |
| outputs: | |
| image-exists: ${{ steps.check-image.outputs.exists }} | |
| git-sha: ${{ steps.set-sha.outputs.sha }} | |
| steps: | |
| - name: Set SHA | |
| id: set-sha | |
| run: echo "sha=$(echo "${{ needs.getPRHead.outputs.sha }}" | cut -c1-7)" >> $GITHUB_OUTPUT | |
| - name: Check if Docker image exists | |
| id: check-image | |
| run: | | |
| SHA7=$(echo "${{ needs.getPRHead.outputs.sha }}" | cut -c1-7) | |
| if docker manifest inspect tahminator/codebloom:staging-$SHA7 > /dev/null 2>&1; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| echo "Image staging-$SHA7 already exists" | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| echo "Image staging-$SHA7 does not exist" | |
| fi | |
| promoteExisting: | |
| name: Promote existing image to staging-latest | |
| runs-on: ubuntu-latest | |
| needs: [getPRHead, checkExistingImage] | |
| if: needs.checkExistingImage.outputs.image-exists == 'true' | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.getPRHead.outputs.sha }} | |
| - name: Setup CI | |
| uses: ./.github/composite/setup-ci | |
| with: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| - name: Load secrets | |
| uses: ./.github/composite/load-secrets | |
| with: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| UNLOAD_ENVIRONMENTS: ci | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: docker.io | |
| username: tahminator | |
| password: ${{ env.DOCKER_HUB_PAT }} | |
| - name: Promote existing image | |
| run: | | |
| SHA7=${{ needs.checkExistingImage.outputs.git-sha }} | |
| docker pull tahminator/codebloom:staging-$SHA7 | |
| docker tag tahminator/codebloom:staging-$SHA7 tahminator/codebloom:staging-latest | |
| docker push tahminator/codebloom:staging-latest | |
| echo "Promoted staging-$SHA7 to staging-latest" | |
| frontendPreTest: | |
| name: Frontend Pre Test | |
| runs-on: ubuntu-latest | |
| needs: [getPRHead, checkExistingImage] | |
| if: needs.checkExistingImage.outputs.image-exists == 'false' | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.getPRHead.outputs.sha }} | |
| - name: Run workflow | |
| uses: ./.github/composite/test/frontend-pre-test | |
| with: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| backendPreTest: | |
| name: Backend Compile Test | |
| runs-on: ubuntu-latest | |
| needs: [getPRHead, checkExistingImage] | |
| if: needs.checkExistingImage.outputs.image-exists == 'false' | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.getPRHead.outputs.sha }} | |
| - name: Run workflow | |
| uses: ./.github/composite/test/backend-pre-test | |
| validateDBSchema: | |
| name: Validate DB Schema on Staging DB | |
| runs-on: ubuntu-latest | |
| needs: [getPRHead, checkExistingImage, backendPreTest] | |
| if: needs.checkExistingImage.outputs.image-exists == 'false' | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.getPRHead.outputs.sha }} | |
| fetch-depth: 0 | |
| - name: Run workflow | |
| uses: ./.github/composite/validate-db | |
| with: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| ENVIRONMENT: staging | |
| SHA: ${{ needs.getPRHead.outputs.sha }} | |
| buildImage: | |
| name: Build Docker Image & Upload to Registry | |
| runs-on: ubuntu-latest | |
| needs: | |
| [ | |
| getPRHead, | |
| checkExistingImage, | |
| validateDBSchema, | |
| backendPreTest, | |
| frontendPreTest, | |
| ] | |
| if: needs.checkExistingImage.outputs.image-exists == 'false' | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.getPRHead.outputs.sha }} | |
| - name: Run workflow | |
| uses: ./.github/composite/build-image | |
| with: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| TAG_PREFIX: staging- | |
| SERVER_PROFILES: stg | |
| redeploy: | |
| name: Redeploy on DigitalOcean | |
| runs-on: ubuntu-latest | |
| needs: [buildImage, promoteExisting, getPRHead] | |
| if: always() && (needs.buildImage.result == 'success' || needs.promoteExisting.result == 'success') | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ needs.getPRHead.outputs.sha }} | |
| fetch-depth: 0 | |
| - name: Run workflow | |
| uses: ./.github/composite/redeploy | |
| with: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| ENVIRONMENT: staging | |
| SHA: ${{ needs.getPRHead.outputs.sha }} | |
| notifyStatus: | |
| name: Notify on deployment status | |
| runs-on: ubuntu-latest | |
| needs: | |
| [ | |
| getPRHead, | |
| checkExistingImage, | |
| sendMessage, | |
| backendPreTest, | |
| frontendPreTest, | |
| validateDBSchema, | |
| buildImage, | |
| promoteExisting, | |
| redeploy, | |
| ] | |
| if: always() | |
| steps: | |
| - name: Comment on PR about deployment status | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prId = ${{ inputs.prId }}; | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const commitHash = '${{ needs.getPRHead.outputs.sha }}'; | |
| const needsObj = ${{ toJSON(needs) }}; | |
| const jobNames = Object.keys(needsObj); | |
| const failedJobs = jobNames.filter((name) => needsObj[name].result === 'failure'); | |
| const cancelledJobs = jobNames.filter((name) => needsObj[name].result === 'cancelled'); | |
| const successJobs = jobNames.filter((name) => needsObj[name].result === 'success'); | |
| let statusMessage; | |
| let status = false; | |
| if (failedJobs.length > 0 && cancelledJobs.length > 0) { | |
| statusMessage = `**Staging deployment failed and was cancelled** for commit ${commitHash}`; | |
| status = false; | |
| } else if (failedJobs.length > 0) { | |
| statusMessage = `**Staging deployment failed** for commit ${commitHash}`; | |
| status = false; | |
| } else if (cancelledJobs.length > 0) { | |
| statusMessage = `**Staging deployment was cancelled** for commit ${commitHash}`; | |
| status = false; | |
| } else { | |
| statusMessage = `**Staging deployment succeeded** for commit ${commitHash}`; | |
| status = true; | |
| } | |
| await github.rest.repos.createCommitStatus({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| sha: commitHash, | |
| state: status ? 'success' : 'failure', | |
| target_url: runUrl, | |
| context: "Deploy to staging", | |
| description: status ? "Staging deployment succeeded" : "Staging deployment failed", | |
| }); |