Skip to content

feat: sync repository environments#169

Merged
joshjohanning merged 34 commits into
mainfrom
copilot/sync-repository-environments
Apr 23, 2026
Merged

feat: sync repository environments#169
joshjohanning merged 34 commits into
mainfrom
copilot/sync-repository-environments

Conversation

Copilot AI commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Adds support for syncing GitHub Actions deployment environments across repositories.

New inputs

  • environments — Comma-separated list of environment names to create (simple case)
  • environments-file — Path to a YAML or JSON file with detailed environment configs
  • delete-unmanaged-environments — Delete environments not in config (default: false)

Usage

Simple — just create named environments:

environments: production, staging, development

Advanced — YAML file with full config:

environments-file: './environments.yml'
# environments.yml
environments:
  - name: production
    wait_timer: 10
    prevent_self_review: true
    reviewers:
      - type: User
        login: joshjohanning          # resolved to numeric ID via API
      - type: Team
        slug: platform-team            # resolved to numeric ID via API
    deployment_branch_policy:
      protected_branches: true
      custom_branch_policies: false
    deployment_protection_rules:
      - app: deployment-gate-demo      # resolved to integration_id via API

  - name: staging
    reviewers:
      - type: Team
        slug: dev-team
    deployment_branch_policy:
      protected_branches: false
      custom_branch_policies: true
    branch_name_patterns:
      - main
      - release/*

  - name: development

Both environments and environments-file can be combined — file entries override inline entries with the same name.

Deployment branch policy options

Setting Behavior
null (or omitted) Any branch can deploy
protected_branches: true, custom_branch_policies: false Only protected branches can deploy
protected_branches: false, custom_branch_policies: true Only branches matching custom name patterns can deploy (specify patterns in branch_name_patterns)

Custom branch name patterns

When custom_branch_policies: true, specify branch_name_patterns to define which branches/tags can deploy. The action syncs patterns via the deployment-branch-policies API — creating missing patterns and removing unmanaged ones.

Deployment protection rules

Custom deployment gates (e.g., external approval apps) can be synced via deployment_protection_rules. The action resolves app slugs to integration IDs and creates/removes rules to match the desired state. The app must be installed on the repository.

Implementation

  • parseEnvironmentsConfig() handles both inline names and YAML/JSON file parsing, validates duplicate names
  • resolveReviewers() converts login/slug to numeric IDs via API
  • syncDeploymentBranchPolicies() syncs custom branch name patterns (list/create/delete)
  • syncDeploymentProtectionRules() creates/removes custom deployment gates
  • syncEnvironments() accepts an array of environment objects
  • Creates, updates, or deletes environments via PUT/DELETE /repos/{owner}/{repo}/environments/{name}
  • Normalizes API responses for comparison (prevent_self_review extracted from protection rules)
  • Paginated environment listing
  • Per-repo overrides support both environments and environments-file (parse failures skip env sync rather than falling back to global)
  • delete-unmanaged-environments uses coerceBooleanConfig for consistent boolean handling
  • Protection rule and branch policy subResults are propagated to repo-level results for accurate summaries
  • Version bump to v2.8.0

Copilot AI linked an issue Apr 15, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Add syncing of Actions environments between repositories feat: sync repository environments Apr 15, 2026
Copilot AI requested a review from joshjohanning April 15, 2026 20:41
@joshjohanning joshjohanning marked this pull request as ready for review April 15, 2026 21:23
Copilot AI review requested due to automatic review settings April 15, 2026 21:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new feature to the bulk repo settings sync GitHub Action to manage GitHub Actions deployment environments across repositories via the Environments REST API, including optional deletion of unmanaged environments.

Changes:

  • Implement syncEnvironments() with environment normalization + diffing and wire it into run() execution flow and summary reporting.
  • Add new action inputs (environments-file, delete-unmanaged-environments) and document them (README + samples).
  • Add Jest coverage for the new environment-sync behavior and bump version to 2.3.0.
Show a summary per file
File Description
src/index.js Adds environment normalization/comparison helpers, implements syncEnvironments(), and integrates it into run() with per-repo overrides and summary output.
action.yml Defines the new environments-file and delete-unmanaged-environments inputs.
README.md Documents environment syncing usage, config format, and adds inputs to the inputs table.
__tests__/index.test.js Adds/updates tests for environment normalization and syncing scenarios, plus input parsing expectations.
sample-configuration/settings-config.yml Demonstrates environments-file in rules-based sample configuration.
sample-configuration/repos.yml Demonstrates environments-file in repo-list sample configuration.
sample-configuration/environments.json Adds an example environments JSON configuration file.
package.json Bumps version 2.2.62.3.0.
package-lock.json Updates lockfile version fields to match the bumped package version.
badges/coverage.svg Updates coverage badge to reflect new coverage %.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 2

Comment thread src/index.js Outdated
Comment thread src/index.js Outdated
Copilot AI and others added 4 commits April 15, 2026 16:38
Add new `environments-file` and `delete-unmanaged-environments` inputs
to sync deployment environments (production, staging, etc.) across
multiple repositories via the GitHub API.

- Create, update, and optionally delete environments
- Support wait timers, reviewers, branch policies, self-review prevention
- Dry-run mode shows planned changes without applying them
- Per-repo overrides via repos.yml or rules-based config
- 24 new tests covering all sync scenarios

Agent-Logs-Url: https://github.com/joshjohanning/bulk-github-repo-settings-sync-action/sessions/f2a87b79-f7d1-422d-99fb-83ac60d4a28a

Co-authored-by: joshjohanning <19912012+joshjohanning@users.noreply.github.com>
… and use explicit comparisons

Agent-Logs-Url: https://github.com/joshjohanning/bulk-github-repo-settings-sync-action/sessions/f2a87b79-f7d1-422d-99fb-83ac60d4a28a

Co-authored-by: joshjohanning <19912012+joshjohanning@users.noreply.github.com>
- Extract prevent_self_review from required_reviewers protection rule
- Use normalized desired env for PUT calls (not raw config)
- Always send all fields in buildEnvironmentParams
- Use coerceBooleanConfig for delete-unmanaged-environments override
- Add pagination for environment listing
- Align global getBooleanInput usage
@joshjohanning joshjohanning force-pushed the copilot/sync-repository-environments branch from 4bae816 to 9c123bb Compare April 15, 2026 21:42
- Add 'environments' input for simple comma-separated names
- Change environments-file from JSON-only to YAML/JSON
- Extract parseEnvironmentsConfig for upstream parsing
- syncEnvironments now accepts an array instead of file path
- Per-repo overrides support both inline and file
- Replace JSON sample with YAML sample
- Add parseEnvironmentsConfig tests
@joshjohanning joshjohanning force-pushed the copilot/sync-repository-environments branch from ed6a5dd to d9ab250 Compare April 16, 2026 01:36
…YAML examples

- Resolve reviewer login/slug to numeric IDs via API
- Add syncDeploymentProtectionRules for custom deployment gates
- Support deployment_protection_rules in environments config
- Update sample config with friendly names and protection rules
@joshjohanning joshjohanning force-pushed the copilot/sync-repository-environments branch from 597041f to 58288cc Compare April 16, 2026 01:53
@joshjohanning joshjohanning requested a review from Copilot April 16, 2026 02:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “environments sync” capability to this bulk repository settings GitHub Action, enabling creation/update/deletion of GitHub Actions deployment environments (including reviewers, wait timers, branch policies, and custom deployment protection rules) across many repositories.

Changes:

  • Implement environment parsing/normalization/comparison and a new syncEnvironments() workflow, plus wiring into run().
  • Add new action inputs for environments syncing and update sample configurations/documentation.
  • Add Jest coverage for the new environment helpers and syncing behavior; bump package version.
Show a summary per file
File Description
src/index.js Adds environment sync implementation, new helpers, and integrates it into the main run loop.
action.yml Adds new inputs (environments, environments-file, delete-unmanaged-environments).
__tests__/index.test.js Adds tests for environment normalization/comparison/syncing and updates input mocks.
README.md Documents environment syncing usage and updates the inputs table.
sample-configuration/settings-config.yml Adds an example environments-file usage in rules-based config.
sample-configuration/repos.yml Adds an example environments-file usage in repos config.
sample-configuration/environments.yml Provides a sample environments config file.
package.json Version bump to 2.6.0.
package-lock.json Lockfile version bump to 2.6.0.
badges/coverage.svg Updates coverage badge to new percentage.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 8

Comment thread __tests__/index.test.js
Comment thread README.md Outdated
Comment thread src/index.js Outdated
Comment thread src/index.js
Comment thread src/index.js
Comment thread src/index.js
Comment thread src/index.js Outdated
Comment thread src/index.js
- Empty deployment_protection_rules array now deletes existing gates
- Aggregate protection rule subResults into environment result
- Correct false-positive detection when only rules match
- Always validate environments-file even when inline names set
- Add reviewer identity to resolution error messages
- Add environments input to mock action.yml in tests
- Add environments input to README inputs table
- Remove stray JSDoc block
- Add environments-file to FILE_PATH_CONFIG_KEYS for base-path resolution
- Fix startup log to show for both inline and file inputs
- Fix parseEnvironmentsConfig JSDoc

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class support to sync GitHub Actions deployment environments (create/update/delete + optional deployment protection rules) across many repositories in this Node.js GitHub Action.

Changes:

  • Implement environment parsing/normalization and repository syncing logic (including reviewer resolution and deployment protection rule syncing).
  • Add new Action inputs (environments, environments-file, delete-unmanaged-environments) and wire them into per-repo overrides.
  • Update docs, samples, tests, and bump package version.
Show a summary per file
File Description
src/index.js Adds environment sync implementation, parsing helpers, and integrates environments into run() flow.
action.yml Documents new inputs for environments syncing.
README.md Adds environments feature documentation and updates the inputs table.
__tests__/index.test.js Extends mocks and adds unit tests for new environment helpers/sync behavior.
sample-configuration/repos.yml Adds sample environments-file usage in repo overrides.
sample-configuration/settings-config.yml Adds sample environments-file usage in rules-based config.
sample-configuration/environments.yml Provides an example environments config file.
package.json Version bump to 2.6.0 for the new feature.
package-lock.json Lockfile version bump alignment with package.json.
badges/coverage.svg Updates coverage badge after adding new code/tests.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 8

Comment thread src/index.js
Comment thread src/index.js Outdated
Comment thread __tests__/index.test.js
Comment thread action.yml
Comment thread sample-configuration/repos.yml Outdated
Comment thread sample-configuration/settings-config.yml
Comment thread README.md Outdated
Comment thread src/index.js
- Deduplicate inline environment names
- Add environments to mockActionYmlParsed
- Update action.yml description for environments input
- Fix all .json references to .yml in README and sample config
- Update README with login/slug reviewer docs and deployment_protection_rules schema
- Replace JSON example with YAML in README
- Remove stray JSDoc opener
- Add environments-file to FILE_PATH_CONFIG_KEYS for base-path
…rule syncs

- Add WARNING subResult when branch_name_patterns is invalid type
- Add WARNING subResult and early return when listing existing
  deployment protection rules fails

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 1

Comment thread action.yml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 4

Comment thread src/index.js Outdated
Comment thread src/index.js
Comment thread src/index.js
Comment thread README.md
- Allow empty environments list with delete-unmanaged to delete all
- Skip branch policy/protection rule sync for uncreated envs in dry-run
- Add NOTE about environments-file defaults resetting existing settings
- Clarify inline vs file mode behavior in docs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 4

Comment thread src/index.js
Comment thread src/index.js Outdated
Comment thread src/index.js
Comment thread README.md
…zation, docs

- Validate file entries are objects before accessing .name
- Skip apps API lookup when desiredRules is empty (delete-all case)
- Clarify environments: '' skip behavior in README

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 3

Comment thread src/index.js
Comment thread src/index.js
Comment thread src/index.js
- Skip protection rule deletion when all desired rules failed validation
- Skip branch policy deletion when all desired patterns were invalid
- Include deleteUnmanagedEnvironments in hasSettings gate

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 3

Comment thread src/index.js
Comment thread src/index.js
Comment thread src/index.js Outdated
Cache resolved reviewer IDs (User login → ID, Team slug → ID) in a
Map that persists across the repo loop, avoiding duplicate API calls
when the same reviewers appear in multiple repos' environment configs.

Closes #191
@joshjohanning joshjohanning linked an issue Apr 23, 2026 that may be closed by this pull request
…ling

- Remove deleteUnmanagedEnvironments from hasSettings gate (requires
  environments config to be meaningful)
- Increase environment listing page size from 30 to 100

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 8/10 changed files
  • Comments generated: 2

Comment thread src/index.js
Comment thread src/index.js
- Include owner in team reviewer cache key since team slugs are
  org-scoped (prevents cross-org cache collision)
- Require explicit environments config for delete-unmanaged to
  prevent accidental mass deletion from inherited global empty list
@joshjohanning joshjohanning merged commit 0859638 into main Apr 23, 2026
4 checks passed
@joshjohanning joshjohanning deleted the copilot/sync-repository-environments branch April 23, 2026 03:21
@github-actions

Copy link
Copy Markdown

📦 Draft Release Created

A draft release v2.8.0 has been created for this PR.

🔗 View Draft Release

Next Steps

  • Review the release notes
  • Publish the release to make it permanent

This is an automated reminder from the publish-github-action workflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants