diff --git a/lib/plugins/archive.js b/lib/plugins/archive.js new file mode 100644 index 00000000..a481029c --- /dev/null +++ b/lib/plugins/archive.js @@ -0,0 +1,86 @@ +const NopCommand = require('../nopcommand'); + +function returnValue(shouldContinue, nop) { + return { shouldContinue, nopCommands: nop }; +} + +module.exports = class Archive { + constructor(nop, github, repo, settings, log) { + this.github = github; + this.repo = repo; + this.settings = settings; + this.log = log; + this.nop = nop; + } + + // Returns true if plugin application should continue, false otherwise + async sync() { + // Fetch repository details using REST API + const { data: repoDetails } = await this.github.repos.get({ + owner: this.repo.owner, + repo: this.repo.repo + }); + if (typeof this.settings?.archived !== 'undefined') { + this.log.debug(`Checking if ${this.repo.owner}/${this.repo.repo} is archived`); + + this.log.debug(`Repo ${this.repo.owner}/${this.repo.repo} is ${repoDetails.archived ? 'archived' : 'not archived'}`); + + if (repoDetails.archived) { + if (this.settings.archived) { + this.log.debug(`Repo ${this.repo.owner}/${this.repo.repo} already archived, inform other plugins should not run.`); + return returnValue(false); + } + else { + this.log.debug(`Unarchiving ${this.repo.owner}/${this.repo.repo}`); + if (this.nop) { + return returnValue(true, [new NopCommand(this.constructor.name, this.repo, this.github.repos.update.endpoint(this.settings), 'will unarchive')]); + } + else { + // Unarchive the repository using REST API + const updateResponse = await this.github.repos.update({ + owner: this.repo.owner, + repo: this.repo.repo, + archived: false + }); + this.log.debug(`Unarchive result ${JSON.stringify(updateResponse)}`); + + return returnValue(true); + } + } + } + else { + if (this.settings.archived) { + this.log.debug(`Archiving ${this.repo.owner}/${this.repo.repo}`); + if (this.nop) { + return returnValue(false, [new NopCommand(this.constructor.name, this.repo, this.github.repos.update.endpoint(this.settings), 'will archive')]); + } + else { + // Archive the repository using REST API + const updateResponse = await this.github.repos.update({ + owner: this.repo.owner, + repo: this.repo.repo, + archived: true + }); + this.log.debug(`Archive result ${JSON.stringify(updateResponse)}`); + + return returnValue(false); + } + } + else { + this.log.debug(`Repo ${this.repo.owner}/${this.repo.repo} is not archived, ignoring.`); + return returnValue(true); + } + } + } + else { + if (repoDetails.archived) { + this.log.debug(`Repo ${this.repo.owner}/${this.repo.repo} is archived, ignoring.`); + return returnValue(false); + } + else { + this.log.debug(`Repo ${this.repo.owner}/${this.repo.repo} is not archived, proceed as usual.`); + return returnValue(true); + } + } + } +}; diff --git a/lib/settings.js b/lib/settings.js index 961aa4c6..e8573a7b 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -5,6 +5,7 @@ const errorTemplate = require('./error') const Glob = require('./glob') const NopCommand = require('./nopcommand') const MergeDeep = require('./mergeDeep') +const Archive = require('./plugins/archive') const env = require('./env') const CONFIG_PATH = env.CONFIG_PATH const eta = new Eta({ views: path.join(__dirname) }) @@ -318,38 +319,42 @@ ${this.results.reduce((x, y) => { if (overrideRepoConfig) { repoConfig = this.mergeDeep.mergeDeep({}, repoConfig, overrideRepoConfig) } - if (repoConfig) { - try { - this.log.debug(`found a matching repoconfig for this repo ${JSON.stringify(repoConfig)}`) - const childPlugins = this.childPluginsList(repo) - const RepoPlugin = Settings.PLUGINS.repository - return new RepoPlugin(this.nop, this.github, repo, repoConfig, this.installation_id, this.log, this.errors).sync().then(res => { - this.appendToResults(res) - return Promise.all( - childPlugins.map(([Plugin, config]) => { - return new Plugin(this.nop, this.github, repo, config, this.log, this.errors).sync() - })) - }).then(res => { - this.appendToResults(res) - }) - } catch (e) { - if (this.nop) { - const nopcommand = new NopCommand(this.constructor.name, this.repo, null, `${e}`, 'ERROR') - this.log.error(`NOPCOMMAND ${JSON.stringify(nopcommand)}`) - this.appendToResults([nopcommand]) - // throw e - } else { - throw e + const {shouldContinue, nopCommands} = await new Archive(this.nop, this.github, repo, repoConfig, this.log).sync() + if (nopCommands) this.appendToResults(nopCommands) + if (shouldContinue) { + if (repoConfig) { + try { + this.log.debug(`found a matching repoconfig for this repo ${JSON.stringify(repoConfig)}`) + const childPlugins = this.childPluginsList(repo) + const RepoPlugin = Settings.PLUGINS.repository + return new RepoPlugin(this.nop, this.github, repo, repoConfig, this.installation_id, this.log, this.errors).sync().then(res => { + this.appendToResults(res) + return Promise.all( + childPlugins.map(([Plugin, config]) => { + return new Plugin(this.nop, this.github, repo, config, this.log, this.errors).sync() + })) + }).then(res => { + this.appendToResults(res) + }) + } catch (e) { + if (this.nop) { + const nopcommand = new NopCommand(this.constructor.name, this.repo, null, `${e}`, 'ERROR') + this.log.error(`NOPCOMMAND ${JSON.stringify(nopcommand)}`) + this.appendToResults([nopcommand]) + // throw e + } else { + throw e + } } + } else { + this.log.debug(`Didnt find any a matching repoconfig for this repo ${JSON.stringify(repo)} in ${JSON.stringify(this.repoConfigs)}`) + const childPlugins = this.childPluginsList(repo) + return Promise.all(childPlugins.map(([Plugin, config]) => { + return new Plugin(this.nop, this.github, repo, config, this.log, this.errors).sync().then(res => { + this.appendToResults(res) + }) + })) } - } else { - this.log.debug(`Didnt find any a matching repoconfig for this repo ${JSON.stringify(repo)} in ${JSON.stringify(this.repoConfigs)}`) - const childPlugins = this.childPluginsList(repo) - return Promise.all(childPlugins.map(([Plugin, config]) => { - return new Plugin(this.nop, this.github, repo, config, this.log, this.errors).sync().then(res => { - this.appendToResults(res) - }) - })) } } diff --git a/test/unit/lib/plugins/archive.test.js b/test/unit/lib/plugins/archive.test.js new file mode 100644 index 00000000..9f5804f0 --- /dev/null +++ b/test/unit/lib/plugins/archive.test.js @@ -0,0 +1,68 @@ +const Archive = require('../../../../lib/plugins/archive'); +const NopCommand = require('../../../../lib/nopcommand'); + +describe('Archive Plugin', () => { + let github; + let log; + let repo; + let settings; + let nop; + + beforeEach(() => { + github = { + repos: { + get: jest.fn(), + update: jest.fn() + } + }; + log = { + debug: jest.fn(), + }; + repo = { owner: 'test-owner', repo: 'test-repo' }; + settings = {}; + nop = false; + }); + + it('should return false if the repository is archived and settings.archived is true', async () => { + github.repos.get.mockResolvedValue({ data: { archived: true } }); + settings.archived = true; + + const archive = new Archive(nop, github, repo, settings, log); + const result = await archive.sync(); + + expect(result.shouldContinue).toBe(false); + }); + + it('should return true if the repository is archived and settings.archived is false', async () => { + github.repos.get.mockResolvedValue({ data: { archived: true } }); + settings.archived = false; + + const archive = new Archive(nop, github, repo, settings, log); + const result = await archive.sync(); + + expect(result.shouldContinue).toBe(true); + expect(log.debug).toHaveBeenCalledWith('Unarchiving test-owner/test-repo'); + }); + + it('should return false if the repository is not archived and settings.archived is true', async () => { + github.repos.get.mockResolvedValue({ data: { archived: false } }); + settings.archived = true; + + const archive = new Archive(nop, github, repo, settings, log); + const result = await archive.sync(); + + expect(result.shouldContinue).toBe(false); + expect(log.debug).toHaveBeenCalledWith('Archiving test-owner/test-repo'); + }); + + it('should return true if the repository is not archived and settings.archived is false', async () => { + github.repos.get.mockResolvedValue({ data: { archived: false } }); + settings.archived = false; + + const archive = new Archive(nop, github, repo, settings, log); + const result = await archive.sync(); + + expect(result.shouldContinue).toBe(true); + expect(log.debug).toHaveBeenCalledWith('Repo test-owner/test-repo is not archived, ignoring.'); + }); +}); \ No newline at end of file