Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,10 @@ You can pass environment variables; the easiest way to do it is via a `.env` fil
```
SETTINGS_FILE_PATH=settings.yml
```
1. Configure the git ref that scheduled and full syncs read the configs from using `CONFIG_REF` (default is the default branch of the admin repo). Webhook-triggered syncs are not affected. For e.g.
Comment thread
tdabasinskas marked this conversation as resolved.
Outdated
```
CONFIG_REF=my-config-branch
```
1. Configure the deployment settings file path using `DEPLOYMENT_CONFIG_FILE` (default is `deployment-settings.yml`). For e.g.
```
DEPLOYMENT_CONFIG_FILE=deployment-settings.yml
Expand Down
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
log: robot.log,
repo: () => { return { repo: env.ADMIN_REPO, owner: installation.account.login } }
}
return syncAllSettings(nop, context)
// CONFIG_REF lets scheduled/CLI syncs read the config from a non-default
// ref of the admin repo (e.g. to test config changes from a branch).
return syncAllSettings(nop, context, context.repo(), env.CONFIG_REF)
}
return null
}
Expand Down
3 changes: 2 additions & 1 deletion lib/env.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
module.exports = {
ADMIN_REPO: process.env.ADMIN_REPO || 'admin',
CONFIG_PATH: process.env.CONFIG_PATH || '.github',
CONFIG_REF: process.env.CONFIG_REF,
SETTINGS_FILE_PATH: process.env.SETTINGS_FILE_PATH || 'settings.yml',
DEPLOYMENT_CONFIG_FILE_PATH: process.env.DEPLOYMENT_CONFIG_FILE || 'deployment-settings.yml',
CREATE_PR_COMMENT: process.env.CREATE_PR_COMMENT || 'true',
CREATE_ERROR_ISSUE: process.env.CREATE_ERROR_ISSUE || 'true',
BLOCK_REPO_RENAME_BY_HUMAN: process.env.BLOCK_REPO_RENAME_BY_HUMAN || 'false',
FULL_SYNC_NOP: process.env.FULL_SYNC_NOP === 'true',
GHE_HOST: process.env.GHE_HOST,
GHE_PROTOCOL: process.env.GHE_PROTOCOL,
GHE_PROTOCOL: process.env.GHE_PROTOCOL
}
83 changes: 83 additions & 0 deletions test/unit/index.syncInstallation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint-disable no-undef */

// Tests for the syncInstallation path in index.js, which serves scheduled
// (CRON) and full-sync runs. The app factory takes Settings as an injectable
// parameter, so the sync can be observed without touching the GitHub API.
describe('syncInstallation', () => {
const installation = { id: 123, account: { login: 'test-org' } }
let robot
let settingsMock

function buildRobot () {
const content = Buffer.from('restrictedRepos: []').toString('base64')
const github = {
paginate: jest.fn().mockResolvedValue([installation]),
rest: {
apps: {
listInstallations: { endpoint: { merge: jest.fn().mockReturnValue({}) } },
getAuthenticated: jest.fn().mockResolvedValue({ data: { slug: 'safe-settings' } })
},
repos: {
getContent: jest.fn().mockResolvedValue({ data: { content } })
}
}
}
return {
log: Object.assign(jest.fn(), {
debug: jest.fn(),
trace: jest.fn(),
info: jest.fn(),
error: jest.fn()
}),
auth: jest.fn().mockResolvedValue(github),
on: jest.fn(),
github
}
}

function loadApp () {
let app
jest.isolateModules(() => {
const appFn = require('../../index')
app = appFn(robot, {}, settingsMock)
})
return app
}

beforeEach(() => {
robot = buildRobot()
settingsMock = {
syncAll: jest.fn().mockResolvedValue({}),
handleError: jest.fn().mockResolvedValue({})
}
})

afterEach(() => {
delete process.env.CONFIG_REF
})

describe('when CONFIG_REF is not set', () => {
it('reads the config from the default branch and passes no ref to syncAll', async () => {
const app = loadApp()

await app.syncInstallation()

expect(robot.github.rest.repos.getContent).toHaveBeenCalledWith(expect.objectContaining({ ref: undefined }))
expect(settingsMock.syncAll).toHaveBeenCalledTimes(1)
expect(settingsMock.syncAll.mock.calls[0][4]).toBeUndefined()
})
})

describe('when CONFIG_REF is set', () => {
it('reads the config from that ref and passes it through to syncAll', async () => {
process.env.CONFIG_REF = 'my-config-branch'
const app = loadApp()

await app.syncInstallation()

expect(robot.github.rest.repos.getContent).toHaveBeenCalledWith(expect.objectContaining({ ref: 'my-config-branch' }))
expect(settingsMock.syncAll).toHaveBeenCalledTimes(1)
expect(settingsMock.syncAll.mock.calls[0][4]).toBe('my-config-branch')
})
})
})