feat: sync repository environments#169
Conversation
There was a problem hiding this comment.
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 intorun()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.6 → 2.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
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
4bae816 to
9c123bb
Compare
- 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
ed6a5dd to
d9ab250
Compare
…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
597041f to
58288cc
Compare
There was a problem hiding this comment.
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 intorun(). - 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
- 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
There was a problem hiding this comment.
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
- 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
- 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
…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
- 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
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
…ling - Remove deleteUnmanagedEnvironments from hasSettings gate (requires environments config to be meaningful) - Increase environment listing page size from 30 to 100
- 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
📦 Draft Release CreatedA draft release v2.8.0 has been created for this PR. Next Steps
|
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 configsdelete-unmanaged-environments— Delete environments not in config (default:false)Usage
Simple — just create named environments:
Advanced — YAML file with full config:
Both
environmentsandenvironments-filecan be combined — file entries override inline entries with the same name.Deployment branch policy options
null(or omitted)protected_branches: true, custom_branch_policies: falseprotected_branches: false, custom_branch_policies: truebranch_name_patterns)Custom branch name patterns
When
custom_branch_policies: true, specifybranch_name_patternsto define which branches/tags can deploy. The action syncs patterns via thedeployment-branch-policiesAPI — 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 namesresolveReviewers()convertslogin/slugto numeric IDs via APIsyncDeploymentBranchPolicies()syncs custom branch name patterns (list/create/delete)syncDeploymentProtectionRules()creates/removes custom deployment gatessyncEnvironments()accepts an array of environment objectsPUT/DELETE /repos/{owner}/{repo}/environments/{name}prevent_self_reviewextracted from protection rules)environmentsandenvironments-file(parse failures skip env sync rather than falling back to global)delete-unmanaged-environmentsusescoerceBooleanConfigfor consistent boolean handling