diff --git a/src/commands/project/init.test.ts b/src/commands/project/init.test.ts index e32f7ebe7..54bcacf85 100644 --- a/src/commands/project/init.test.ts +++ b/src/commands/project/init.test.ts @@ -27,7 +27,8 @@ describe("Initializing a blank standard repo", () => { const filepaths = [ "bedrock.yaml", "maintainers.yaml", - "azure-pipelines.yaml" + "azure-pipelines.yaml", + "Dockerfile" ].map(filename => path.join(randomTmpDir, filename)); for (const filepath of filepaths) { @@ -79,11 +80,16 @@ describe("Initializing a blank mono-repo", () => { const gitIgnoreFilePath = path.join(subProjectDir, ".gitignore"); expect(fs.existsSync(gitIgnoreFilePath)).toBe(true); + + const dockerfilePath = path.join(subProjectDir, "Dockerfile"); + expect(fs.existsSync(dockerfilePath)).toBe(true); } // azure-pipelines.yaml should not be in the root expect(fs.existsSync(path.join(randomTmpDir, "azure-pipelines.yaml"))).toBe( false ); + + expect(fs.existsSync(path.join(randomTmpDir, "Dockerfile"))).toBe(false); }); }); diff --git a/src/commands/project/init.ts b/src/commands/project/init.ts index fce351ded..6aa678003 100644 --- a/src/commands/project/init.ts +++ b/src/commands/project/init.ts @@ -4,6 +4,7 @@ import path from "path"; import shelljs from "shelljs"; import * as config from "../../config"; import { + generateDockerfile, generateGitIgnoreFile, generateStarterAzurePipelinesYaml } from "../../lib/fileutils"; @@ -71,7 +72,7 @@ export const initCommandDecorator = (command: commander.Command): void => { }; /** - * Initializes the `rootProject` with a bedrock.yaml, maintainers.yaml, and azure-pipelines.yaml file + * Initializes the `rootProject` with a bedrock.yaml, maintainers.yaml * If opts.monoRepo == true, the root directly will be initialized as a mono-repo * If opts.monoRepo == true, all direct subdirectories under opts.packagesDir will be initialized as individual projects * @@ -116,6 +117,7 @@ export const initialize = async ( for (const absPackagePath of absPackagePaths) { await generateStarterAzurePipelinesYaml(absProjectRoot, absPackagePath); generateGitIgnoreFile(absPackagePath, gitIgnoreFileContent); + generateDockerfile(absPackagePath); } logger.info(`Project initialization complete!`); diff --git a/src/commands/service/create.test.ts b/src/commands/service/create.test.ts index 7985aa8eb..654e7950b 100644 --- a/src/commands/service/create.test.ts +++ b/src/commands/service/create.test.ts @@ -52,7 +52,7 @@ describe("Adding a service to a repo directory", () => { expect(fs.existsSync(serviceDirPath)).toBe(true); // Verify new azure-pipelines created - const filepaths = ["azure-pipelines.yaml"].map(filename => + const filepaths = ["azure-pipelines.yaml", "Dockerfile"].map(filename => path.join(serviceDirPath, filename) ); @@ -90,8 +90,8 @@ describe("Adding a service to a repo directory", () => { const serviceDirPath = path.join(randomTmpDir, packageDir, serviceName); expect(fs.existsSync(serviceDirPath)).toBe(true); - // Verify new azure-pipelines created - const filepaths = ["azure-pipelines.yaml"].map(filename => + // Verify new azure-pipelines and Dockerfile created + const filepaths = ["azure-pipelines.yaml", "Dockerfile"].map(filename => path.join(serviceDirPath, filename) ); diff --git a/src/commands/service/create.ts b/src/commands/service/create.ts index d640c66e8..23d6c3c4c 100644 --- a/src/commands/service/create.ts +++ b/src/commands/service/create.ts @@ -6,6 +6,7 @@ import { logger } from "../../logger"; import { addNewServiceToBedrockFile, addNewServiceToMaintainersFile, + generateDockerfile, generateGitIgnoreFile, generateStarterAzurePipelinesYaml } from "../../lib/fileutils"; @@ -212,6 +213,9 @@ export const createService = async ( // Create empty .gitignore file in directory generateGitIgnoreFile(newServiceDir, ""); + // Create simple Dockerfile in directory + generateDockerfile(newServiceDir); + // add maintainers to file in parent repo file const newUser = { email: maintainerEmail, diff --git a/src/lib/fileutils.test.ts b/src/lib/fileutils.test.ts index ece0cb880..17ad8745e 100644 --- a/src/lib/fileutils.test.ts +++ b/src/lib/fileutils.test.ts @@ -15,6 +15,7 @@ import { IBedrockFile, IHelmConfig, IMaintainersFile } from "../types"; import { addNewServiceToBedrockFile, addNewServiceToMaintainersFile, + generateDockerfile, generateGitIgnoreFile, generateHldAzurePipelinesYaml } from "./fileutils"; @@ -197,3 +198,41 @@ describe("Adding a new service to a Bedrock file", () => { ); }); }); + +describe("generating service Dockerfile", () => { + const targetDirectory = "my-new-service"; + + beforeEach(() => { + mockFs({ + "my-new-service": {} + }); + }); + afterEach(() => { + mockFs.restore(); + }); + + it("should not do anything if file exist", async () => { + const mockFsOptions = { + [`${targetDirectory}/Dockerfile`]: "hello!!!!" + }; + mockFs(mockFsOptions); + + const writeSpy = jest.spyOn(fs, "writeFileSync"); + generateDockerfile(targetDirectory); + expect(writeSpy).not.toBeCalled(); + }); + + it("should generate the file if one does not exist", async () => { + const writeSpy = jest.spyOn(fs, "writeFileSync"); + generateDockerfile(targetDirectory); + + const absTargetPath = path.resolve(targetDirectory); + const expectedGitIgnoreFilePath = `${absTargetPath}/Dockerfile`; + + expect(writeSpy).toBeCalledWith( + expectedGitIgnoreFilePath, + "FROM alpine\nRUN echo 'hello world'", + "utf8" + ); + }); +}); diff --git a/src/lib/fileutils.ts b/src/lib/fileutils.ts index dacbcd6c7..63d7734c5 100644 --- a/src/lib/fileutils.ts +++ b/src/lib/fileutils.ts @@ -294,3 +294,31 @@ export const addNewServiceToBedrockFile = ( logger.info("Updating bedrock.yaml"); fs.writeFileSync(bedrockFilePath, yaml.safeDump(bedrockFile), "utf8"); }; + +/** + * Writes out a default Dockerfile if one doesn't exist + * + * @param targetDirectory directory to generate the Dockerfile + * @param content content of file + */ +export const generateDockerfile = (targetDirectory: string) => { + const absTargetPath = path.resolve(targetDirectory); + logger.info(`Generating starter Dockerfile in ${absTargetPath}`); + + const dockerfilePath = path.join(absTargetPath, "Dockerfile"); + + if (fs.existsSync(dockerfilePath)) { + logger.warn( + `Existing Dockerfile found at ${dockerfilePath}, skipping generation.` + ); + + return; + } + + logger.info(`Writing Dockerfile to ${dockerfilePath}`); + fs.writeFileSync( + dockerfilePath, + "FROM alpine\nRUN echo 'hello world'", + "utf8" + ); +};