diff --git a/src/actions/init/steps.js b/src/actions/init/steps.js index 0e71288..e0f778d 100644 --- a/src/actions/init/steps.js +++ b/src/actions/init/steps.js @@ -1,18 +1,8 @@ -import cpy from 'cpy'; -import jsonfile from 'jsonfile'; -import replace from 'replace-in-file'; import yaml from 'write-yaml'; -import { mkdir, readFile, writeFile } from 'lib/fs'; +import { readFile, writeFile } from 'lib/fs'; import { exec } from 'lib/child-process'; -import { CWD, DOTFILES_FOLDER } from 'constants'; - -export const createDir = async ({ packageName }) => { - const PACKAGE_DIR = `${CWD}/${packageName}`; - await mkdir(PACKAGE_DIR); - await mkdir(`${PACKAGE_DIR}/src`); - await writeFile(`${PACKAGE_DIR}/src/index.js`, ''); -}; +import { CWD } from 'constants'; export const createNcmrc = async ({ packageType, @@ -30,6 +20,7 @@ export const createNcmrc = async ({ }, package: { type: packageType, + template: '', name: packageName, description: '', keywords: '', @@ -46,7 +37,6 @@ export const createNcmrc = async ({ npm: organisationNpm, }, }; - console.log(template); const NCMRC_PATH = `${CWD}/${packageName}/.ncmrc.yml`; yaml.sync(NCMRC_PATH, template, { safe: true, @@ -60,61 +50,5 @@ export const addCommentsToNcmrc = async ({ packageName }) => { await writeFile(NCMRC_PATH, updated); }; -export const generatePackageJson = async ({ - packageType, - componentEnv, - packagePublic, - packageName, - organisationID, - npmScope, - authorDetail, -}) => { - const TEMPLATE_PATH = `${DOTFILES_FOLDER}/${packageType}/package.json`; - const template = await jsonfile.readFile(TEMPLATE_PATH); - - template.name = `@${npmScope}/${packageName}`; - template.repository = `git@github.com:${organisationID}/${packageName}.git`; - template.author = authorDetail; - - if (packagePublic) { - // make it compatible with semantic-release - delete template.private; - template.publishConfig = { - access: 'public', - }; - } - - if (componentEnv === 'cli') { - delete template.main; - template.bin = { - [packageName]: 'dist/index.js', - }; - } - - const TARGET_PATH = `${CWD}/${packageName}/package.json`; - await jsonfile.writeFile(TARGET_PATH, template, { - spaces: 2, - }); -}; - -export const copyConfigFiles = async ({ packageType, packageName }) => - cpy( - [ - `${DOTFILES_FOLDER}/common/*`, - `${DOTFILES_FOLDER}/common/.*`, - `${DOTFILES_FOLDER}/${packageType}/*`, - `${DOTFILES_FOLDER}/${packageType}/.*`, - `!${DOTFILES_FOLDER}/${packageType}/package.json`, // don't copy the package.json - ], - `./${packageName}`, - ); - -export const updateReadme = async ({ packageName, organisationID, npmScope }) => - replace({ - files: `${CWD}/${packageName}/README.md`, - from: [/{{packageName}}/g, /{{organisationID}}/g, /{{npmScope}}/g], - to: [packageName, organisationID, npmScope], - }); - export const initGit = async ({ packageName }) => exec(`git init -q ${CWD}/${packageName}`); diff --git a/src/actions/setup.js b/src/actions/setup.js deleted file mode 100644 index 8b7644c..0000000 --- a/src/actions/setup.js +++ /dev/null @@ -1,44 +0,0 @@ -import cosmiconfig from 'cosmiconfig'; -import octokit from '@octokit/rest'; - -import { exec } from 'lib/child-process'; - -const readConfig = async () => { - const MODULE_NAME = 'ncm'; - const { config } = await cosmiconfig(MODULE_NAME).search(); - return config; -}; - -const initGh = async ({ authRequired = false }) => { - const gh = octokit(); - if (authRequired) { - if (process.env.NCM_AUTH_GITHUB_TOKEN) { - throw Error('NCM_AUTH_GITHUB_TOKEN not found in environment'); - } - await gh.authenticate({ - type: 'oauth', - token: process.env.NCM_AUTH_GITHUB_TOKEN, - }); - } - return gh; -}; - -const addGitRemoteOrigin = async ({ packageName, organisation }) => - exec( - `git add remote origin git@git@github.com:${organisation}/${packageName}`, - ); - -export default async () => { - const config = await readConfig(); - const gh = await initGh(); - await gh.repos.createInOrg({ - org: config.owner.organisation, - name: config.package.name, - description: config.package.description, - private: config.package.private, - }); - await addGitRemoteOrigin({ - organisation: config.owner.organisation, - packageName: config.package.name, - }); -}; diff --git a/src/actions/setup/index.js b/src/actions/setup/index.js new file mode 100644 index 0000000..d56dada --- /dev/null +++ b/src/actions/setup/index.js @@ -0,0 +1,19 @@ +import * as steps from './steps'; + +export default async () => { + const config = await steps.readConfig(); + + await steps.cloneTemplateRepo(config); + + await steps.copyTemplateFiles(); + + await steps.removeTemplateDir(); + + await steps.updatePackageJson(config); + + // await steps.generateReadme(config); + + await steps.createGithubRepo(config); + + await steps.addGitRemoteOrigin(config); +}; diff --git a/src/actions/setup/package-json.js b/src/actions/setup/package-json.js new file mode 100644 index 0000000..c0b111f --- /dev/null +++ b/src/actions/setup/package-json.js @@ -0,0 +1,48 @@ +const configPackageJsonFromTemplate = (config, template) => { + const output = Object.assign({}, template); + if (config.package.type === 'component') { + output.name = `@${config.owner.npm}/${config.package.name}`; + output.description = config.package.description; + output.keywords = config.package.keywords; + + // cleanup possible fields + delete output.private; + delete output.license; + delete output.publishConfig; + delete output.main; + delete output.bin; + + if (!config.package.private) { + // make it compatible with semantic-release + output.publishConfig = { + access: 'public', + }; + output.license = 'MIT'; // TODO: read license in config + } else { + output.private = true; + } + + if (config.component.environment === 'cli') { + output.bin = { + [config.package.name]: 'dist/index.js', + }; + } else { + output.main = 'dist/index.js'; + } + } else { + delete output.main; // entry point specified in Dockerfile + delete output.description; // only useful in npm + delete output.keywords; // only useful in npm + delete output.engine; // only useful for component + output.name = config.package.name; + output.private = true; + } + output.repository = `git@github.com:${config.owner.github}/${ + config.package.name + }.git`; + output.author = `${config.owner.name} <${config.owner.email}>`; + + return output; +}; + +export default configPackageJsonFromTemplate; diff --git a/src/actions/setup/steps.js b/src/actions/setup/steps.js new file mode 100644 index 0000000..c424758 --- /dev/null +++ b/src/actions/setup/steps.js @@ -0,0 +1,88 @@ +import cpy from 'cpy'; +import cosmiconfig from 'cosmiconfig'; +import jsonfile from 'jsonfile'; +// import replace from 'replace-in-file'; + +// import { CWD } from 'constants'; +import { setupGithubClient } from 'lib/github'; +import { exec } from 'lib/child-process'; + +import configPackageJsonFromTemplate from './package-json'; + +// TODO: setup schema and sanitise config file +export const readConfig = async () => { + const MODULE_NAME = 'ncm'; + const { config } = await cosmiconfig(MODULE_NAME).search(); + return config; +}; + +export const cloneTemplateRepo = async config => { + const DEFAULT_TEMPLATE = `opbi/ncm-template-${config.package.type}`; + const template = config.package.template || DEFAULT_TEMPLATE; + await exec(`rm -rf .template`); + await exec(`git clone git@github.com:${template}.git .template`); +}; + +export const copyTemplateFiles = async () => { + await cpy( + [ + '.template/*', + '.template/.*', + '!.template/.ncmrc.yml', // there can be .ncmrc.yml in template + ], + '.', + ); + await exec('cp -r .template/src .'); + await exec('cp -r .template/.circle .'); +}; + +export const removeTemplateDir = async () => exec('rm -rf .template'); + +export const updatePackageJson = async config => { + const PACKAGE_JSON_PATH = './package.json'; + const template = await jsonfile.readFile(PACKAGE_JSON_PATH); + const packageJson = configPackageJsonFromTemplate(config, template); + await jsonfile.writeFile(PACKAGE_JSON_PATH, packageJson, { + spaces: 2, + }); +}; + +// export const generateReadme = async ({ +// packageName, +// organisationID, +// npmScope, +// }) => +// replace({ +// files: `${CWD}/${packageName}/README.md`, +// from: [/{{packageName}}/g, /{{organisationID}}/g, /{{npmScope}}/g], +// to: [packageName, organisationID, npmScope], +// }); + +export const createGithubRepo = async config => { + const github = await setupGithubClient(); + await github.repos.createInOrg({ + org: config.owner.github, + name: config.package.name, + description: config.package.description, + private: config.package.private, + }); +}; + +export const addGitRemoteOrigin = async config => + exec( + `git add remote origin git@git@github.com:${config.owner.github}/${ + config.package.name + }`, + ); + +// export const setupCIPipeline = async config => {}; + +// export const setupCoveralls = async config => {}; + +// export const setupScrutinizer = async config => {}; + +// export const initGitCommit = async () => {}; + +// export const installDeps = async () => {}; + +// export const initGitPush = async () => {}; diff --git a/src/lib/github.js b/src/lib/github.js new file mode 100644 index 0000000..d3b6ccb --- /dev/null +++ b/src/lib/github.js @@ -0,0 +1,17 @@ +import octokit from '@octokit/rest'; + +export const setupGithubClient = async ({ authRequired = false }) => { + const github = octokit(); + if (authRequired) { + if (process.env.NCM_AUTH_GITHUB_TOKEN) { + throw Error('NCM_AUTH_GITHUB_TOKEN not found in environment'); + } + await github.authenticate({ + type: 'oauth', + token: process.env.NCM_AUTH_GITHUB_TOKEN, + }); + } + return github; +}; + +export default {};