Skip to content
Open
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
7 changes: 6 additions & 1 deletion lib/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,14 +370,19 @@ ${this.results.reduce((x, y) => {
const RepoPlugin = Settings.PLUGINS.repository

const archivePlugin = new Archive(this.nop, this.github, repo, repoConfig, this.log)
const { shouldArchive, shouldUnarchive } = await archivePlugin.getState()
const { isArchived, shouldArchive, shouldUnarchive } = await archivePlugin.getState()

if (shouldUnarchive) {
this.log.debug(`Unarchiving repo ${repo.repo}`)
const unArchiveResults = await archivePlugin.sync()
this.appendToResults(unArchiveResults)
}

if (isArchived && !shouldUnarchive) {
this.log.debug(`Skipping repo/child plugin updates for archived repo ${repo.repo}`)
return
}

const repoResults = await new RepoPlugin(this.nop, this.github, repo, repoConfig, this.installation_id, this.log, this.errors).sync()
this.appendToResults(repoResults)

Expand Down
21 changes: 21 additions & 0 deletions schema/dereferenced/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@
}
}
},
"code_security": {
"type": "object",
"description": "Use the `status` property to enable or disable GitHub Code Security for this repository.",
"description": "Use the `status` property to enable or disable GitHub Advanced Security for this repository.\nFor more information, see \"[About GitHub Advanced\nSecurity](/github/getting-started-with-github/learning-about-github/about-github-advanced-security).\"\n\nFor standalone Code Scanning or Secret Protection products, this parameter cannot be used.",
"properties": {
"status": {
"type": "string",
"description": "Can be `enabled` or `disabled`."
}
Comment on lines +58 to +61
}
},
"code_security": {
"type": "object",
"description": "Use the `status` property to enable or disable GitHub Code Security for this repository.",
Comment on lines +53 to 66
Expand Down Expand Up @@ -90,6 +101,16 @@
}
}
},
"secret_scanning_ai_detection": {
"type": "object",
"description": "Use the `status` property to enable or disable secret scanning AI detection for this repository. For more information, see \"[Responsible detection of generic secrets with AI](https://docs.github.com/code-security/secret-scanning/using-advanced-secret-scanning-and-push-protection-features/generic-secret-detection/responsible-ai-generic-secrets).\"",
"properties": {
"status": {
"type": "string",
"description": "Can be `enabled` or `disabled`."
}
}
},
"secret_scanning_non_provider_patterns": {
"type": "object",
"description": "Use the `status` property to enable or disable secret scanning non-provider patterns for this repository. For more information, see \"[Supported secret scanning patterns](/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets).\"",
Expand Down
50 changes: 50 additions & 0 deletions test/unit/lib/plugins/archive.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,56 @@ describe('Archive Plugin', () => {
})
})

describe('getState', () => {
it('getState when repo is already archived and desired state is not set returns isArchived true shouldArchive false shouldUnarchive false', async () => {
// Arrange
github.rest.repos.get.mockResolvedValue({ data: { archived: true } })
archive = new Archive(false, github, repo, {}, log)

// Act
const result = await archive.getState()

// Assert
expect(result).toEqual({
isArchived: true,
shouldArchive: false,
shouldUnarchive: false
})
})

it('getState when repo is not archived and desired state is not set returns isArchived false shouldArchive false shouldUnarchive false', async () => {
// Arrange
github.rest.repos.get.mockResolvedValue({ data: { archived: false } })
archive = new Archive(false, github, repo, {}, log)

// Act
const result = await archive.getState()

// Assert
expect(result).toEqual({
isArchived: false,
shouldArchive: false,
shouldUnarchive: false
})
})

it('getState when repo is archived and desired state is false returns isArchived true shouldArchive false shouldUnarchive true', async () => {
// Arrange
github.rest.repos.get.mockResolvedValue({ data: { archived: true } })
archive = new Archive(false, github, repo, { archived: false }, log)

// Act
const result = await archive.getState()

// Assert
expect(result).toEqual({
isArchived: true,
shouldArchive: false,
shouldUnarchive: true
})
})
})

describe('sync', () => {
beforeEach(() => {
archive = new Archive(false, github, repo, settings, log)
Expand Down
87 changes: 87 additions & 0 deletions test/unit/lib/settings.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,91 @@ repository:
);
});
});

describe('updateRepos - archived repo skipping', () => {
const Archive = require('../../../lib/plugins/archive')

let settings
let mockRepoSync
let originalRepoPlugin

beforeEach(() => {
// Preserve the original RepoPlugin so it can be restored after each test
originalRepoPlugin = Settings.PLUGINS.repository

// Replace RepoPlugin with a mock constructor whose sync() we can assert on
mockRepoSync = jest.fn().mockResolvedValue([])
Settings.PLUGINS.repository = jest.fn().mockImplementation(() => ({
sync: mockRepoSync
}))

// Build a Settings instance that will enter the `if (repoConfig)` branch:
// config.repository must be defined so repoConfig is truthy
settings = new Settings(
false,
stubContext,
{ owner: 'test-org', repo: 'test-repo' },
{ repository: { name: 'test-repo' } },
'main'
)

// Pre-set subOrgConfigs so updateRepos() does not call the async getSubOrgConfigs()
settings.subOrgConfigs = {}

// Pre-set repoConfigs so getRepoOverrideConfig() does not throw on undefined
settings.repoConfigs = {}
})

afterEach(() => {
// Restore the real RepoPlugin and all prototype spies
Settings.PLUGINS.repository = originalRepoPlugin
jest.restoreAllMocks()
})

it('updateRepos when repo is already archived and not being unarchived does not call RepoPlugin sync', async () => {
// Arrange
jest.spyOn(Archive.prototype, 'getState').mockResolvedValue({
isArchived: true,
shouldArchive: false,
shouldUnarchive: false
})

// Act
await settings.updateRepos({ owner: 'test-org', repo: 'test-repo' })

// Assert
expect(mockRepoSync).not.toHaveBeenCalled()
})

it('updateRepos when repo is archived but is being unarchived calls RepoPlugin sync', async () => {
// Arrange
jest.spyOn(Archive.prototype, 'getState').mockResolvedValue({
isArchived: true,
shouldArchive: false,
shouldUnarchive: true
})
jest.spyOn(Archive.prototype, 'sync').mockResolvedValue([])

// Act
await settings.updateRepos({ owner: 'test-org', repo: 'test-repo' })

// Assert
expect(mockRepoSync).toHaveBeenCalledTimes(1)
})

it('updateRepos when repo is not archived calls RepoPlugin sync', async () => {
// Arrange
jest.spyOn(Archive.prototype, 'getState').mockResolvedValue({
isArchived: false,
shouldArchive: false,
shouldUnarchive: false
})

// Act
await settings.updateRepos({ owner: 'test-org', repo: 'test-repo' })

// Assert
expect(mockRepoSync).toHaveBeenCalledTimes(1)
})
}) // updateRepos - archived repo skipping
}) // Settings Tests