Hamburger Cross Icon
VCS Guardrails - Lunar Policy for Repository And Ownership

VCS Guardrails

Policy Stable Repository And Ownership

Enforce version control security standards including branch protection rules, required approvals, status checks, and merge strategies. Prevent unauthorized changes to critical branches.

Add 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.

Guardrail

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.

branch protection github security
View Guardrail
Guardrail

require-pull-request

Requires all changes to go through pull requests before merging. Prevents direct pushes to protected branches without review.

pull request code review pr required
View Guardrail
Guardrail

minimum-approvals

Enforces a minimum number of approving reviews before merge (default 1). Configurable via the min_approvals input for stricter requirements.

code review approvals required reviewers
View Guardrail
Guardrail

require-codeowner-review

Requires approval from designated code owners defined in CODEOWNERS file. Ensures domain experts review changes to critical paths.

codeowners code owner review
View Guardrail
Guardrail

dismiss-stale-reviews

Automatically dismisses approvals when new commits are pushed to a PR. Prevents merging outdated approvals after significant changes.

stale reviews review dismissal
View Guardrail
Guardrail

require-status-checks

Requires CI status checks to pass before merging pull requests. Prevents merging code that fails tests or linting.

status checks ci checks required checks
View Guardrail
Guardrail

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.

up to date branch sync
View Guardrail
Guardrail

disallow-force-push

Prohibits force pushes to protected branches to preserve commit history. Force pushes can destroy audit trails and cause data loss.

force push git security
View Guardrail
Guardrail

disallow-branch-deletion

Prevents deletion of protected branches (typically main/master). Protects against accidental or malicious branch removal.

branch deletion protected branches
View Guardrail
Guardrail

require-linear-history

Enforces linear commit history by requiring squash or rebase merges. Makes git history cleaner and easier to bisect for debugging.

linear history git rebase
View Guardrail
Guardrail

require-signed-commits

Requires all commits to be GPG or SSH signed for authenticity verification. Proves commits were made by the claimed author.

signed commits gpg signing commit verification
View Guardrail
Guardrail

require-private

Ensures repository visibility is set to private, not public. Prevents accidental exposure of proprietary code.

private repository visibility
View Guardrail
Guardrail

require-default-branch

Validates the default branch name matches the required name (default "main"). Helps standardize branch naming across repositories.

default branch main branch
View Guardrail
Guardrail

allowed-merge-strategies

Restricts merge strategies to an allowed list (merge, squash, rebase). Enforces consistent merge practices across the organization.

merge strategies squash merge rebase merge
View Guardrail

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
1
Integrations Gather Data
Collectors extract metadata from code, CI pipelines, tool outputs, and scans
2
{ } Centralized as JSON
All data merged into each component's unified metadata document
3
Guardrails Enforce Standards This Policy
Real-time feedback in PRs and AI workflows

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 GitHub

VCS 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:

  1. GitHub: Navigate to your repository → Settings → Branches → Branch protection rules
  2. Select your default branch (typically main or master) or create a new rule
  3. 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
  4. Save the branch protection rule
  5. Re-run the Lunar collector and policy to verify compliance

Repository Settings Policies

When repository settings policies fail, update repository settings:

  1. GitHub: Navigate to your repository → Settings
  2. 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 master to main)
      • GitHub provides a "Rename branch" button in the repository settings
      • Update local clones and CI/CD configurations after renaming
    • 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
  3. Save the changes
  4. 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.

View Repository

Common Use Cases

Explore how individual guardrails work with specific integrations.

+
Branch Protection Enabled + GitHub Collector Requires branch protection rules to be enabled on the default branch. Branch...
+
Require Pull Request + GitHub Collector Requires all changes to go through pull requests before merging. Prevents direct...
+
Minimum Approvals + GitHub Collector Enforces a minimum number of approving reviews before merge (default...
+
Require Codeowner Review + GitHub Collector Requires approval from designated code owners defined in CODEOWNERS...
+
Dismiss Stale Reviews + GitHub Collector Automatically dismisses approvals when new commits are pushed to a PR. Prevents...
+
Require Status Checks + GitHub Collector Requires CI status checks to pass before merging pull requests. Prevents merging...
+
Require Branches Up To Date + GitHub Collector Requires PR branches to be up-to-date with the base branch before...
+
Disallow Force Push + GitHub Collector Prohibits force pushes to protected branches to preserve commit history. Force...
+
Disallow Branch Deletion + GitHub Collector Prevents deletion of protected branches (typically main/master). Protects...
+
Require Linear History + GitHub Collector Enforces linear commit history by requiring squash or rebase merges. Makes git...
+
Require Signed Commits + GitHub Collector Requires all commits to be GPG or SSH signed for authenticity...
+
Require Private + GitHub Collector Ensures repository visibility is set to private, not public. Prevents accidental...
+
Require Default Branch + GitHub Collector Validates the default branch name matches the required name (default...
+
Allowed Merge Strategies + GitHub Collector Restricts merge strategies to an allowed list (merge, squash, rebase). Enforces...

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.

Works with any process
check Infrastructure conventions
check Post-mortem action items
check Security & compliance policies
check Testing & quality requirements
Book a Demo
See it work with your own use cases
See How It Works