VCS Guardrails
Enforce version control security standards including branch protection rules, required approvals, status checks, and merge strategies. Prevent unauthorized changes to critical branches.
vcs to your lunar-config.yml:uses: github://earthly/lunar-lib/policies/vcs@v1.0.0
Included Guardrails
This policy includes 14 guardrails that enforce standards for your repository and ownership.
branch-protection-enabled
Requires branch protection rules to be enabled on the default branch. Branch protection is the foundation for all other VCS security controls.
require-pull-request
Requires all changes to go through pull requests before merging. Prevents direct pushes to protected branches without review.
minimum-approvals
Enforces a minimum number of approving reviews before merge (default 1). Configurable via the min_approvals input for stricter requirements.
require-codeowner-review
Requires approval from designated code owners defined in CODEOWNERS file. Ensures domain experts review changes to critical paths.
dismiss-stale-reviews
Automatically dismisses approvals when new commits are pushed to a PR. Prevents merging outdated approvals after significant changes.
require-status-checks
Requires CI status checks to pass before merging pull requests. Prevents merging code that fails tests or linting.
require-branches-up-to-date
Requires PR branches to be up-to-date with the base branch before merging. Prevents merging stale branches that may have integration issues.
disallow-force-push
Prohibits force pushes to protected branches to preserve commit history. Force pushes can destroy audit trails and cause data loss.
disallow-branch-deletion
Prevents deletion of protected branches (typically main/master). Protects against accidental or malicious branch removal.
require-linear-history
Enforces linear commit history by requiring squash or rebase merges. Makes git history cleaner and easier to bisect for debugging.
require-signed-commits
Requires all commits to be GPG or SSH signed for authenticity verification. Proves commits were made by the claimed author.
require-private
Ensures repository visibility is set to private, not public. Prevents accidental exposure of proprietary code.
require-default-branch
Validates the default branch name matches the required name (default "main"). Helps standardize branch naming across repositories.
allowed-merge-strategies
Restricts merge strategies to an allowed list (merge, squash, rebase). Enforces consistent merge practices across the organization.
How Guardrails Fit into Lunar
Lunar guardrails define your engineering standards as code. They evaluate data collected by integrations and produce pass/fail checks with actionable feedback.
Policies support gradual enforcement—from silent scoring to blocking PRs or deployments—letting you roll out standards at your own pace without disrupting existing workflows.
Learn How Lunar Works →Required Integrations
This policy evaluates data gathered by one or more of the following integration(s).
Make sure to enable them in your lunar-config.yml.
Configuration
Configure this policy in your lunar-config.yml.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
min_approvals
|
Optional |
1
|
Minimum number of required approvals (integer, or omit to skip check) |
required_default_branch
|
Optional |
main
|
Required default branch name for the require-default-branch policy. Defaults to 'main' |
allowed_merge_strategies
|
Required | — | Comma-separated list of allowed merge strategies for the allowed-merge-strategies policy (merge, squash, rebase). Only listed strategies will be allowed |
Documentation
View on GitHubVCS Guardrails
Version control system (VCS) best practices and security policies for repositories
Overview
This policy plugin enforces version control system security standards, focusing on branch protection rules that prevent unauthorized or risky changes to critical branches. Branch protection is a fundamental security control that ensures code review, testing, and approval processes are followed before changes reach production. Development teams using GitHub (or similar VCS platforms) should use this policy to enforce consistent protection rules across repositories.
Policies
This plugin provides the following policies (use include to select a subset):
Branch Protection Policies
These policies enforce specific branch protection requirements. Use include to select which policies to enforce.
| Policy | Description |
|---|---|
branch-protection-enabled |
Branch protection must be enabled |
require-pull-request |
Pull requests must be required before merging |
minimum-approvals |
Pull requests must have minimum number of approvals (configurable via min_approvals input) |
require-codeowner-review |
Code owner review must be required |
dismiss-stale-reviews |
Stale reviews must be dismissed on new commits |
require-status-checks |
Status checks must be required to pass |
require-branches-up-to-date |
Branches must be up to date before merging |
disallow-force-push |
Force pushes must be disallowed |
disallow-branch-deletion |
Branch deletions must be disallowed |
require-linear-history |
Linear history must be required |
require-signed-commits |
Signed commits must be required |
Repository Settings Policies
| Policy | Description |
|---|---|
require-private |
Repository visibility must be private |
require-default-branch |
Default branch must match required name (configurable via required_default_branch input, defaults to "main") |
allowed-merge-strategies |
Merge strategies must match allowed list (configurable via allowed_merge_strategies input) |
Required Data
This policy reads from the following Component JSON paths:
| Path | Type | Description |
|---|---|---|
.vcs.branch_protection.enabled |
boolean | Whether branch protection is enabled |
.vcs.branch_protection.require_pr |
boolean | Whether pull requests are required |
.vcs.branch_protection.required_approvals |
integer | Number of required approvals |
.vcs.branch_protection.require_codeowner_review |
boolean | Whether code owner review is required |
.vcs.branch_protection.dismiss_stale_reviews |
boolean | Whether stale reviews are dismissed |
.vcs.branch_protection.require_status_checks |
boolean | Whether status checks are required |
.vcs.branch_protection.require_branches_up_to_date |
boolean | Whether branches must be up to date |
.vcs.branch_protection.allow_force_push |
boolean | Whether force pushes are allowed |
.vcs.branch_protection.allow_deletions |
boolean | Whether branch deletions are allowed |
.vcs.branch_protection.require_linear_history |
boolean | Whether linear history is required |
.vcs.branch_protection.require_signed_commits |
boolean | Whether signed commits are required |
.vcs.visibility |
string | Repository visibility |
.vcs.default_branch |
string | Default branch name |
.vcs.merge_strategies.allow_merge_commit |
boolean | Whether merge commits are allowed |
.vcs.merge_strategies.allow_squash_merge |
boolean | Whether squash merges are allowed |
.vcs.merge_strategies.allow_rebase_merge |
boolean | Whether rebase merges are allowed |
Note: This policy requires a VCS collector (such as github) that populates the .vcs data.
Installation
Add to your lunar-config.yml:
policies:
# Run all policies (default - enforces all branch protection and repository settings)
- uses: github://earthly/lunar-lib/policies/vcs@v1.0.0
on: "domain:your-domain" # Or use tags like production, critical
enforcement: report-pr # Options: draft, score, report-pr, block-pr, block-release, block-pr-and-release
with:
min_approvals: 2
allowed_merge_strategies: "squash"
# required_default_branch: "main"
# Use include to run only specific policies
- uses: github://earthly/lunar-lib/policies/vcs@v1.0.0
include:
- branch-protection-enabled
- require-pull-request
- minimum-approvals
- disallow-force-push
- require-signed-commits
- require-private
on: "domain:your-domain"
enforcement: block-pr
with:
min_approvals: 2
# Run only repository settings policies
- uses: github://earthly/lunar-lib/policies/vcs@v1.0.0
include:
- require-private
- require-default-branch
- allowed-merge-strategies
on: "domain:your-domain"
enforcement: report-pr
with:
allowed_merge_strategies: "squash,rebase"
Examples
Passing Example - Production Repository
A production repository with strict security controls:
{
"vcs": {
"provider": "github",
"visibility": "private",
"default_branch": "main",
"branch_protection": {
"enabled": true,
"branch": "main",
"require_pr": true,
"required_approvals": 2,
"require_codeowner_review": true,
"dismiss_stale_reviews": true,
"require_status_checks": true,
"require_branches_up_to_date": true,
"allow_force_push": false,
"allow_deletions": false,
"require_linear_history": false,
"require_signed_commits": true
},
"merge_strategies": {
"allow_merge_commit": false,
"allow_squash_merge": true,
"allow_rebase_merge": false
}
}
}
With policy configuration using include to select desired checks:
include:
- branch-protection-enabled
- require-pull-request
- minimum-approvals
- require-codeowner-review
- dismiss-stale-reviews
- require-status-checks
- require-branches-up-to-date
- disallow-force-push
- disallow-branch-deletion
- require-signed-commits
- require-private
- require-default-branch
- allowed-merge-strategies
with:
min_approvals: 2
allowed_merge_strategies: "squash"
This passes because all security controls match policy requirements.
Failing Example - Branch Protection Not Enabled
{
"vcs": {
"branch_protection": {
"enabled": false,
"branch": "main"
}
}
}
With policy configuration:
include:
- branch-protection-enabled
- minimum-approvals
with:
min_approvals: 1
Failure messages:
branch-protection-enabled:"Branch protection is not enabled on main"minimum-approvals:"Branch protection is not enabled"
Failing Example - Wrong Settings
{
"vcs": {
"visibility": "public",
"default_branch": "master",
"merge_strategies": {
"allow_merge_commit": true,
"allow_squash_merge": true,
"allow_rebase_merge": false
}
}
}
With policy configuration:
include:
- require-private
- require-default-branch
- allowed-merge-strategies
with:
allowed_merge_strategies: "squash"
# required_default_branch defaults to "main"
Failure messages:
"Repository visibility is 'public', but policy requires 'private'""Default branch is 'master', but policy requires 'main'""Merge commits are enabled, but policy does not allow them (should be disabled)"
Remediation
Branch Protection Policies
When branch protection policies fail, configure branch protection rules in your repository settings:
- GitHub: Navigate to your repository → Settings → Branches → Branch protection rules
- Select your default branch (typically
mainormaster) or create a new rule - Enable the required protection settings based on the policy failures:
- Require pull request reviews before merging - Set the number of required approvals
- Require review from Code Owners - Enable if codeowner review is required
- Dismiss stale pull request approvals when new commits are pushed - Enable if required
- Require status checks to pass before merging - Enable and select required checks
- Require branches to be up to date before merging - Enable if required
- Do not allow bypassing the above settings - Disable "Allow force pushes" and "Allow deletions"
- Require linear history - Enable if required by policy
- Require signed commits - Enable if required by policy
- Save the branch protection rule
- Re-run the Lunar collector and policy to verify compliance
Repository Settings Policies
When repository settings policies fail, update repository settings:
- GitHub: Navigate to your repository → Settings
- Update the relevant settings based on the policy failures:
- Repository visibility (General section):
- Change visibility to match policy requirements (Private or Public)
- Note: Changing visibility may have security implications - consult your security team
- Default branch (General section):
- Rename your default branch if required (e.g., from
mastertomain) - GitHub provides a "Rename branch" button in the repository settings
- Update local clones and CI/CD configurations after renaming
- Rename your default branch if required (e.g., from
- Merge button (Pull Requests section):
- Enable only the merge strategies listed in
allowed_merge_strategies - Disable any strategies not in the allowed list
- Example: If policy specifies
"squash,rebase", enable those two and disable merge commits
- Enable only the merge strategies listed in
- Repository visibility (General section):
- Save the changes
- Re-run the Lunar collector and policy to verify compliance
Open Source
This policy is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.
Common Use Cases
Explore how individual guardrails work with specific integrations.
Ready to Automate Your Standards?
See how Lunar can turn your engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 100+ built-in guardrails.