Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,27 @@

# Uncomment this to get GitHub comments for the Pull Request Workflow.
# ENABLE_PR_COMMENT=true

# ADMIN_REPO=safe-settings-config
CONFIG_PATH=.github
SETTINGS_FILE_PATH=settings.yml

# Configuration support for Hub-Sync safe-settings feature
# SAFE_SETTINGS_HUB_REPO=safe-settings-config-master
# SAFE_SETTINGS_HUB_ORG=foo-training
# A subfolder under 'CONFIG_PATH' where the 'organizations/<org>/<repo>' structure is found
# SAFE_SETTINGS_HUB_PATH=safe-settings
# SAFE_SETTINGS_HUB_DIRECT_PUSH=true



# ┌────────────── second (optional)
# │ ┌──────────── minute
# │ │ ┌────────── hour
# │ │ │ ┌──────── day of month
# │ │ │ │ ┌────── month
# │ │ │ │ │ ┌──── day of week
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * *
# CRON=* * * * * # Run every minute
83 changes: 83 additions & 0 deletions docs/hubSyncHandler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Safe Settings Organization Sync & Dashboard

This feature provides a centralized approach to managing the Safe-Settings Admin Repo, allowing Safe-Settings configurations to be sync'd across multiple ORGs.

## Overview

This feature adds a hub‑and‑spoke synchronization capability to Safe Settings.

One central **master admin repository** (the hub) serves as the authoritative source of configuration which is automatically propagated to each organization’s **admin repository** (the spokes).

**Note:** When something changes in the central repo, only those changed files are copied to each affected ORG’s admin repo, so everything stays in sync with little manual work.

## Sync Lifecycle (High Level)

```mermaid
graph TD
A0(PR Closed) --> A1(HUB Admin Repo)
A1(ORG Admin Repo) --> B(ORG Admin Repo)
A1(HUB Admin Repo) --> C(ORG Admin Repo)
A1(HUB Admin Repo) --> D(ORG Admin Repo)
```

## Environment Variables & Inputs

Environment variables specific to the 'Sync-Feature'

| Name | Purpose | Default |
|------|---------|---------|
| `SAFE_SETTINGS_HUB_REPO` | Repo for master safe-settings contents | admin-master |
| `SAFE_SETTINGS_HUB_ORG` | Organization that hold the Repo | admin-master-org |
| `SAFE_SETTINGS_HUB_PATH` | source folder | .github/safe-settings |
| `SAFE_SETTINGS_HUB_DIRECT_PUSH` | Use a PR or direct commit | false |


---
---

## Hub Sync Scenarios

1. Sync the `Hub Admin Repo` changes to a `Safe-Settings Admin Repo` in **the same ORG** as the Hub Admin Repo.

2. Sync the `Hub Admin changes` to a `Safe-Settings Admin Repo` in **a different ORG**.

3. _`'Global'`_ `Hub Admin Repo` updates.
Changes will `applied to all Organization`

---

## Safe-Settings Hub API endpoints

### API Endpoints

The following table summarizes the Safe Settings API endpoints:

| Endpoint | Method | Purpose | Example Usage |
|------------------------------------------|--------|------------------------------------------------------|---------------|
| `/api/safe-settings/installation` | GET | Organization installation, repo, and sync status | Fetch org status |
| `/api/safe-settings/hub/content` | GET | List hub repo files/directories | List hub files |
| `/api/safe-settings/hub/content/*` | GET | Fetch specific file or directory from hub repo | Get file content |
| `/api/safe-settings/hub/import` | POST | Import settings from orgs into the hub | Import org settings |
| `/api/safe-settings/env` | GET | App environment/config variables | Get env vars |

**Examples:**
- Fetch org installation status:
```http
GET /api/safe-settings/installation
```
- Import settings from orgs:
```http
POST /api/safe-settings/hub/import
Body: { "orgs": ["org1", "org2"] }
```
- List hub repo files:
```http
GET /api/safe-settings/hub/content?ref=main&recursive=true
```
- Get environment variables:
```http
GET /api/safe-settings/env
```

---

754 changes: 754 additions & 0 deletions hubSyncHandler.log

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@ const Glob = require('./lib/glob')
const ConfigManager = require('./lib/configManager')
const NopCommand = require('./lib/nopcommand')
const env = require('./lib/env')
const { setupRoutes } = require('./lib/routes')
const { initCache } = require('./lib/installationCache')
const { hubSyncHandler } = require('./lib/hubSyncHandler')

let deploymentConfig

module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) => {
let appSlug = 'safe-settings'

// Initialize all routes (static UI + API) via centralized module
setupRoutes(robot, getRouter)

// Initialize installation cache (env-controlled prefetch)
initCache(robot)

async function syncAllSettings (nop, context, repo = context.repo(), ref) {
try {
deploymentConfig = await loadYamlFileSystem()
Expand Down Expand Up @@ -521,6 +531,19 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
return createCheckRun(context, pull_request, payload.pull_request.head.sha, payload.pull_request.head.ref)
})

/**
* @description Handle pull_request.closed events to support hub synchronization
* @param {Object} context - The context object provided by Probot
*/
robot.on('pull_request.closed', async context => {
try {
await hubSyncHandler(robot, context)
} catch (err) {
robot.log.error(`pull_request.closed handler failed: ${err && err.message ? err.message : err}`)
}
return null
})

robot.on(['check_suite.rerequested'], async context => {
robot.log.debug('Check suite was rerequested!')
return createCheckRun(context)
Expand Down
6 changes: 6 additions & 0 deletions lib/env.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
module.exports = {
ADMIN_REPO: process.env.ADMIN_REPO || 'admin',
SAFE_SETTINGS_HUB_REPO: process.env.SAFE_SETTINGS_HUB_REPO || 'admin-master',
SAFE_SETTINGS_HUB_ORG: process.env.SAFE_SETTINGS_HUB_ORG || 'admin-master-org',
SAFE_SETTINGS_HUB_DIRECT_PUSH: process.env.SAFE_SETTINGS_HUB_DIRECT_PUSH || 'false',
SAFE_SETTINGS_HUB_PATH: process.env.SAFE_SETTINGS_HUB_PATH || '.github/safe-settings',
APP_ID: process.env.APP_ID || null,
PRIVATE_KEY_PATH: process.env.PRIVATE_KEY_PATH || 'private-key.pem',
CONFIG_PATH: process.env.CONFIG_PATH || '.github',
SETTINGS_FILE_PATH: process.env.SETTINGS_FILE_PATH || 'settings.yml',
DEPLOYMENT_CONFIG_FILE_PATH: process.env.DEPLOYMENT_CONFIG_FILE || 'deployment-settings.yml',
Expand Down
Loading