Implementing Granular Approval Workflows in GitHub Actions

GitHub Actions has evolved from a simple continuous integration tool into a sophisticated orchestration engine capable of handling complex deployment pipelines. A critical requirement in modern DevOps is the ability to enforce manual approval gates for sensitive operations, such as production deployments or infrastructure changes. Historically, GitHub provided only global branch protection rules for pull requests, lacking the granularity needed for monorepos or specific job-level controls within a workflow. This limitation forced teams to either enforce excessive approval requirements across entire repositories or rely on external tooling. The current landscape offers three distinct approaches to solving this problem: native environment protection rules, third-party actions for file-specific pull request approvals, and custom workflow steps that integrate with external notification systems like Google Chat. Understanding the mechanics, limitations, and configuration nuances of each method is essential for building secure and efficient CI/CD pipelines.

Native Environment Protection Rules

The most supported and native method for implementing manual approval gates in GitHub Actions is through the use of environment protection rules. This feature allows repository administrators to pause specific jobs within a workflow until a designated user or team provides approval. This approach is particularly effective for deployment jobs, where human oversight is required before code is pushed to a production environment.

Environment protection rules are the only native way to require manual approval for part of a GitHub Actions workflow. When a job is attached to an environment with required reviewers, GitHub will pause that job's execution. The job remains in a pending state until an approved user or team reviews and approves the request. This mechanism provides a clean, user-friendly interface within the GitHub UI, where reviewers can approve the workflow step and add comments.

It is important to understand the scope and limitations of this feature. Environment protection rules operate at the job level, but they are tied to the concept of environments, not standalone jobs. There is no separate job-level approval feature that exists outside of the environment construct. Other native features, such as workflow_dispatch or branch protection, do not provide this functionality. workflow_dispatch only controls the starting of the workflow, not pausing it mid-run. Branch protection rules apply to the merge of a pull request, not to the execution of individual jobs within a pipeline.

The recommended and supported pattern is to place sensitive jobs, such as deployments, behind a protected environment. Administrators must configure required reviewers on that environment, keeping in mind plan limits for the number of environments and reviewers. There is no official alternative or roadmap item for standalone job approvals without environments. Any attempt to bypass environments for approval gates would require a workaround rather than using a supported feature.

File-Specific Pull Request Approvals via Third-Party Actions

While environment protection rules handle job-level approvals, a different challenge arises in monorepo structures. GitHub allows setting the required number of approvals on a global level for branch protection. However, in a monorepo, teams often have sensitive projects that require more than one reviewer, while other parts of the repository may not need such strict oversight. Forcing multiple approvals on all parts of the monorepo can slow down development velocity for non-critical changes.

To address this, third-party actions such as "Configurable Required Approvals" allow teams to define groups of files using glob patterns and specify the minimum number of approvals required for each group. This action checks if specific files in a pull request have the required number of approvals. It enables granular control, ensuring that changes to critical backend services require more scrutiny than changes to frontend documentation, for example.

The configuration for this action involves defining requirements in the workflow file. The action allows you to set paths and approval requirements based on file change globs. Users can define multiple patterns and assign a specific number of required approvals to each. For instance, a workflow can be configured to require two approvals for changes to frontend packages and three approvals for changes to backend or shared libraries.

A key design consideration of this action is its behavior regarding status checks. To avoid pull requests showing a red error icon when the required approvals are not met, the action is designed to always succeed. If the approval requirements are met, the action adds an additional check to the pull request with the name "Required number of approvals met." If the required approvals are not met, this additional status check is not added, and the PR remains in a pending state.

This design allows users to set this additional check ("Required number of approvals met") as a required check in the branch protection settings. This ensures that the branch protection rule blocks the merge until the specific file-based approval requirements are satisfied. However, there are technical caveats. When multiple workflows run in parallel, the custom check may be randomly attached to one of the workflows instead of the originating workflow. To resolve this issue and ensure the check is attached to the correct workflow, users must use a GitHub App token instead of the default GITHUB_TOKEN.

The action also handles cases where none of the files in the specified patterns are touched in the pull request. In such cases, the action sets the custom check, effectively bypassing the approval requirement for unrelated changes. If files in the specified patterns are touched, the action verifies that the pull request has the required number of approvals. This action is not certified by GitHub and is provided by a third-party, governed by separate terms of service and privacy policies.

Configuring Specific User Groups for Approvals

Another approach to managing approvals involves specifying exactly which users must approve a pull request. Third-party actions like "Require User Approval" enable this by automatically checking if certain required users have approved a pull request. This method moves beyond counting approvals to verifying identity, ensuring that specific stakeholders sign off on changes.

Implementing this requires preparing two YAML files: a reviewers configuration file and a workflow configuration file. The reviewers configuration file defines groups of users and the number of approvals required from each group. The default configuration file location is .github/require_reviewers.yml, but this can be overridden in the workflow configuration file.

The configuration format allows for flexible group definitions. A group can be defined with a list of members and a required count. For example, a group named review-group-all might require all four members of a specific team to approve a pull request. Another group, review-group-some, might require any two users from a larger pool to approve. A third group, review-group-any, might require only one user from a designated list to approve.

An important constraint of this configuration is that the action does not currently validate whether the number of required approvals for a group is less than or equal to the number of members specified. Users must ensure manually that they do not set a requirement for more users than are present in the group, as this would result in an unfulfillable condition.

The workflow file must be created in the .github/workflows directory. It references the configuration file and triggers the action on pull request events. Similar to the configurable required approvals action, this tool is not certified by GitHub and is provided by a third-party. It provides a robust way to enforce specific personnel reviews for critical code paths, adding a layer of accountability that generic approval counts do not provide.

Custom Approval Workflows with External Notifications

For teams that require more complex approval logic or integration with external communication tools, custom workflow steps can be implemented. This approach leverages the ability to pause workflows and send notifications to platforms like Google Chat. This method provides a high degree of customization, allowing teams to tailor the approval process to their specific operational needs.

Setting up a custom approval workflow involves creating a workflow that includes steps for notifying reviewers and waiting for approval. One common implementation uses an Azure App Service as a deployment target or as part of the pipeline. The workflow can be configured to send a notification to a Google Chat room when a deployment approval is requested.

The notification step can be implemented using a curl command to send a POST request to the Google Chat API. The message can include a link to the GitHub Actions run, allowing reviewers to click through and approve the workflow step directly from their chat interface. The approval process is managed by GitHub's native environment protection rules, which pause the job until approval is granted.

When the protection rules are hit, the run stops and waits, but the reviewers are notified. The notification occurs via standard GitHub notification means, such as email, as well as the custom Google Chat notification. Once the reviewer approves the workflow step, the job resumes execution. After the deployment is complete, a subsequent step can send another notification to Google Chat to confirm that the deployment and approval request are done.

This approach enhances workflow control by integrating approval gates into familiar communication channels. It simplifies the integration of approval steps into CI/CD pipelines, providing a more responsive and accessible experience for reviewers. The addition of these features to GitHub Actions represents a significant enhancement, empowering users to enhance their continuous integration and delivery practices with greater security and flexibility.

Conclusion

The evolution of approval workflows in GitHub Actions reflects the growing complexity of modern software development. From native environment protection rules to file-specific third-party actions and custom integrations with external notification systems, teams now have a variety of tools to enforce secure and efficient deployment practices. Native environment rules provide a supported, straightforward way to pause jobs for review, while third-party actions offer granular control over pull request approvals based on file patterns or specific user groups. Custom workflows further extend these capabilities by integrating with communication platforms like Google Chat, ensuring that reviewers are promptly notified and can act quickly.

Understanding the nuances of each approach is crucial for implementing effective approval gates. Environment rules are the best fit for job-level approvals, while file-specific actions address the needs of monorepos. Custom workflows offer the highest degree of flexibility for teams with unique operational requirements. By leveraging these tools, organizations can balance security and velocity, ensuring that critical changes are reviewed without slowing down the development process. As GitHub continues to refine its capabilities, these methods will remain foundational to building robust and secure CI/CD pipelines.

Sources

  1. Configurable Required Approvals

  2. Adding Approval Workflow to Your GitHub Action

  3. GitHub Community Discussion: Manual Approval Step

  4. Require User Approval

  5. Required Approvals

Related Posts