github/branch-deploy

Merge deploy mode skips deployment status update

nerdoza opened this issue · 4 comments

Describe the Issue

I would expect that when the merge_deploy_mode is 'true', and it is determined that the deployment operation should continue (outputs.continue === 'true'), that the post deployment steps would run and update the deployment status automatically.

As it's currently configured, the bypass property is set to true, resulting in the post deployment process being skipped entirely. It's then up to the developer to mimic the deployment status updating for these workflows.

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

@bayssmekanique Thanks for opening this issue! Have you taken a look yet at the docs for this feature? In the example workflow on that document, the environment: production option is set for the workflow. This effectively tells Actions to start and end a deployment to the production environment when that workflow is run. By doing so, this effectively removes the need to have the branch-deploy Action handle this logic internally. More on this can be covered in the "how environments relate to deployments" in GitHub's public documentation as well.

Do you have a specific use case that limits or prevents you from using the environment selector option in your workflow?

@GrantBirki, I'm using the environment variable on the action step.

I can see in the code where the issue I'm seeing is happening for the post-deploy because the mergeDeployMode conditional sets the bypass value to true.

// If we are running in the merge deploy mode, run commit checks
if (mergeDeployMode) {
core.info(`🏃 running in 'merge deploy' mode`)
await identicalCommitCheck(octokit, context, environment)
// always bypass post run logic as they is an entirely alternate workflow from the core branch-deploy Action
core.saveState('bypass', 'true')
return 'success - merge deploy mode'
}

This results in the whole postDeoloy function from being executed.

// If bypass is set, exit the workflow
if (bypass) {
core.warning(`⛔ ${COLORS.highlight}bypass${COLORS.reset} set, exiting`)
return
}

I can see where in the code the in-progress deployment should be set, but I haven't traced back up the call-stack to figure out where it's exiting.

branch-deploy/src/main.js

Lines 644 to 653 in f9e741b

// Set the deployment status to in_progress
await createDeploymentStatus(
octokit,
context,
precheckResults.ref,
'in_progress',
createDeploy.id,
environment,
environmentObj.environmentUrl // environment_url (can be null)
)


It's possible I'm misunderstanding the merge-deploy feature, so please correct me where I'm mistaken.

Here's the file that runs for my production deployments on the main branch.

name: Production Deployment

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}

permissions:
  id-token: write
  contents: write
  issues: write
  pull-requests: write
  deployments: write

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
      - name: Deployment Check
        id: deployment-check
        uses: github/branch-deploy@v9
        with:
          merge_deploy_mode: 'true'
          environment: production

      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Use Node.js v20
        uses: actions/setup-node@v4
        with:
          node-version: 20
          check-latest: true
          cache: npm

      - name: Install Dependencies
        run: npm ci --no-audit

      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

      - name: Configure AWS credentials
        if: ${{ steps.deployment-check.outputs.continue == 'true' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::1234:role/GitHub
          aws-region: us-west-4

      - name: Deploy
        if: ${{ steps.deployment-check.outputs.continue == 'true' }}
        run: npm run deploy:production

@bayssmekanique if you do something like this (seen below), in your workflow, then GitHub will handle the full deployment flow for you automatically:

...
jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
+  environment: production # GitHub Actions environment selector
    steps:
      - name: Deployment Check
        id: deployment-check
        uses: github/branch-deploy@v9
        with:
          merge_deploy_mode: 'true'
          environment: production # <--- same as this env!
...

All you need to do is add the environment tag to the top level of the given job that is defining where you do a deployment. It will start, set into progress, and complete (success/failure) your deployment for you. Since this is handled natively by GitHub Actions, it is the exact reason why I did not bake it into this Action's sub-workflow.


You can further improve your workflow by splitting the deployment-check item into its own workflow step as well:

https://github.com/the-hideout/cloudflare/blob/dd1240ecbf23bbf16d9534807d9d33f94b102c7a/.github/workflows/deploy.yml#L15-L27

This allows for better separation between the steps checking if a deployment should start, and actually running the deployment.

Let me know if that helps!

@GrantBirki, the environment attribute solved the deployment problem and the hint to split the check into it's own job helped reduce my workflow files quite a bit. Thank you for the insight!


For anyone that stumbles into the same issue in the future, here's what I ended up with for CI files.

branchDeploy.yml for deploying from PRs:

name: Branch Deployment

on:
  issue_comment:
    types:
      - created

concurrency:
  group: ${{ github.workflow }}

permissions:
  id-token: write
  pull-requests: write
  deployments: write
  contents: write
  checks: read
  statuses: read

jobs:
  deployment-check:
    name: Deployment Check
    runs-on: ubuntu-latest
    if: ${{ github.event.issue.pull_request }}
    outputs:
      continue: ${{ steps.check-branch-deploy.outputs.continue }}
      ref: ${{ steps.check-branch-deploy.outputs.ref }}
      environment: ${{ steps.check-branch-deploy.outputs.environment }}
      noop: ${{ steps.check-branch-deploy.outputs.noop }}
    steps:
      - name: Check Branch Deploy
        id: check-branch-deploy
        uses: github/branch-deploy@v9
        with:
          environment: preview
          environment_targets: preview,production
          environment_urls: 'preview|https://preview.mysite.com,production|https://mysite.com'

  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    needs: deployment-check
    if: ${{ needs.deployment-check.outputs.continue == 'true' }}
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
        with:
          ref: ${{ needs.deployment-check.outputs.ref }}

      - name: Use Node.js v20
        uses: actions/setup-node@v4
        with:
          node-version: 20
          check-latest: true
          cache: npm

      - name: Install Dependencies
        run: npm ci --no-audit

      - name: Build Only
        if: ${{ needs.deployment-check.outputs.noop == 'true' }}
        run: npm run build:${{ needs.deployment-check.outputs.environment }}

      - name: Deploy
        if: ${{ needs.deployment-check.outputs.noop != 'true' }}
        run: npm run deploy:${{ needs.deployment-check.outputs.environment }}

previewDeployment.yml for deploying on merge to main:

name: Preview Deployment

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}

permissions:
  id-token: write
  contents: read
  deployments: write

jobs:
  deployment-check:
    name: Deployment Check
    runs-on: ubuntu-latest
    if: github.event_name == 'push'
    outputs:
      continue: ${{ steps.check-branch-deploy.outputs.continue }}
    steps:
      - name: Check Branch Deploy
        id: check-branch-deploy
        uses: github/branch-deploy@v9
        with:
          merge_deploy_mode: 'true'
          environment: preview

  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment:
      name: preview
      url: https://preview.mysite.com
    needs: deployment-check
    if: ${{ needs.deployment-check.outputs.continue == 'true' }}
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4

      - name: Use Node.js v20
        uses: actions/setup-node@v4
        with:
          node-version: 20
          check-latest: true
          cache: npm

      - name: Install Dependencies
        run: npm ci --no-audit

      - name: Deploy
        run: npm run deploy:preview