diff --git a/plugins/all-contributors/__tests__/all-contributors.test.ts b/plugins/all-contributors/__tests__/all-contributors.test.ts index 91591bb55..f4390d464 100644 --- a/plugins/all-contributors/__tests__/all-contributors.test.ts +++ b/plugins/all-contributors/__tests__/all-contributors.test.ts @@ -1,4 +1,5 @@ import * as Auto from "@auto-it/core"; +import generateReadme from "all-contributors-cli/dist/generate"; import addContributor from "all-contributors-cli/dist/contributors"; import { makeHooks, @@ -11,6 +12,7 @@ import env from "env-ci"; import AllContributors from "../src"; +const generateMock = jest.fn(); const addContributorMock = jest.fn(); const envMock = jest.fn(); const gitShow = jest.fn(); @@ -25,6 +27,9 @@ jest.mock("env-ci"); jest.mock("child_process"); jest.mock("all-contributors-cli/dist/contributors"); jest.mock("all-contributors-cli/dist/generate"); + +// @ts-ignore +generateReadme.mockImplementation(generateMock); // @ts-ignore addContributor.mockImplementation(addContributorMock); // @ts-ignore @@ -546,6 +551,35 @@ describe("All Contributors Plugin", () => { expect(addContributorMock).not.toHaveBeenCalled(); }); + test("should initialize contributors if not already initialized", async () => { + const releasedLabel = new AllContributors(); + const autoHooks = makeHooks(); + mockRead( + '{ "contributors": [ { "login": "Jeff", "contributions": ["code"] } ], "files": ["README.md"]}' + ); + + mockRead( + "\n\n\n\n" + ); + + releasedLabel.apply({ hooks: autoHooks, logger: dummyLog() } as Auto.Auto); + + await autoHooks.afterAddToChangelog.promise({ + bump: Auto.SEMVER.patch, + currentVersion: "0.0.0", + lastRelease: "0.0.0", + releaseNotes: "", + commits: [ + makeCommitFromMsg("Do the thing", { + files: ["src/index.ts"], + username: "Jeff", + }), + ], + }); + + expect(generateMock).toHaveBeenCalled(); + }); + describe("parseCommit", () => { test("should do nothing if no extra contributions are found", async () => { const releasedLabel = new AllContributors(); diff --git a/plugins/all-contributors/src/index.ts b/plugins/all-contributors/src/index.ts index ac1ef803d..59338f99a 100644 --- a/plugins/all-contributors/src/index.ts +++ b/plugins/all-contributors/src/index.ts @@ -80,7 +80,7 @@ function getRcFile(auto: Auto) { `Encountered errors loading all-contributors configuration at ${rcFile}`, error ); - process.exit(1) + process.exit(1); } } @@ -110,7 +110,7 @@ interface AllContributorsRc { /** All of the current contributors */ contributors: Contributor[]; /** Files to generate a markdown table of contributors in */ - files: string[]; + files?: string[]; } const defaultOptions: IAllContributorsPluginOptions = { @@ -173,6 +173,31 @@ function getExtraContributors(body?: string) { return authorContributions; } +/** Determine which files need to display contributors and generate contributors */ +function generateContributorReadme( + config: AllContributorsRc, + contributors: any +) { + return Promise.all( + (config.files || ["README.md"]).map(async (file) => { + const oldReadMe = fs.readFileSync(file, { + encoding: "utf-8", + }); + const newReadMe = await generateReadme( + { + contributorsPerLine: 7, + imageSize: 100, + ...config, + contributors, + }, + contributors, + oldReadMe + ); + fs.writeFileSync(file, newReadMe); + }) + ); +} + /** Automatically add contributors as changelogs are produced. */ export default class AllContributorsPlugin implements IPlugin { /** The name of the plugin */ @@ -180,6 +205,8 @@ export default class AllContributorsPlugin implements IPlugin { /** The options of the plugin */ readonly options: Required; + /** Has the Readme been initialized */ + private generatedReadme: boolean; /** Initialize the plugin with it's options */ constructor(options: IAllContributorsPluginOptions = {}) { @@ -187,6 +214,8 @@ export default class AllContributorsPlugin implements IPlugin { exclude: [...(defaultOptions.exclude || []), ...(options.exclude || [])], types: { ...defaultOptions.types, ...options.types }, }; + + this.generatedReadme = false; } /** Tap into auto plugin points. */ @@ -485,31 +514,35 @@ export default class AllContributorsPlugin implements IPlugin { username, Array.from(newContributions).join(",") ); - + this.generatedReadme = true; // Update files that contain contributors table - await Promise.all( - (config.files || ["README.md"]).map(async (file) => { - const oldReadMe = fs.readFileSync(file, { - encoding: "utf-8", - }); - const newReadMe = await generateReadme( - { - contributorsPerLine: 7, - imageSize: 100, - ...config, - contributors, - }, - contributors, - oldReadMe - ); - fs.writeFileSync(file, newReadMe); - }) - ); + await generateContributorReadme(config, contributors); } else { auto.logger.verbose.warn(`"${username}" had no new contributions...`); } } + if (config.contributors.length && !this.generatedReadme) { + // if the all-contributors has not been generated ... generate it + try { + // test if the first file in the list of files has been init + const file = path.join( + process.cwd(), + config.files ? config.files[0] : "README.md" + ); + + const displayFile = file ? fs.readFileSync(file, "utf8") : ""; + + const notInitalized = displayFile.indexOf( + "\n" + ); + + if (notInitalized && file) { + await generateContributorReadme(config, config.contributors); + } + } catch {} + } + if (didUpdate) { auto.logger.log.success("Updated contributors!"); }