Giter Site home page Giter Site logo

github / branch-deploy Goto Github PK

View Code? Open in Web Editor NEW
348.0 74.0 44.0 11.67 MB

Enabling Branch Deployments through IssueOps with GitHub Actions - If you find this project useful, give it a star! ⭐️

Home Page: https://github.com/marketplace/actions/branch-deploy

License: MIT License

JavaScript 99.84% Shell 0.16%
actions automation deployment issueops cicd github continuous-deployment github-actions workflows action

branch-deploy's Introduction

Branch Deploy Action 🚀

CodeQL test package-check lint actions-config-validation coverage

A GitHub Action to enable branch deployments using IssueOps!

ship-it

This Action does the heavy lifting for you to enable branch deployments:

  • 🔍 Detects when IssueOps commands are used on a pull request
  • ✏️ Configurable - Choose your command syntax, environment, noop trigger, base branch, reaction, and more
  • ✔️ Respects your branch protection settings configured for the repo
  • 🗨️ Comments and reacts to your IssueOps commands
  • 🚀 Triggers GitHub deployments for you with simple configuration
  • 🔓 Deploy locks to prevent multiple deployments from clashing

Available Commands 💬

  • .deploy - Deploy a pull request
  • .noop - Deploy a pull request in noop mode
  • .deploy to <environment> - Deploy a pull request to a specific environment
  • .deploy <stable_branch> - Trigger a rollback deploy to your stable branch (main, master, etc)
  • .lock - Create a deployment lock for the default environment
  • .lock --reason <text> - Create a deployment lock for the default environment with a custom reason
  • .lock --details - View details about a deployment lock
  • .lock <environment> - Create a deployment lock for a specific environment
  • .lock --global - Create a global deployment lock
  • .unlock - Remove a deployment lock
  • .unlock <environment> - Remove a deployment lock for a specific environment
  • .unlock --global - Remove a global deployment lock
  • .help - Get help with IssueOps commands with this Action

These commands are all fully customizable and are just an example using this Action's defaults

For the full command usage, check out the usage document

Alternate command syntax and shortcuts can be found at the bottom of this readme here

Demo 🎥

A video demo showing how IssueOps on a pull request works using this Action

demo.mp4

Turbo Quickstart ⚡

A quick section to get you started with this Action

Usage 📝

Basic usage assuming all defaults:

- name: branch-deploy
  id: branch-deploy
  uses: github/[email protected]

Advanced usage with custom configuration:

- name: branch-deploy
  id: branch-deploy
  uses: github/[email protected]
  with:
    trigger: ".deploy"
    noop_trigger: ".noop"
    reaction: "eyes"
    environment: "production"
    stable_branch: "main"

Example 📚

Check out a super simple workflow example using this Action to quickly get up and running with branch deployments

name: "branch deploy demo"

# The workflow to execute on is comments that are newly created
on:
  issue_comment:
    types: [created]

# Permissions needed for reacting and adding comments for IssueOps commands
permissions:
  pull-requests: write
  deployments: write
  contents: write
  checks: read
  statuses: read

jobs:
  demo:
    if: ${{ github.event.issue.pull_request }} # only run on pull request comments
    runs-on: ubuntu-latest
    steps:
      # Execute IssueOps branch deployment logic, hooray!
      # This will be used to "gate" all future steps below and conditionally trigger steps/deployments
      - uses: github/[email protected]
        id: branch-deploy
        with:
          trigger: ".deploy"

      # Run your deployment logic for your project here - examples seen below

      # Checkout your projects repository based on the ref provided by the branch-deploy step
      - uses: actions/checkout@v4
        with:
          ref: ${{ steps.branch-deploy.outputs.ref }}

      # Do some fake "noop" deployment logic here
      # conditionally run a noop deployment
      - name: fake noop deploy
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' }}
        run: echo "I am doing a fake noop deploy"

      # Do some fake "regular" deployment logic here
      # conditionally run a regular deployment
      - name: fake regular deploy
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }}
        run: echo "I am doing a fake regular deploy"

Keep reading to learn more about this Action! Even further details about how this Action works can be found below as well

You can check out further examples by checking out our examples documentation

About 💡

Before we get into details, let's first define a few key terms below:

  • IssueOps - Its like ChatOps but instead of using a chat bot, commands are invoked by commenting on a pull request (PRs are issues under the hood) - Example: commenting .deploy on a pull request
  • Branch Deployment - A branch deploy is a deployment methodology that enables you to deploy a branch (or pull request) to a desired environment before merging to main or master - More on this below
  • PR - Short for pull request

IssueOps 🗨️

The best way to define IssueOps is to compare it to something similar, ChatOps. You may be familiar with the concept ChatOps already but in case you aren't here is a quick definition below:

ChatOps is the process of interacting with a chat bot to execute commands directly in a chat platform. For example, with ChatOps you might do something like .ping example.org to check the status of a website

IssueOps adopts the same mindset but through a different medium. Rather than using a chat service to invoke the commands we use comments on a GitHub Issue or Pull Request. GitHub Actions is the runtime which executes our desired logic

Branch Deployments 🌲

Branch deployments are a battle tested way of deploying your changes to a given environment for a variety of reasons. Branch deployments allow you to do the following:

  • Deploy your changes to production before merging
  • Deploy changes to a staging, QA, or non-production environment

Branch Deployment Core Concepts ⭐

Note: The main branch is considered the base repository branch for all examples below

  • The main branch is always considered to be a stable and deployable branch
  • All changes are deployed to production before they are merged to the main branch
  • To roll back a branch deployment, you deploy the main branch
  • noop deployments should not make changes but rather report what they "would" have done

Why use branch deployments?

To put the merge -> deploy model in the past!

What if your changes are bad and you broke production with the merge -> deploy model? Well now you have to revert your PR, get passing CI/builds, and then re-merge your changes to get back to a stable environment. With the branch deploy model, this is almost never the case. The main branch is considered to be always safe and stable

How does it work? 📚

This section will go into detail about how this Action works and hopefully inspire you on ways you can leverage it in your own projects

Let's walk through a GitHub Action workflow using this Action line by line:

# The name of the workflow, it can be anything you wish
name: "branch deploy demo"

# The workflow to execute on is comments that are newly created
on:
  issue_comment:
    types: [created]

It is important to note that the workflow we want to run IssueOps on is issue_comment and created. This means we will not run under any other contexts for this workflow. You can edit this as you wish but it does change how this model ultimately works. For example, issue_comment workflows only use files found on main to run. If you do something like on: pull_request you could open yourself up to issues as a user could alter a file in a PR and exfil your secrets for example. Only using issue_comment is the suggested workflow type

# Permissions needed for reacting and adding comments for IssueOps commands
permissions:
  pull-requests: write # Required for commenting on PRs
  deployments: write # Required for updating deployment statuses
  contents: write # Required for reading/writing the lock file
  checks: read # Required for checking if the CI checks have passed in order to deploy the PR
  statuses: read # Required for checking if all commit statuses are "success" in order to deploy the PR

These are the minimum permissions you need to run this Action. If you need further assistance with permissions within GitHub Actions, please review the following documentation.

jobs:
  demo:
    if: ${{ github.event.issue.pull_request }} # only run on pull request comments
    runs-on: ubuntu-latest
    steps:
      # Checkout your projects repository
      - uses: actions/checkout@v4

Sets up your demo job, uses an ubuntu runner, and checks out your repo - Just some standard setup for a general Action. We also add an if: statement here to only run this workflow on pull request comments to make it a little cleaner

Note: The Action will check the context for us anyways but this can save us a bit of CI time by using the if: condition

      # Execute IssueOps branch deployment logic, hooray!
      - uses: github/[email protected]
        id: branch-deploy
        with:
          trigger: ".deploy"

Note: It is important to set an id: for this job so we can reference its outputs in subsequent steps

The core of this Action takes place here. This block of code will trigger the branch deploy action to run. It will do the following:

  1. Check the comment which invoked the workflow for the trigger: phrase (.deploy) defined here
  2. If the trigger phrase is found, it will proceed with a deployment
  3. It will start by reacting to your message to let you know it is running
  4. The Action will post a comment with a link to the running Actions workflow for you to follow its progress
  5. A deployment will be started and attached to your pull request - You'll get a nice little yellow rocket which tells you a deployment is in progress
  6. Outputs will be exported by this job for later reference in other jobs as well
      # Do some fake "noop" deployment logic here
      # conditionally run a noop deployment
      - name: fake noop deploy
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' }}
        run: echo "I am doing a fake noop deploy"

      # Do some fake "regular" deployment logic here
      # conditionally run a regular deployment
      - name: fake regular deploy
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }}
        run: echo "I am doing a fake regular deploy"

As seen above, we have two steps. One for a noop deploy, and one for a regular deploy. For example, the noop deploy could trigger a terraform plan and the regular deploy could be a terraform apply. These steps are conditionally gated by two variables:

  • steps.branch-deploy.outputs.continue == 'true' - The continue variable is only set to true when a deployment should continue
  • steps.branch-deploy.outputs.noop == 'true' - The noop variable is only set to true when a noop deployment should be run

Example: You comment .noop on a pull request. A noop deployment is detected so this action outputs the noop variable to true. You also have the correct permissions to execute the IssueOps command so the action also outputs the continue variable to true. This will allow the "fake noop deploy" step seen above to run and the "fake regular deploy" step will be skipped

Inputs 📥

Input Required? Default Description
github_token true ${{ github.token }} The GitHub token used to create an authenticated client - Provided for you by default!
status true ${{ job.status }} The status of the GitHub Actions - For use in the post run workflow - Provided for you by default!
reaction false eyes If set, the specified emoji "reaction" is put on the comment to indicate that the trigger was detected. For example, "rocket" or "eyes"
trigger false .deploy The string to look for in comments as an IssueOps trigger. Example: ".deploy"
noop_trigger false .noop The string to look for in comments as an IssueOps noop trigger. Example: ".noop" - The usage would then be ".noop"
lock_trigger false .lock The string to look for in comments as an IssueOps lock trigger. Used for locking branch deployments on a specific branch. Example: ".lock"
unlock_trigger false .unlock The string to look for in comments as an IssueOps unlock trigger. Used for unlocking branch deployments. Example: ".unlock"
help_trigger false .help The string to look for in comments as an IssueOps help trigger. Example: ".help"
lock_info_alias false .wcid An alias or shortcut to get details about the current lock (if it exists) Example: ".info" - Hubbers will find the ".wcid" default helpful ("where can I deploy")
permissions true write,maintain,admin The allowed GitHub permissions an actor can have to invoke IssueOps commands - Example: "write,maintain,admin"
param_separator false | The separator to use for parsing parameters in comments in deployment requests. Parameters will are saved as outputs and can be used in subsequent steps - See Parameters for additional details
global_lock_flag false --global The flag to pass into the lock command to lock all environments. Example: "--global"
environment false production The name of the default environment to deploy to. Example: by default, if you type .deploy, it will assume "production" as the default environment
environment_targets false production,development,staging Optional (or additional) target environments to select for use with deployments. Example, "production,development,staging". Example usage: .deploy to development, .deploy to production, .deploy to staging
environment_urls false "" Optional target environment URLs to use with deployments. This input option is a mapping of environment names to URLs and the environment names must match the environment_targets input option. This option is a comma separated list with pipes (|) separating the environment from the URL. Note: disabled is a special keyword to disable an environment url if you enable this option. Format: "<environment1>|<url1>,<environment2>|<url2>,etc" Example: "production|https://myapp.com,development|https://dev.myapp.com,staging|disabled" - See the environment urls section for more details
draft_permitted_targets false "" Optional environments which can allow "draft" pull requests to be deployed. By default, this input option is empty and no environments allow deployments sourced from a pull request in a "draft" state. Examples: "development,staging"
environment_url_in_comment false "true If the environment_url detected in the deployment should be appended to the successful deployment comment or not. Examples: "true" or "false" - See the environment urls section for more details
production_environments false production A comma separated list of environments that should be treated as "production". GitHub defines "production" as an environment that end users or systems interact with. Example: "production,production-eu". By default, GitHub will set the "production_environment" to "true" if the environment name is "production". This option allows you to override that behavior so you can use "prod", "prd", "main", "production-eu", etc. as your production environment name. ref: #208
stable_branch false main The name of a stable branch to deploy to (rollbacks). Example: "main"
update_branch false warn Determine how you want this Action to handle "out-of-date" branches. Available options: "disabled", "warn", "force". "disabled" means that the Action will not care if a branch is out-of-date. "warn" means that the Action will warn the user that a branch is out-of-date and exit without deploying. "force" means that the Action will force update the branch. Note: The "force" option is not recommended due to Actions not being able to re-run CI on commits originating from Actions itself
outdated_mode false "strict" The mode to use for determining if a branch is up-to-date or not before allowing deployments. This option is closely related to the update_branch input option above. There are three available modes to choose from: pr_base, default_branch, or strict. The default is strict to help ensure that deployments are using the most up-to-date code. Please see the documentation for more details.
required_contexts false "false" Manually enforce commit status checks before a deployment can continue. Only use this option if you wish to manually override the settings you have configured for your branch protection settings for your GitHub repository. Default is "false" - Example value: "context1,context2,context3" - In most cases you will not need to touch this option
skip_ci false "" A comma separated list of environments that will not use passing CI as a requirement for deployment. Use this option to explicitly bypass branch protection settings for a certain environment in your repository. Default is an empty string "" - Example: "development,staging"
checks false "all" This input defines how the branch-deploy Action will handle the status of CI checks on your PR/branch before deployments can continue. "all" requires that all CI checks must pass in order for a deployment to be triggered. "required" only waits for required CI checks to be passing. View the documentation for more details.
skip_reviews false "" A comma separated list of environment that will not use reviews/approvals as a requirement for deployment. Use this options to explicitly bypass branch protection settings for a certain environment in your repository. Default is an empty string "" - Example: "development,staging"
allow_forks false "true" Allow branch deployments to run on repository forks. If you want to harden your workflows, this option can be set to false. Default is "true"
admins false "false" A comma separated list of GitHub usernames or teams that should be considered admins by this Action. Admins can deploy pull requests without the need for branch protection approvals. Example: "monalisa,octocat,my-org/my-team"
admins_pat false "false" A GitHub personal access token with "read:org" scopes. This is only needed if you are using the "admins" option with a GitHub org team. For example: "my-org/my-team"
merge_deploy_mode false "false" Advanced configuration option for operations on merge commits. See the merge commit docs below
unlock_on_merge_mode false "false" Advanced configuration option for automatically releasing locks associated with a pull request when that pull request is merged. See the unlock on merge mode documentation for more details
skip_completing false "false" If set to "true", skip the process of completing a deployment. You must manually create a deployment status after the deployment is complete. Default is "false"
deploy_message_path false ".github/deployment_message.md" The path to a markdown file which is used as a template for custom deployment messages. Example: ".github/deployment_message.md"
sticky_locks false "false" If set to "true", locks will not be released after a deployment run completes. This applies to both successful, and failed deployments.Sticky locks are also known as "hubot style deployment locks". They will persist until they are manually released by a user, or if you configure another workflow with the "unlock on merge" mode to remove them automatically on PR merge.
sticky_locks_for_noop false "false" If set to "true", then sticky_locks will also be used for noop deployments. This can be useful in some cases but it often leads to locks being left behind when users test noop deployments.
allow_sha_deployments false "false" If set to "true", then you can deploy a specific sha instead of a branch. Example: ".deploy 1234567890abcdef1234567890abcdef12345678 to production" - This is dangerous and potentially unsafe, view the docs to learn more
disable_naked_commands false "false" If set to "true", then naked commands will be disabled. Example: .deploy will not trigger a deployment. Instead, you must use .deploy to production to trigger a deployment. This is useful if you want to prevent accidental deployments from happening. View the docs to learn more
successful_deploy_labels false "" A comma separated list of labels to add to the pull request when a deployment is successful. Example: "deployed,success"
successful_noop_labels false "" A comma separated list of labels to add to the pull request when a noop deployment is successful. Example: "noop,success"
failed_deploy_labels false "" A comma separated list of labels to add to the pull request when a deployment fails. Example: "failed,deploy-failed"
failed_noop_labels false "" A comma separated list of labels to add to the pull request when a noop deployment fails. Example: "failed,noop-failed"
skip_successful_noop_labels_if_approved false "false" Whether or not the post run logic should skip adding successful noop labels if the pull request is approved. This can be useful if you add a label such as "ready-for-review" after a .noop completes but want to skip adding that label in situations where the pull request is already approved.
skip_successful_deploy_labels_if_approved false "false" Whether or not the post run logic should skip adding successful deploy labels if the pull request is approved. This can be useful if you add a label such as "ready-for-review" after a .deploy completes but want to skip adding that label in situations where the pull request is already approved.

Outputs 📤

Output Description
continue The string "true" if the deployment should continue, otherwise empty - Use this to conditionally control if your deployment should proceed or not - ⭐ The main output you should watch for when determining if a deployment shall carry on
fork The string "true" if the pull request is a fork, otherwise "false"
triggered The string "true" if the trigger was found, otherwise the string "false"
comment_body The comment body
issue_number The issue number of the pull request (or issue) that was commented on
actor The GitHub handle of the actor that invoked the IssueOps command
environment The environment that has been selected for a deployment
params The raw parameters that were passed into the deployment command (see param_separator) - Further documentation
noop The string "true" if the noop trigger was found, otherwise the string "false" - Use this to conditionally control whether your deployment runs as a noop or not
sha The sha of the branch to be deployed
ref The ref (branch or sha) to use with deployment
base_ref The base ref that the pull request is merging into
comment_id The comment id which triggered this deployment
deployment_id The ID of the deployment created by running this action
environment_url The environment URL detected and used for the deployment (sourced from the environment_urls input)
type The type of trigger that was detected (examples: deploy, lock, unlock, lock-info-alias, help)
fork_ref The true ref of the fork
fork_label The API label field returned for the fork
fork_checkout The console command presented in the GitHub UI to checkout a given fork locally
fork_full_name The full name of the fork in "org/repo" format
initial_reaction_id The reaction id for the initial reaction on the trigger comment
actor_handle The handle of the user who triggered the action
global_lock_claimed The string "true" if the global lock was claimed
global_lock_released The string "true" if the global lock was released
unlocked_environments Only exposed when using the "unlock on merge" mode - This output variable will contain a comma separated list of the environments that were unlocked - See the unlock on merge mode documentation for more details
sha_deployment If allow_sha_deployments is enabled, and a sha deployment is performed instead of a branch deployment, this output variable will contain the sha that was deployed. Otherwise, this output variable will be empty
review_decision The pull request review status. Can be one of a few values - examples: APPROVED, skip_reviews, REVIEW_REQUIRED, null
is_outdated The string "true" if the branch is out-of-date, otherwise "false"
merge_state_status The status of the merge state. Can be one of a few values - examples: "DIRTY", "DRAFT", "CLEAN", etc
commit_status The status of the commit. Can be one of a few values - examples: "SUCCESS", null, "skip_ci", "PENDING", "FAILURE" etc
approved_reviews_count The number of approved reviews on the pull request

Custom Deployment Messages ✏️

For documentation on how to customize the deployment messages, see the custom deployment messages docs.

About Environments 🌎

If you are using environment rather than repo secrets, this section will be of interest to you

For those familiar with GitHub Actions, you have probably used environments before to store secrets and trigger deployments. The syntax for doing so is very simple and usually looks like this:

jobs:
  deploy:
    environment: production # right here we use an environment
    runs-on: ubuntu-latest
    steps:
      - name: deployment
        run: terraform apply -auto-approve

However, this has a few limitations:

  • When workflows finish, so does the deployment to that environment - This means that the little green rocket doesn't "stick" to your pull request
  • It is tricky to tune in environment protection rules with a single environment when using IssueOps + branch-deployments

To get around these limitations with this branch-deploy action and IssueOps, we can use two different environments. One to store our environnement secrets and another to use in our branch deployments.

Yes this isn't the most elegant solution, but it works and is very easy to accomplish

Here is a proper example for using two environments with this action:

jobs:
  deploy:
    if: ${{ github.event.issue.pull_request }} # only run on pull request comments
    environment: production-secrets # custom environment for storing secrets
    runs-on: ubuntu-latest
    steps:
      - uses: github/[email protected]
        id: branch-deploy
        with:
          trigger: ".deploy"
          environment: production # the environment for the actual deployment

      # Your deployment steps go here...

This allows you to achieve the following:

  • Fine grained control over your environment secrets in the production-secrets environment
  • A "sticky" green rocket to your PR that doesn't disappear when the workflow finishes
  • Access to all the environment secrets stored in the production-secrets environment

Environment Targets

With this Action, you can also choose the environment you wish to deploy to. This is useful if you have multiple environments and want to deploy to a specific environment.

This can be achieved with the environment_targets input

With this option, you can specify a comma separated list of environments that you can deploy to besides just the default with .deploy

The defaults that are used are: production,development,staging. However, you can configure this to be whatever you like!

To use a deployment with a specific environment, you would invoke your commands like so:

  • .deploy production
  • .deploy to production
  • .deploy to <environment>

This also works with noop commands as well

  • .noop production
  • .noop to production
  • .noop to <environment>

YAML input example:

- uses: github/[email protected]
  id: branch-deploy
  with:
    trigger: ".deploy"
    environment: production # the default environment
    environment_targets: "production,development,staging" # the environments that you can deploy to with explicit commands

You can view additional details about the environment_targets input option in the action.yml section above

Environment URLs

Environment URLs can be configured and mapped to matching environment_targets using the environment_urls input.

This input option is a mapping of environment names to URLs and the environment names must match the environment_targets input option. This option is a comma separated list with pipes (|) separating the environment from the URL.

Note: disabled is a special keyword to disable an environment url if you enable this option but not all environments have a url.

Format: "<environment1>|<url1>,<environment2>|<url2>,etc"

Example: "production|https://myapp.com,development|https://dev.myapp.com,staging|disabled"

This option is especially useful when your deployment targets are services with a URL (website, API, etc)

By enabling this option, you will get a "clickable" link on success (non-noop) deployment messages on pull requests. You will also be able to click the "View deployment" button in your repository's deployments page and be taken to the URL of the environment you deployed to.

If you wish to disable the "clickable" link on the successful deployment message, you can set the environment_url_in_comment input to "false".

Rollbacks 🔄

This Action supports rollback deployments out of the box. This is useful when you run a branch deployment (.deploy) and something goes wrong and you need to rollback to a previous known working state.

This can be achieved by using the .deploy <stable_branch> command

See the inputs section above for more information on how to configure the stable branch

The <stable_branch> can be any branch you like but it is highly recommended that you use a branch that is protected and only has stable code in it. An example would be using main or master as your stable branch and enforcing strict branch protection rules on it to ensure that only stable code is merged into it

Security 🔒

The IssueOps + branch-deploy model is significantly more secure than a traditional "deploy on merge" or "run on commit" model. Let's reference the workflow trigger that the branch-deploy model uses:

on:
  issue_comment:
    types: [created]

Unlike the on: pull_request trigger, the on: issue_comment trigger only uses Actions workflow files from the default branch in GitHub. This means that a bad actor cannot open a PR with a malicious workflow edit and dump secrets, trigger bad deployments, or cause other issues. This means that any changes to the workflow files can be protected with branch protection rules to ensure only verified changes make it into your default branch.

To further harden your workflow files, it is strongly suggested to include the base permissions that this Action needs to run:

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

Permissions Explained:

  • pull-requests: write - Required to add comments to pull requests with deployment results
  • deployments: write - Required to update repository deployment statuses
  • contents: write - Write access is required for this Action to create "lock" branches for deployments
  • checks: read - Only read access is needed for this Action to get the status of other CI checks
  • statuses: read - Only read access is needed for this Action to get the commit statuses of commits in the PR

It should also be noted that this Action has built in functions to check the permissions of a user who invokes a IssueOps command. If the user does not have write or greater permissions to the repository, their command will be rejected

Admins 👩‍🔬

This Action supports a configurable input called admins which can be used to specify a list of individual GitHub users or teams that should have elevated permissions when using this Action

The admins input option takes a comma separated list of GitHub handles or GitHub org teams which can bypass branch protection rules related to approvals for deployments. For example, if you give the option admins: monalisa, the monalisa user will be able to deploy without needing approval on their pull requests. CI checks will still need to pass however.

It should be noted that if you do not have pull request approvals enabled in your branch protection rules, then this option will not make a difference either way

Here is a simple example using only handles below (the monalisa and octocat users will be treated as admins):

- uses: github/[email protected]
  id: branch-deploy
  with:
    admins: monalisa,octocat

Here is an example using a mix of GitHub handles and a GitHub org team below:

- uses: github/[email protected]
  id: branch-deploy
  with:
    admins: monalisa,octocat,octo-awesome-org/octo-awesome-team
    admins_pat: ${{ secrets.BRANCH_DEPLOY_ADMINS_PAT }}

In this case, all users (and future users) in the octo-awesome-org/octo-awesome-team team will be treated as admins in addition to the monalisa and octocat users

It should be noted if you choose to use GitHub org teams for admin definitions, you will need a GitHub Personal Access Token with the read:org scope. This is because the Action will need to make API calls on behalf of an authenticated user in the org to retrieve team memberships. If you choose to only use GitHub handles for admin definitions, then the admins_pat input is not required

Note: You can read more about the admin option under the inputs section in this readme

Actions Stability 🔧

In order to ensure your usage of this action is stable, it is highly recommended that you use either pin your action to a SHA or use a specific release tag

Actions Tag Pinning

You can easily select the exact version you want on the GitHub Actions marketplace seen in the screenshot below:

Screenshot from 2022-05-09 12-12-06

Actions SHA Pinning

You can also pin to an exact commit SHA as well using a third party tool such as mheap/pin-github-action

GitHub Actions security hardening and stability docs available here: docs

Deployment Locks and Actions Concurrency 🔓

For full details about how this Action handles deployment locks and concurrency, please see the deployment locks and concurrency documentation

This linked document also contains usage, setup details, and examples

Merge Commit Workflow Strategy

Checkout the merge commit workflow strategy for more information on how to use this Action with a merge commit workflow strategy.

Manual Deployment Control

If you need more fine tuned control over when the deployment status is set to success you can use the skip_completing option to prevent this Action from setting your deployment status to success after it completes.

When using this option, you will need to manually set your deployment status depending on if you deployment succeeds or fails.

An example workflow using this option can be found here

Saving on Actions Compute

If you are looking to save on Actions compute time, here is a helpful tip! You can use the if conditional to only run this Action when a specific comment is made on a pull request. This can help you save on Actions compute time by only running this Action when it should truly be invoked.

Here is an example workflow demonstrating the if conditional:

name: "branch deploy demo"

# The workflow to execute on is comments that are newly created
on:
  issue_comment:
    types: [created]

# Permissions needed for reacting and adding comments for IssueOps commands
permissions:
  pull-requests: write
  deployments: write
  contents: write
  checks: read
  statuses: read

jobs:
  demo:
    if: # only run on pull request comments and very specific comment body string as defined in our branch-deploy settings - this will save on Actions compute time
      ${{ github.event.issue.pull_request &&
      (startsWith(github.event.comment.body, '.deploy') ||
      startsWith(github.event.comment.body, '.noop') ||
      startsWith(github.event.comment.body, '.lock') ||
      startsWith(github.event.comment.body, '.help') ||
      startsWith(github.event.comment.body, '.wcid') ||
      startsWith(github.event.comment.body, '.unlock')) }}
    runs-on: ubuntu-latest
    steps:
      - uses: github/[email protected] # replace with the latest version
        id: branch-deploy
        with:
          trigger: ".deploy"
          noop_trigger: ".noop"
          lock_trigger: ".lock"
          unlock_trigger: ".unlock"
          help_trigger: ".help"
          lock_info_alias: ".wcid"
          # these are all the command definitions that we want to listen for (above) ^

      # Run your deployment logic for your project below...

Examples

This section contains real world examples of how this Action can be used

Checkout the examples document for more examples

Remember, these are just examples and you can quite literally configure this Action for any deployment target you want!

Live Examples 📸

What to see live examples of this Action in use?

Check out some of the links below to see how others are using this Action in their projects:

Are you using this Action in a cool new way? Open a pull request to this repo to have your workflow added to the list above!

Suggestions 🌟

This section will cover a few suggestions that will help you when using this Action

  1. Suggest Updating Pull Request Branches - You should absolutely use this option when using the branch-deploy Action. This option can be found in your repository's /settings page

    branch-setting

  2. Enable Branch Protection Settings - It is always a good idea to enable branch protection settings for your repo, especially when using this Action

Alternate Command Syntax

Here are a few alternate ways you can invoke commands:

  • .noop staging - Invoke a "noop" deployment to the staging environment
  • .deploy development - Invoke a deployment to the development environment (notice how you can omit the "to" keyword)
  • .deploy to development - Invoke a deployment to the development environment (with the "to" keyword)
  • .deploy - Uses the default environment (usually "production")
  • .wcid - Alias for .lock --details meaning "where can I deploy?"

Check out the usage guide for more information


Contributing 💻

All contributions are welcome from all!

Check out the contributing guide to learn more

If you are a maintainer of this Action, please see the maintainer guide for more information

branch-deploy's People

Contributors

chrisgavin avatar dependabot[bot] avatar garnertb avatar grantbirki avatar greysteil avatar juboe-kion avatar kyo-nanba avatar ncalteen avatar nobe4 avatar nodeselector avatar reggi avatar sinsoku avatar tiagonbotelho avatar ugzuzg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

branch-deploy's Issues

Mandate pull request merge only after branch-deploy workflow succeeds

Details

I am evaluating the branch-deploy action as part of a Terraform-infrastructure deployment workflow.

My process mandates that a pull request can only be merged post the successful application of all infrastructure changes to target environments.

The obvious solution would be to configure jobs of the branch-deploy workflow, e.g., the Terraform apply job, as status checks in branch protection rules. However, since the branch-deploy workflow runs in the context of the main branch - the consequence of the on: issue_comment trigger - status checks are never reported to the feature-branch and thus never succeed.

I am wondering if there is a solution to this within the scope of the IssueOps approach, or if a "hacky" approach is necessary, e.g., manual status reporting via the GitHub API? I would appreciate any insights if you have encountered a similar process or use case. Thanks!

Prefixing environments for mono-repo setup

Details

I handle infrastructure code (Terraform) in a mono-repo, which necessitates the deployment of numerous projects across various environments from a single repository.

I managed to implement a separate branch-deployment gate for each project using distinct triggers:

trigger:
  if: |
    github.event.issue.pull_request
  runs-on: ubuntu-latest
  steps:
    - name: Gate branch deployment
      id: branch-deploy
      uses: github/[email protected]
      with:
        trigger: .deploy ${{ inputs.project_name }}
        noop_trigger: plan

The above configuration produces the following IssueOps interface:

.deploy foo dev/staging/prod
.deploy foo plan dev/staging/prod

.deploy bar dev/staging/prod
.deploy bar plan dev/staging/prod

However, given multiple projects, specified environments, i.e., dev/staging/prod, are "shared" (from the branch-deploy action's perspective), which implies that whenever I deploy to project foo, corresponding Github environments are being locked and altered with deployment status, preventing me against deploying to the boo project from other pull requests.

Consequently, in a mono-repo setup, one must distinguish Github environments by project, e.g., using a prefix: foo-dev vs. bar-dev, foo-prod vs. bar-prod, etc.

That is possible to implement by a combination of environment and environment_targets input variables:

environment: foo-dev
environment_targets: foo-dev,foo-staging,foo-prod

However, with the current design of the branch-deploy action, the IssueOps interface would look like this:

.deploy foo foo-dev
.deploy bar bar-dev

... which seems inconvenient and unreadable as one has to repeat the project name twice.

I wonder if we could introduce an additional parameter, e.g., environment_prefix, that would alter the behavior of the branch-deploy action internally so that the action, given an environment dev (from issue comment), prefixes it internally with environment_prefix and only the prefixed Github environment is used for further processing. In other words, it would be great to somehow separate input environments from Github environments.

environment: dev
environment_targets: dev,staging,prod
environment_prefix: foo

That would be a significant enabler towards adopting the action into existing mono-repo configurations.

Introduce a `.help` command

We currently developed a small workflow that triggers whenever a PR get created providing instructions on how to use branch-deploy, like the image below.

Screenshot 2022-10-24 at 15 02 10

It'd be great to introduce something similar to this by default in the action itself 🚀

When there are no checks deployment isn't allowed

Describe the Issue

A changeset that doesn't trigger any checks cannot be deployed;
image

We've changed one of our bicep files (and of course you could argue we should have a compile check on those, but we don't currently) and as such it doesn't let us deploy.

Action Configuration

      - name: Branch deployment
        id: branch-deploy
        uses: github/[email protected]
        with:
          # see https://github.com/github/branch-deploy#inputs-
          environment: qa # the default environment
          environment_targets: "qa"
          skip_reviews: "qa"
          environment_urls: "qa|https://qa.example.com"
          update_branch: disabled
          merge_deploy_mode: false
          stable_branch: master
          allow_forks: false
          environment_url_in_comment: true

Relevant Actions Log Output

No response

Extra Information

No response

Export locking functions

I'm using branch-deploy but also want to be able to trigger individual deploys using workflow-dispatch. In order to do this I need to be able to control the locks myself rather than relying on branch-deploy.

I wonder if it would make sense to create an actions subdirectory for these two bits of functionality so we can reference them like this:

  uses: github/branch-deploy/actions/[email protected]

So then it'd be a case of writing our actions manifest and a little bit of javascript for the two actions:

  • create actions/lock/actions.yaml and actions/lock/index.js
  • create actions/unlock/actions.yaml and actions/unlock/index.js

WDYT?

Make checks required only for specific environments

Hello 👋

We currently have a use case where one of the environments we are deploying to is used specifically for development, which shouldn't necessarily require an review approval before being able to deploy. However, using branch-deploy as it stands, in order to deploy any environment, the PR needs to be in an approved state.

Would it be feasible to somehow introduce an option (defaulting to all environments) to allow some environments to skip the checks perhaps? 🤔

Process for altering workflow configuration

Describe the Issue

I am trying to develop a process for altering the workflow configuration when using the branch-deploy action.

By design, the workflow is executed based on the configuration in the main branch, meaning I can only test changes after a merge. This poses a risk of introducing workflow bugs into the main branch.

Changing the workflow trigger, e.g., to on: pull_request, is not an option as the action is driven by issue comments.

What is the recommended development process when using this action?

Thank you in advance for any help. I am really enjoying working with this tool! 😃

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

Action is not working with "Require deployments to succeed before merging"

I'm trying to get to the stage where I can auto-merge a branch once status checks and deployments to multiple environments have succeeded. I've noticed though that whenever I run .deploy prd for an environment, it does not have any impact on the deployment check.

image

The action step is as follows:

      - uses: github/[email protected]
        id: branch-deploy
        with:
          trigger: ".deploy"
          environment: nonprod
          environment_targets: nonprod, prd 

The three questions I have are:

  1. Is this known behaviour?
  2. Is there some configuration that I'm not setting?
  3. If the branch-deploy action isn't able to update the deployment check correctly, what's the simplest way around the issue? (Separate workflow files per environment?)

Thanks

Malicious workflow manipulation

Describe the Issue

In the security section of the README there is the following statement:

The IssueOps + branch-deploy model is significantly more secure than a traditional "deploy on merge" or "run on commit" model. Let's reference the workflow trigger that the branch-deploy model uses (...)

Unlike the on: pull_request trigger, the on: issue_comment trigger only uses Actions workflow files from the default branch in GitHub. This means that a bad actor cannot open a PR with a malicious workflow edit and dump secrets, trigger bad deployments, or cause other issues. This means that any changes to the workflow files can be protected with branch protection rules to ensure only verified changes make it into your default branch.

What if a bad actor opens a PR with a custom workflow having a different trigger, e.g., on: pull_request, and executes abusive actions that skip the branch-deploy policy? Branch protection rules do not protect us in this case. Do you have any recommendations on how to secure the branch-deploy process against malicious workflow manipulation?

My concern is mainly related to the statement:

This means that a bad actor cannot open a PR with a malicious workflow edit and dump secrets, trigger bad deployments, or cause other issues

Perhaps, this matter requires more explanation. Thanks in advance for any guidance!

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

Environment-specific locks

Would be nice if we could toggle sticky locks for specific environments by providing the environment name after the trigger, such as .lock staging & .unlock development. Then the lock should only affect deployments to the locked environment, so that I could lock a branch to staging, but still deploy to development. A universal lock could still be applied by omitting the environment parameter.

Additionally, it'd be nice to have an action with an environment option that checks if a lock exists. This way we could use these locks when triggering deployments via other methods such as pushes to the main branch.

Something with a pattern like:

- name: lock-exists
  id: lock-exists
  uses: github/lock-exists
  with:
    environment: development

- name: deploy
  if: ${{ steps.lock-exists.outputs.exists == 'false' }}
  # deployment script, etc

Basically, I'm looking to deploy to all environments on pushes to main by default, but omit the deploys to development and staging when they're locked.

Unable to lock and unlock specific environments

Describe the Issue

I am unable to lock and unlock specific deployment environments when using .lock and .unlock commands:

Screenshot 2023-08-16 at 10 58 46

However, when no specific environment is selected, the default one is successfully unlocked:

Screenshot 2023-08-16 at 10 54 22

I am using custom trigger for both lock and unlock as visible in the attached action configuration.

Action Configuration

- name: Gate branch deployment
  id: branch-deploy
  uses: github/[email protected]
  with:
    trigger: .deploy app
    lock_trigger: .lock app
    unlock_trigger: .unlock app
    help_trigger: .help app
    noop_trigger: .plan app
    environment: app-dev
    environment_targets: app-dev,app-staging,app-prod
    production_environment: app-prod
    draft_permitted_targets: app-dev,app-staging,app-prod
    stable_branch: master
    prefix_only: true
    skip_completing: true

Relevant Actions Log Output

No response

Extra Information

No response

Large plans/applies throw an odd error

Describe the Issue

When I try to do large deploys I get a failure like the one below:

Error: An error occurred trying to start process '/usr/bin/bash' with working directory '/home/runner/work/****. Argument list too long

Feel free to slack me 😄

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

Bug: does not observe required checks

At the moment deploys are blocked on all status checks passing, even if they're not required.

This is because statusCheckRollup.state doesn't care about whether a check is required or not:

https://github.com/github/branch-deploy/blob/43afd75c657a06c55c953cc7af493d9cf565aa43/src/functions/prechecks.js#LL151

I don't know if there's an elegant way to check this 😢 (especially one that avoids paging through results). The best graphql I could come up with was this:

{
  repository(owner: "github", name: "branch-deploy") {
    pullRequest(number: 69) {
      reviewDecision
      commits(last: 1) {
        nodes {
          commit {
            checkSuites {
              totalCount
            }
            statusCheckRollup {
              state
              contexts(first: 100) {
                nodes {
                  ... on CheckRun {
                    isRequired(pullRequestNumber: 69)
                    conclusion
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Users with role 'maintain' cannot trigger deployments

Describe the Issue

Hi! We're using this action in our organization, but are currently facing an issue with some users who have the maintain role.

Problem description

It seems that when a user (only?) has the maintain role, he is not allowed to run commands using this action. When a deploy is triggered by a user with this permission, the following message appears:

👋 actor, seems as if you have not admin/write permissions in this repo, permissions: maintain

However, if I understand the GitHub docs correctly, this role should sit between the Write and Admin roles. Thus, we'd also expect a user with this role to be able to trigger deployments.

Probable root cause

Seems like the values admin and write are hard-coded in the valid-permissions.js file:

  // Check to ensure the user has at least write permission on the repo
  const actorPermission = permissionRes.data.permission
  if (!['admin', 'write'].includes(actorPermission)) {
    return `👋 __${context.actor}__, seems as if you have not admin/write permissions in this repo, permissions: ${actorPermission}`
  }

Action Configuration

on:
  issue_comment:
    types: [created, edited]

jobs:
  trigger:
    if: ${{ github.event.issue.pull_request && github.actor != 'xyz' }}
    runs-on: ubuntu-latest
    steps:
      - uses: github/[email protected]
        id: branch-deploy
        with:
          trigger: ".deploy-xyz"
          environment: dev-xyz
          environment_targets: dev-xyz
          update_branch: disabled
          skip_reviews: dev-xyz
          skip_ci: dev-xyz
          skip_completing: "true"
          lock_trigger: ".lock-xyz"
          unlock_trigger: ".unlock-xyz"

Relevant Actions Log Output

Error: 👋 xyz, seems as if you have not admin/write permissions in this repo, permissions: maintain

Extra Information

No response

prefix_only=false is not having any effect

Describe the Issue

We are running into issues using the prefix_only config. Setting it to "false" seems to not take any effect.

We would expect that we can trigger a deployment to "dev" using following:

something .deploy dev
something .deploy
.deploy dev something
something .deploy dev something

We want to add "something" to the comment so that we can read it from the comment body and hand it over to subsequent workflow jobs.

It is possible that I do not understand the documentation for prefiex_only correctly. MAybe someone can elaborate this a little more?

Action Configuration

    - uses: github/[email protected]
      id: branch-deploy
      with:
        trigger: ".deploy"
        environment: dev
        environment_targets: dev
        update_branch: disabled
        skip_reviews: dev
        skip_ci: dev
        skip_completing: 'true'
        prefix_only: 'false'

Relevant Actions Log Output

2023-05-09T11:25:12.6594583Z ##[debug]Evaluating condition for step: 'Run github/[email protected]'
2023-05-09T11:25:12.6596557Z ##[debug]Evaluating: success()
2023-05-09T11:25:12.6597081Z ##[debug]Evaluating success:
2023-05-09T11:25:12.6597623Z ##[debug]=> true
2023-05-09T11:25:12.6598251Z ##[debug]Result: true
2023-05-09T11:25:12.6599087Z ##[debug]Starting: Run github/[email protected]
2023-05-09T11:25:12.6644944Z ##[debug]Register post job cleanup for action: github/[email protected]
2023-05-09T11:25:12.6667339Z ##[debug]Loading inputs
2023-05-09T11:25:12.6671913Z ##[debug]Evaluating: github.token
2023-05-09T11:25:12.6672406Z ##[debug]Evaluating Index:
2023-05-09T11:25:12.6672761Z ##[debug]..Evaluating github:
2023-05-09T11:25:12.6673144Z ##[debug]..=> Object
2023-05-09T11:25:12.6673519Z ##[debug]..Evaluating String:
2023-05-09T11:25:12.6674023Z ##[debug]..=> 'token'
2023-05-09T11:25:12.6674778Z ##[debug]=> ''
2023-05-09T11:25:12.6676656Z ##[debug]Result: '
'
2023-05-09T11:25:12.6678593Z ##[debug]Evaluating: job.status
2023-05-09T11:25:12.6678993Z ##[debug]Evaluating Index:
2023-05-09T11:25:12.6679366Z ##[debug]..Evaluating job:
2023-05-09T11:25:12.6679732Z ##[debug]..=> Object
2023-05-09T11:25:12.6845352Z ##[debug]..Evaluating String:
2023-05-09T11:25:12.6845681Z ##[debug]..=> 'status'
2023-05-09T11:25:12.6846098Z ##[debug]=> 'success'
2023-05-09T11:25:12.6846387Z ##[debug]Result: 'success'
2023-05-09T11:25:12.6855503Z ##[debug]Loading env
2023-05-09T11:25:12.6892515Z ##[group]Run github/[email protected]
2023-05-09T11:25:12.6892862Z with:
2023-05-09T11:25:12.6893099Z trigger: .deploy
2023-05-09T11:25:12.6893342Z environment: dev
2023-05-09T11:25:12.6893597Z environment_targets: dev
2023-05-09T11:25:12.6893870Z update_branch: disabled
2023-05-09T11:25:12.6894121Z skip_reviews: dev
2023-05-09T11:25:12.6894365Z skip_ci: dev
2023-05-09T11:25:12.6894618Z skip_completing: true
2023-05-09T11:25:12.6894962Z prefix_only: false
2023-05-09T11:25:12.6895463Z github_token: ***
2023-05-09T11:25:12.6895727Z status: success
2023-05-09T11:25:12.6895994Z environment_url_in_comment: true
2023-05-09T11:25:12.6896301Z production_environment: production
2023-05-09T11:25:12.6896584Z reaction: eyes
2023-05-09T11:25:12.6896829Z noop_trigger: noop
2023-05-09T11:25:12.6897070Z lock_trigger: .lock
2023-05-09T11:25:12.6897565Z unlock_trigger: .unlock
2023-05-09T11:25:12.6897818Z help_trigger: .help
2023-05-09T11:25:12.6898071Z lock_info_alias: .wcid
2023-05-09T11:25:12.6898331Z global_lock_flag: --global
2023-05-09T11:25:12.6898594Z stable_branch: main
2023-05-09T11:25:12.6898848Z required_contexts: false
2023-05-09T11:25:12.6899101Z allow_forks: true
2023-05-09T11:25:12.6899334Z admins: false
2023-05-09T11:25:12.6899571Z admins_pat: false
2023-05-09T11:25:12.6899812Z merge_deploy_mode: false
2023-05-09T11:25:12.6900065Z ##[endgroup]
2023-05-09T11:25:12.8849144Z ##[debug]Trigger ".lock" not found in the comment body
2023-05-09T11:25:12.8852076Z ##[debug]Trigger ".unlock" not found in the comment body
2023-05-09T11:25:12.8852694Z ##[debug]Trigger ".help" not found in the comment body
2023-05-09T11:25:12.8853267Z ##[debug]Trigger ".wcid" not found in the comment body
2023-05-09T11:25:13.2234683Z ##[warning]No matching environment target found. Please check your command and try again. You can read more about environment targets in the README of this Action.

The following environment targets are available: dev
2023-05-09T11:25:14.6460684Z ##[debug]No valid environment targets found
2023-05-09T11:25:14.6483908Z ##[debug]Node Action run completed with exit code 0

Extra Information

No response

Unlock environments on pull request merge

Describe the Issue

I am trying to recreate the locking feature of the Atlantis workflow using the branch-deploy action.

In Atlantis, it is possible to configure a workflow behavior where a lock is acquired on terraform plan for a set of directories, and the lock is released after the pull request is successfully merged into the main branch.

When running terraform apply before a pull request is merged, the main branch ceases to represent the most current version of the infrastructure. Locking ensures no further changes occur until the PR is merged, keeping the infrastructure representation intact. More reasoning behind this concept is well explained in Atlantis documentation.

I believe incorporating a similar locking feature would be a significant improvement for Terraform users of this action. This is particularly relevant given that Terraform is showcased as one of the main usage examples.

When using the branch-deploy action, it is easy to implement the first part of the locking feature, i.e., acquire a lock on terraform plan (or apply) using the lock action. However, it is problematic to release the lock on the pull request merge (e.g., using the on: pull_request[closed] trigger). The main difficulty lies in obtaining the list of active locks to release.

I would genuinely appreciate any insights you might have on implementing this functionality. Perhaps, I missed some details in the documentation or usage examples.

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

Is it possible to limit environment deployments to a specific `base_ref`?

Details

If I want to limit deployments to environment A and B to PRs against main, and deployments to environment C to PRs against release/*. Is that possible using this action? I figured I'd include a github.base_ref check and have two workflows, one for A & B, and one for C, but there's no base_ref in an issue_comment it seems.

Unsafe SHA Deployments

Unsafe SHA Deployments

The following pull request (#212) enables users to use the branch-deploy Action to deploy an exact SHA1 or SHA256 hash instead of a branch. While this feature can be incredibly useful or even necessary for some projects, it can be dangerous and unsafe.

Why is this option dangerous / unsafe?

Before we start, let's first take a look at how SHA1/256 hashes are used in Git. Branches, tags, and commits, all point to a "SHA" under the hood. So think of a branch / tag as a friendly name to point to a SHA at a certain point in time.

When using the branch-deploy Action in its default configuration, a user is typically either deploying a branch associated with a pull request, or they are deploying main (the main or default branch) in a rollback should something go wrong.

Branches can be associated with CI checks, and approvals. The main (or default) branch can be associated with branch protection rules and we can often assume that changes only land on main once they have gone through the proper pull request process.

Now pulling together all the statements above... what does this tell us about deploying a given SHA? It can be incredibly risky. A user could comment .deploy <sha> on their pull request and deploy a commit attached to another user's pull request that has not been approved or tested. This could potentially allow for malicious or broken code to be deployed.

Since a given SHA could originate from anywhere in a given Git project, we can't reliably check if CI passed or if approvals were given for the SHA in question.

Given all of the above, it is clear that deploying SHAs could potentially be unsafe if you are unfamiliar with the actions being taken by this style of deployment

My project structure requires SHA deployments, what should I do?

Just because SHA deployments can be unsafe doesn't mean that they will be unsafe.

For example, if you:

  • Understand the risks
  • Have proper and restricted repo permissions for your collaborators (i.e. the whole company doesn't have write access to deploy)
  • Trust your collaborators
  • Have a well defined rollback process

Then you can properly evaluate the risk of enabling this deployment option.

Enabling SHA Deployments

In order to use this feature, you must set the following input option:

- uses: github/[email protected]
  id: branch-deploy
  with:
    allow_sha_deployments: "true" # <--- this option must be "true"

The reasoning for this is that SHA deployments can easily become dangerous. So users should be informed, and have to manually enable this feature for it to be used.

Example 📸

Once you have enabled SHA deployments, you should see some output similar to this example to know that it is working properly.

image

`update_branch: warn` doesn’t catch before createDeployment

Describe the Issue

When using the default for update_branch the expected warn and fail scenario is not run.

Action Configuration

##[group]Run github/[email protected]
with:
  production_environment: prod
  environment_targets: sandbox,qa,prod
  environment: sandbox
  skip_completing: true
  github_token: ***
  status: success
  reaction: eyes
  trigger: .deploy
  noop_trigger: noop
  lock_trigger: .lock
  unlock_trigger: .unlock
  help_trigger: .help
  lock_info_alias: .wcid
  stable_branch: main
  prefix_only: true
  update_branch: warn
  required_contexts: false
  allow_forks: true
  admins: false
  admins_pat: false
  merge_deploy_mode: false
##[endgroup]

Relevant Actions Log Output

Skipping commit status check and proceeding...
##[debug]raw graphql result for debugging:
##[debug]{"repository":{"pullRequest":{"reviewDecision":null,"mergeStateStatus":"HAS_HOOKS","commits":{"nodes":[{"commit":{"checkSuites":{"totalCount":1},"statusCheckRollup":null}}]}}}}
##[debug]raw admins value: false
##[debug]***** is not an admin
##[debug]precheck values for debugging:
##[debug]reviewDecision: null
##[debug]mergeStateStatus: HAS_HOOKS
##[debug]commitStatus: null
##[debug]userIsAdmin: false
##[debug]update_branch: warn
##[debug]skipCi: false
##[debug]skipReviews: false
##[debug]allowForks: true
##[debug]forkBypass: false
##[debug]environment: sandbox
##[debug]behind: false
⚠️ CI checks have not been defined and required reviewers have not been defined... proceeding - OK

Extra Information

Using GHES 3.6.2 and including the log output that seems the most different from a GitHub Cloud run.

HttpError: Branch not found

Describe the Issue

More frequently than before I observe the following error when executing the branch deploy action:

Error: HttpError: Branch <environment>-branch-deploy-lock not found
    at /runner/_work/_actions/github/branch-deploy/v7.0.0/webpack:/branch-deploy-action/node_modules/@octokit/request/dist-node/index.js:86:1
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at createLock (/runner/_work/_actions/github/branch-deploy/v7.0.0/webpack:/branch-deploy-action/src/functions/lock.js:70:1)
    at lock (/runner/_work/_actions/github/branch-deploy/v7.0.0/webpack:/branch-deploy-action/src/functions/lock.js:600:1)
    at run (/runner/_work/_actions/github/branch-deploy/v7.0.0/webpack:/branch-deploy-action/src/main.js:444:1)
Error: Branch <environment>-branch-deploy-lock not found

The issue originates in here:

  // Create the lock branch if it doesn't exist
  await createBranch(octokit, context, branchName)

  // Create the lock file
  await createLock(
    octokit,
    context,
    ref,
    reason,
    sticky,
    environment,
    global,
    reactionId
  )

It seems that the newly created lock branch is not always available when the createLock method is called, which is responsible for updating the lock file in that branch.

Indeed, I checked and the lock file is not present on the branch when the action fails.

Action Configuration

- name: Gate branch deployment
  id: branch-deploy
  uses: github/[email protected]
  with:
    trigger: .deploy app
    lock_trigger: .lock app
    unlock_trigger: .unlock app
    help_trigger: .help app
    noop_trigger: .plan app
    environment: dev
    environment_targets: dev,prod
    production_environment: prod
    stable_branch: master
    prefix_only: true
    skip_completing: true
    reaction: eyes

Relevant Actions Log Output

No response

Extra Information

No response

Multiple `production_environment`

Describe the Issue

I've got a scenario where I have multiple production environments all managed in the same environment.

There doesn't seem to be a way to have multiple production environments managed within the same repository? While there are ways to have multiple environments, it feels that the production_environment is meant for the main one?

Does it make sense to just set production_environment to something obscure if you have multiple production environments?

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

Sticky Locks Removed - Bug

Sticky Locks Removed - Bug

Sticky locks are being removed after a deployment

Note: I'm just making note of this here and will update the issue later on


Replication

  1. .lock to obtain a lock
  2. .deploy and the lock gets removed after the successful deployment - this is a bug and sticky locks should not be removed in this manner

Can pass custom parameters?

If managing multiple projects in one repository (like a monorepo), may need condition handling in deploy scripts to only deploy a specific project. (like on.workflow_dispatch.inputs)

Is there any way currently possible?
For example .deploy --project foobar (Similar to .lock --reason <text>)

Use branch deploy environments together with configure-aws-credentials github action

Details

I'm testing branch-deploy to deploy to AWS. I'm using github OpeniD connect and the configure-aws-credentials github action and a trust policy requiring an environment to be passed with the request in IAM role trust policy like this:

        "Condition": {
            "StringEquals": {
                "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
            },
            "ForAnyValue:StringEquals": {
                "token.actions.githubusercontent.com:sub": [
                    "repo:<org>/<reponame>:environment:beta"
                ]
            }

When I'm setting environment on the job: in the workflow I'm able to authetnicate with the configure-aws-credentials action, but it does not work when I'm passing in an environment using f.ex .deploy to beta or just having one default environment set for branch deploy action and using .deploy. Looking in the log the environment is not part of the claims.

It would be really neat if this was supported to allow dynamic definition of environment using the .deploy command together with the configure-aws-credentials role. Is it possible to configure branch-deploy so that aws-configure-credentials passes the environment as the claim the same it is picked up when environment is set on a job:?

I'm calling the configure-aws-credentials action like this:

  - uses: aws-actions/configure-aws-credentials@v2
    if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }}
    with:
      role-to-assume: '<arn of role>'
      aws-region: eu-west-1

Include branch SHA in outputs

To ensure we're using the latest branch commit during the deployment step, we need the sha of the ref in the action's outputs as well. Very similar to how the ref is updated to use the specific sha for forks, but simply a separate output to use.

https://github.com/github/branch-deploy/blob/c2a6b34cdfdd0ddd7c73895e8ca6ffda6d45623e/src/functions/prechecks.js#LL144C5-L144C27

This will help when we branch-deploy back-to-back from a PR so we can check that we're deploying the right version without having to always run extra GitHub API calls to get the sha from the context's head.

(this is my first real public issue requesting a feature - my apologies if I'm not doing this right

`.lock` and `.unlock` commands not working with `--reason`

Pretty much the title. Opening this issue to track fixes

initially detected here: #185 (comment)


Debug log:

Trigger ".deploy" not found in the comment body
Trigger ".noop" not found in the comment body
Trigger ".unlock" not found in the comment body
Trigger ".help" not found in the comment body
Trigger ".wcid" not found in the comment body
##[debug]'--reason' found in comment body: .lock --reason "i am testing out the brancheploy action" - attempting to remove for environment checks
##[debug]comment body after '--reason' removal: .lock 
##[debug]Using default environment for lock request
##[debug]reason: "i am testing out the branch-deploy action"
##[debug]detected lock env: production
##[debug]detected lock global: false
##[debug]constructed lock branch: production-branch-deploy-lock
##[debug]lock branch production-branch-deploy-lock does not exist
no active deployment locks found
##[debug]Node Action run completed with exit code 0

Question: Two jobs (build and then deploy) behind one trigger?

Apologies in advance if this is a dumb question but having a hard time wrapping my head around it.

I'm migrating from a merge deploy based workflow with two jobs. I've got a build job that does a matrix to build and push some images to a container registry, and then a second job that performs the actual deploy of the images from the build job.

Something like:

jobs:
  build:
    if: <if main or dev && is a push>
    strategy:
      matrix:
    ...
    steps:
     <build a bunch of images and push them to a registry>

  deploy:
    if: <if main or dev && is a push>
    needs: build
    steps:
      <reference some output from build, and call some deployment steps, tf plan etc>

What's the best way to transition these to using the branch-deploy action and have them execute sequentially?

Can I just use the branch-deploy action with the same keyword trigger on each job - and then keep the needs requirement of the second job? Do I need to merge these two jobs into a single one? Or should I have two discrete keyword triggers for each e.g. .build and .deploy?

Add `.noop` alias prefix for `.deploy noop`

Capturing this in an issue before I fork off and start work on this.

At the moment we use branch-deploy a lot and it's slightly terrifying how easy it is to almost run a prod deploy when the intention is to run a noop deploy.

It'd be very cool (in my opinion) to have the option of typing a very differently patterned command to reduce the margin for human error (especially with so many folks using that repo).

Code Coverage Badge

Any specific reason why the code coverage badge on the README.md is just an SVG? I just thought that seemed a little goofy, I mean I guess we always have 100% code coverage then? 😃

Demo not working properly

I made minor changes to the demo and cannot get it to work. Added issues: write to the permissions and environment: "test".

name: "branch deploy demo"
on:
  issue_comment:
    types: [created]
permissions:
  pull-requests: write
  deployments: write
  contents: write
  issues: write

jobs:
  demo:
    if: ${{ github.event.issue.pull_request }}
    runs-on: ubuntu-latest
    steps:
      - uses: github/[email protected]
        id: branch-deploy
        with:
          trigger: ".deploy"
          environment: "test"
      - uses: actions/checkout@v3
        with:
          ref: ${{ steps.branch-deploy.outputs.ref }}
      - name: fake noop deploy
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop == 'true' }}
        run: echo "I am doing a fake noop deploy"
      - name: fake regular deploy
        if: ${{ steps.branch-deploy.outputs.continue == 'true' && steps.branch-deploy.outputs.noop != 'true' }}
        run: echo "I am doing a fake regular deploy"

Getting this error:

GraphqlResponseError: Request failed due to following response errors:
 - Resource not accessible by integration
    at /home/runner/work/_actions/github/branch-deploy/v2.2.0/webpack:/branch-deploy-action/node_modules/@octokit/graphql/dist-node/index.js:81:1
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at prechecks (/home/runner/work/_actions/github/branch-deploy/v2.2.0/webpack:/branch-deploy-action/src/functions/prechecks.js:166:1)
    at run (/home/runner/work/_actions/github/branch-deploy/v2.2.0/webpack:/branch-deploy-action/src/main.js:264:1)

Question: How can I deploy a pr to multiple environments (prod and qa) using branch-deploy?

Hello and thank you for this action. I think once I customize it for our organization, it will significantly improve our deployment frequency. Below are two different workflows that I use for deploying an ecs service to qa and prod aws accounts. How can I use this action if I want to deploy a pr to first qa environment and then to prod environment? Do I need two workflows? Thanks.

Thanks!

name: Deploy to Amazon ECS QA Environment
on:
  push:
    branches:
      - develop
    paths-ignore:
      - src/LambdaFunctions/**
      - .github/workflows/scheduled-event-triggers-sam-deploy-qa.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  id-token: write # required to use OIDC authentication
  contents: read # required to checkout the code from the repo

jobs:
  call-dockerized-build:
    uses: MyOrg/shared-actions/.github/workflows/ci-dockerized-app-build.yml@cloud-367/shared-backend-actions
    name: Call Dockerized Build
    with:
      environment: qa
      region: eu-west-1
      namespace: org
      service_name: fulfillment
      app_dockerfile: docker/app.dockerfile
      pre_release: true
      dry_run: false
    secrets:
      aws_role_to_assume: ${{ secrets.AWS_QA_ROLE_TO_ASSUME_ARN }}
      cert_file: ${{ secrets.QA_CERT_FILE }}
      dhparam_file: ${{ secrets.QA_DHPARAM_FILE }}
      key_file: ${{ secrets.QA_KEY_FILE }}
      gh_packages_user: ${{ secrets.GH_PACKAGES_USER }}
      gh_packages_pat: ${{ secrets.GH_PACKAGES_PAT }}
      application_id: ${{ secrets.APPLICATION_ID }}
      application_private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}

  call-ecs-deploy:
    uses: MyOrg/shared-actions/.github/workflows/cd-ecs.yml@cloud-367/shared-backend-actions
    needs: call-dockerized-build
    name: Call ECS Deploy
    with:
      environment: qa
      region: eu-west-1
      namespace: org
      service_name: fulfillment
      tag: ${{ needs.call-dockerized-build.outputs.tag }}
    secrets:
      aws_role_to_assume: ${{ secrets.AWS_QA_ROLE_TO_ASSUME_ARN }}

  call-post-deployment-status-to-slack:
    uses: MyOrg/shared-actions/.github/workflows/controller-post-ecs-deployment-info-to-slack.yml@cloud-367/shared-backend-actions
    needs: call-ecs-deploy
    name: Call Post Deployment Status to Slack
    with:
      environment: qa
      region: eu-west-1
      namespace: org
      service_name: fulfillment
      slack_channel: "#dev-team"
    secrets: inherit
name: Deploy to Amazon ECS PROD Environment
on:
  push:
    branches:
      - main
    paths-ignore:
      - src/LambdaFunctions/**
      - .github/workflows/scheduled-event-triggers-sam-deploy-prod.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: false

permissions:
  id-token: write # required to use OIDC authentication
  contents: read # required to checkout the code from the repo

jobs:
  call-dockerized-build:
    uses: MyOrg/shared-actions/.github/workflows/ci-dockerized-app-build.yml@cloud-367/shared-backend-actions
    name: Call Dockerized Build
    with:
      environment: prod
      region: eu-west-1
      namespace: org
      service_name: fulfillment
      app_dockerfile: docker/prod.app.dockerfile
      pre_release: false
      dry_run: false
    secrets:
      aws_role_to_assume: ${{ secrets.AWS_PROD_ROLE_TO_ASSUME_ARN }}
      cert_file: ${{ secrets.PROD_CERT_FILE }}
      dhparam_file: ${{ secrets.PROD_DHPARAM_FILE }}
      key_file: ${{ secrets.PROD_KEY_FILE }}
      gh_packages_user: ${{ secrets.GH_PACKAGES_USER }}
      gh_packages_pat: ${{ secrets.GH_PACKAGES_PAT }}
      application_id: ${{ secrets.APPLICATION_ID }}
      application_private_key: ${{ secrets.APPLICATION_PRIVATE_KEY }}

  call-ecs-deploy:
    uses: MyOrg/shared-actions/.github/workflows/cd-ecs.yml@cloud-367/shared-backend-actions
    needs: call-dockerized-build
    name: Call ECS Deploy
    with:
      environment: prod
      region: eu-west-1
      namespace: org
      service_name: fulfillment
      tag: ${{ needs.call-dockerized-build.outputs.tag }}
    secrets:
      aws_role_to_assume: ${{ secrets.AWS_PROD_ROLE_TO_ASSUME_ARN }}

  call-post-deployment-status-to-slack:
    uses: MyOrg/shared-actions/.github/workflows/controller-post-ecs-deployment-info-to-slack.yml@cloud-367/shared-backend-actions
    needs: call-ecs-deploy
    name: Call Post Deployment Status to Slack
    with:
      environment: prod
      region: eu-west-1
      namespace: org
      service_name: fulfillment
      slack_channel: "#dev-team"
    secrets: inherit

Input option for `post_completing`

Details

Anyone using reusable workflows is almost always going to have multiple jobs, the first with the github/branch-deploy action using skip_completing: true, and the reusable workflow(s) as the rest.

I have multiple repos using branch-deploy and fear it will become a bit of a hassle managing updating the post-deploy job steps (as shown in a few examples using the skip_completing feature), especially as more features start coming out for the branch-deploy action.

Request

Similar to how the skip_completing input will skip select steps towards the end of the job, could there be a post_completing input that skips select steps at the beginning and runs the final update logic?

This way I know my first and last jobs will work as-expected and don't have to approve and maintain multiple 3rd party actions or custom actions/github-script action scripts

Hubot Style Deploy Locking

Hubot Style Deploy Locking 🔒

Wait, what is hubot? - Hubot is GitHub's chatop friend. It had .deploy functionality that is extremely similar to this Action.

This issue tracks work to implement @hubot style deploy locking.

Currently, if you run a .deploy command, it creates a non-sticky lock that is released as soon as the deployment finishes. This is fine for smaller projects, but if you have dozens or even hundreds of PRs open at the same time (from different people) there is a good chance when your deploy finishes, someone else will run .deploy and wipe out your changes.

In Hubot land, when someone runs .deploy it creates a lock that persists until you either merge your pull request with the related lock, or someone (perhaps you) removes the lock manually with .unlock.

The new default behavior of this Action will be to use Hubot style locking out of the box. If you want to disable this feature and use the "classic locking" that is the default today (as of this writing), users will have to sent an input option to do so. Due to this, this change will be a new major release with breaking changes.

This new behavior will not be enabled out of the box and instead you will have to enable it in your Actions configuration with sticky_locks: "true". The reasoning for this is that users should configure the "unlock on merge" mode workflow to take full advantage of automatically releasing locks on PR merge. Since not every one will use this, and since it requires an additional setup step (even though its easy), this option will not be enabled by default. Instead, it should be treated as a custom setup option for advanced users to improve their deployments further.

commitStatus: null

Please note, this is not an issue that I opened, this issue is one that I copied over from a GitHub discussion by @JoaoMJoia

Hello guys,
I'm using your job in my workflow.
After I created a PR and all the CI checks passed and I got an approval I tried to run the deploy command but I kept receiving this message

`### ⚠️ Cannot proceed with deployment

  • reviewDecision: APPROVED
  • commitStatus: null

This is usually caused by missing PR approvals or CI checks failing`

I look at the branch-deploy job and I found this message on the setup

`environment: ./terraform/test/elastic/
.deploy test command used on current branch - setting ref to PD-12605
Could not retrieve PR commit status: TypeError: Cannot read properties of null (reading 'state') - Handled: OK
Skipping commit status check and proceeding...
Error: ### ⚠️ Cannot proceed with deployment

  • reviewDecision: APPROVED
  • commitStatus: null

This is usually caused by missing PR approvals or CI checks failing`

May you guys have any idea why this happened ?

My job config

  • name: Setup branch-deploy
    id: branch-deploy
    uses: github/[email protected]
    with:
    trigger: ".deploy ${{ env.TF_ENVIRONMENT_FOLDER }}"
    noop_trigger: "plan"
    environment: ${{ matrix.directory }}
    stable_branch: "main"

Originally posted by @JoaoMJoia in https://github.com/github/branch-deploy/discussions/109

Add an option to only wait for specific CI checks

Hi @GrantBirki 👋 I've currently encountered a scenario where we have a few CI tasks running in our PRs that shouldn't really block our deploys from going forward.

I've noticed by reading the docs that there doesn't seem to be a way of allow-listing only a number of CI checks or even just flat-out not waiting for CI to have finished run before we can go ahead with deploys.

I wonder if that is something there'd be appetite in adding to branch-deploy? 😊

Massive thanks for working on this!

`.lock` producing a weird behaviour after `4.0.0`

👋 I've recently updated our workflow to 4.0.0 and noticed that whenever I issued a .lock/.unlock I would get a repeated set of messages as the image below shows.

Screenshot 2023-02-09 at 11 41 14

Upon further investigation I was able to track down the following error from the logs of the branch-deploy action run:

Error: HttpError: Invalid request.

"sha" wasn't supplied.
    at /home/runner/work/_actions/github/branch-deploy/0b617a0ced1[42](https://github.com/npm/breach-api/actions/runs/4133871384/jobs/7144298067#step:2:43)f5f2b27302d61557637ba633dcc/webpack:/branch-deploy-action/node_modules/@octokit/request/dist-node/index.js:86:1
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at createLock (/home/runner/work/_actions/github/branch-deploy/0b617a0ced142f5f2b27302d61557637ba633dcc/webpack:/branch-deploy-action/src/functions/lock.js:37:1)
    at lock (/home/runner/work/_actions/github/branch-deploy/0b617a0ced142f5f2b27302d61557637ba633dcc/webpack:/branch-deploy-action/src/functions/lock.js:269:1)
    at run (/home/runner/work/_actions/github/branch-deploy/0b617a0ced142f5f2b27302d61557637ba633dcc/webpack:/branch-deploy-action/src/main.js:229:1)
Error: Invalid request.

"sha" wasn't supplied.

If we look closer into the line that this error is reporting, it seems to suggest that this has something to do with how we are using GitHub's API.

Looking at the documentation I see the following

Required if you are updating a file. The blob SHA of the file being replaced.

Which hints at us potentially attempting to update the lock.json file using GitHub's API perhaps? 🤔

Use getBooleanInput

Use core.getBooleanInput()

This issue tracks work to convert all "true" / "false" string inputs to actual Boolean inputs. There is an function in the Actions core library (as documented here) that will enable this.

This change will absolutely result in a new major semantic release as all users will need to update their Actions inputs where the Booleans are set as strings.

Edit: No actual changes we have to be made by users. The inputs are still "Strings" representing "Booleans" but this method just converts them to Booleans internally so I don't have to.

As seen in the source code for this method, it is casting "Strings" into "Booleans". For example and input of allow_forks: "true" would be processed as a true value in the JS Action

Support deploying a specific SHA or branch

Hello 👋

As part of being able to quickly revert a change to a specific point in time we were wondering if it'd be possible for the branch-deploy action to support deploying a specific SHA or branch-name to a given environment.

Something like .deploy SHA to production or .deploy <my-fav-branch> to production would be what I had in mind 😊

Thanks!

`merge_deploy_mode = true` don't update the current branch deployed

Details

Hi!

Every time a Pull Requests is merged, I'm deploying the stable branch to my development environment.

To do that, I'm using the property merge_deploy_mode = true and it works pretty well. However, it doesn't update the current branch deployed.

If I have an opened PR, it still shows as "deployed" even when it's not:

Screenshot 2023-09-04 at 13 17 33

Is there any way to fix that?

Ability to disable "naked" `.deploy`

Describe the Issue

At the moment, there's no way of actually disabling the ability to run a naked .deploy and enforcing that the user must specify the environment they are deploying to (aka .deploy to foo)

It's not particularily high priority, but it would be nice to have to improve UX. Thank you for your work on this action.

Action Configuration

No response

Relevant Actions Log Output

No response

Extra Information

No response

Why do pull requests need to be subset of push?

Details

In https://github.com/github/branch-deploy/blob/main/.github/workflows/codeql-analysis.yml#L8, the code with comments is:

push:
    branches: [ main ]
  # Disable on PR for now to speed up testing
  # pull_request:
  #   # The branches below must be a subset of the branches above
  #   branches: [ main ]

Why do the pull requests branches have to be a subset of push branches? From testing, it appears that they don't need to be. Moreover, it appears that the any workflow (including CodeQL) runs twice if the branch name matches both those in push and pull request.

Secrets design with branch-deploy action

Details

Hi,

The production-secrets vs production environment split makes sense to me, but I am struggling with where to place secrets if I will be using workflows in addition to branch-deploy that depend on environment secrets.

For example, if I have environment-specific secrets for two different environments (dev, prod) and I create development-secrets and production-secrets, I can tell the branch-deploy workflow where to pull secrets from and where to deploy to. If I have a workflow that runs on a schedule and interacts with either of the -secrets environments, then as far as I can tell the deployment will be tracked against one of the -secrets environments, not production or development. Is there a way to avoid this?

I’ve been going through some of the live examples, and found ci.yml in tarkov-data-manager is deploying to the production environment, while branch-deploy.yml is pulling secrets from production-secrets and deploying to production.

How are secrets handled for the ci.yml workflow? Are they somehow pulled from production-secrets, or are they stored instead as repository secrets?

If they are stored as repository secrets, then what is the purpose of theproduction-secrets environment in the tarkov-data-manager repo?

Removing non-sticky lock when retrying a failed job in multi-job workflows fails

Describe the Issue

In a workflow configured to use this action in a multi-job configuration, if the deployment workflow originally fails and is re-tried using "Re-run jobs > Re-run failed jobs", the "Remove a non-sticky lock" step of the "result" job will always error out with

Run gh api \
  gh api \
    --method DELETE \
    'repos/{owner}/{repo}/git/refs/heads/staging-branch-deploy-lock'
  shell: /usr/bin/bash -e {0}
  env:
    GH_REPO: bkonicek-calm/branch-deploy-test
    GH_TOKEN: ***
  
gh: Reference does not exist (HTTP 4[2](https://github.com/bkonicek-calm/branch-deploy-test/actions/runs/6591572276/job/17910470241#step:5:2)2)
{"message":"Reference does not exist","documentation_url":"https://docs.github.com/rest/git/refs#delete-a-reference"}
Error: Process completed with exit code 1.

We could always trigger a new deployment, but in more complicated workflows that can cost a lot of time. It would be nice if we could just retry the failing jobs when possible (e.g. a missing config value caused the original failure)

Action Configuration

https://github.com/bkonicek-calm/branch-deploy-test/blob/main/.github/workflows/pr_deployment.yml

Relevant Actions Log Output

https://pipelinesghubeus9.actions.githubusercontent.com/Xmv5KJtKvOGHIycin2JVVwumt6WTcDqR22VW4O22M8m91PSios/_apis/pipelines/1/runs/6/signedlogcontent/6?urlExpires=2023-10-20T18%3A59%3A50.1307385Z&urlSigningMethod=HMACV1&urlSignature=ROHcFGJTsdlyr%2BM8v27rZYuI5ZsoRN%2FZVyT2w0dNPsY%3D

Extra Information

Multiple job documentation: https://github.com/github/branch-deploy/blob/main/docs/examples.md#multiple-jobs

Example of a retried action: https://github.com/bkonicek-calm/branch-deploy-test/actions/runs/6591572276/attempts/2

  • The first attempt, the "test" job failed, and the "result" job correctly succeeded and commented in the PR
  • The 2nd attempt after retrying the failed jobs, it failed on the "remove a non-sticky lock" step.

Allow to deploy 'draft' PRs to some environments

Details

I am wondering. Would it be a good idea to have a list of environments that we can deploy to even if PR is in a draft state?

In "my" organization, people can deploy to some stages before the review. Marking PR as "ready" triggers review requests, and it may be unwanted in most cases.

Identical Merge Commit Check - Issues

Identical Merge Commit Check - Issues

I have noticed that if the last "commit" on a PR is a merge commit from clicking the Update Branch button (on a PR), that when said PR is merged, the commit checks are different and the "merge commit check" fails and a fresh deployment is triggered again.

This is certainly a bug and should be resolved.

Reproduction Steps

  1. Open a PR with a single commit (could be anything)
  2. Push a commit to the $default_branch (main in most cases)
  3. Go back to your PR and click the Update Branch button
  4. Deploy your PR
  5. Merge the PR and witness the repo be deployed again because the commits are "different"

Example

Branch is updated:

Screenshot 2023-08-14 at 5 59 03 PM

Deploy command is issued:

.deploy

PR is merged:

Screenshot 2023-08-14 at 5 57 31 PM

Merge Commit Check on main runs:

latest commit on main excluding the merge commit: d9bd...
latest deployment sha: 13d5...
latest deployment is not identical to the latest commit on the default branch

Inspecting the merge commit on main from where the PR was merged:

Screenshot 2023-08-14 at 6 01 30 PM

^ the final screenshot seems to point to the issue. There are two parents leading to the final commit on main being brand new. The first one being where we hit the Update Branch button on our pull request (resulting in 13d5...) and the other one being the latest commit prior to this PR that was merged into main

Either way, the resulting commit on main is completely different from the commit of the latest PR that was deployed so this is a bug that needs to be resolved. I volunteer myself lol

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.