Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure that create script installs same version of starter files and kit #1621

Merged
merged 5 commits into from
Sep 27, 2022
Merged
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
67 changes: 58 additions & 9 deletions bin/cli
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#!/usr/bin/env node

const fs = require('fs-extra')
const os = require('os')
const path = require('path')

const { exec } = require('../lib/exec')
const { runUpgrade } = require('../lib/upgradeToV13')

Expand Down Expand Up @@ -29,6 +31,14 @@ public/
.idea
`

const packageJson = {
scripts: {
start: 'govuk-prototype-kit start'
}
}

const packageJsonFormat = { encoding: 'utf8', EOL: os.EOL, spaces: 2 }

function usage () {
const prog = 'npx govuk-prototype-kit'
console.log(`
Expand Down Expand Up @@ -84,34 +94,73 @@ const getChosenKitDependency = () => {

(async () => {
if (command === 'create') {
// Install as a two-stage bootstrap process.
//
// In stage one (`create`) we create an empty project folder and install
// govuk-prototype-kit and govuk-frontend, then bootstrap stage two from
// the newly installed package.
//
// In stage two (`init`) we do the actual setup of the starter files.
//
// Doing it this way means we can be sure the version of the cli matches
// the version of the kit the user ends up with. Try to put as much logic
// as possible into stage two; stage one should ideally be able to install
// any future version of the kit.

const installDirectory = getInstallLocation()
const kitDependency = getChosenKitDependency()

const copyFile = (fileName) => fs.copy(path.join(kitRoot, fileName), path.join(installDirectory, fileName))

await fs.ensureDir(installDirectory)
if ((await fs.readdir(installDirectory)).length > 0) {
console.error(`Directory ${installDirectory} is not empty, please specify an empty location.`)
process.exit(3)
process.exitCode = 3
return
}

await Promise.all([
fs.copy(path.join(kitRoot, 'prototype-starter'), installDirectory),
fs.writeFile(path.join(installDirectory, '.gitignore'), gitignore, 'utf8'),
fs.writeFile(path.join(installDirectory, '.npmrc'), npmrc, 'utf8'),
copyFile('LICENCE.txt')
])
await fs.writeJson(path.join(installDirectory, 'package.json'), {}, packageJsonFormat)

console.log('Creating your prototype')
const dots = setInterval(() => {
process.stdout.write('.')
}, 500)

await exec(`npm install ${kitDependency} govuk-frontend`, {
stdio: 'inherit',
cwd: installDirectory
}, console.log)

clearInterval(dots)

await exec(`npx govuk-prototype-kit init -- ${installDirectory}`, {
stdio: 'inherit',
cwd: installDirectory
}, console.log)
} else if (command === 'init') {
// `init` is stage two of the install process (see above), it should be
// called by `create` with the correct arguments.

if (additionalOptions[0] !== '--') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for the double-hypen? Is it just to make sure people don't use it by mistake?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, exactly that 😁

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether we should be more specific with it - something like --internal-use-only ... selfishly for the parser I've just created I'd love it if it was a key and value pair e.g. ---internal-use=true.

If you think it's best as just -- we can support that separately to the parser.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether we should be more specific with it

I'm not sure there is any need to be more specific, using -- to indicate internal arguments is a pattern I've encountered several times before in the past.

If you think it's best as just -- we can support that separately to the parser.

Yeah, I don't think it needs to go into the parser, this code can read the arguments straightforwardly from process.argv and assume that the caller has supplied them correctly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'm happy with that.

usage()
process.exitCode = 2
return
}

const installDirectory = additionalOptions[1]

const copyFile = (fileName) => fs.copy(path.join(kitRoot, fileName), path.join(installDirectory, fileName))
const updatePackageJson = async (packageJsonPath) => {
let newPackageJson = Object.assign({}, packageJson)
newPackageJson = Object.assign(newPackageJson, await fs.readJson(packageJsonPath))
await fs.writeJson(packageJsonPath, newPackageJson, packageJsonFormat)
}

await Promise.all([
fs.copy(path.join(kitRoot, 'prototype-starter'), installDirectory),
fs.writeFile(path.join(installDirectory, '.gitignore'), gitignore, 'utf8'),
fs.writeFile(path.join(installDirectory, '.npmrc'), npmrc, 'utf8'),
copyFile('LICENCE.txt'),
updatePackageJson(path.join(installDirectory, 'package.json'))
])
} else if (command === 'start') {
require('../start')
} else if (command === 'upgrade') {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"tmp-kit": "mkdir -p $TMPDIR/govuk-prototype-kit-playground && cd $TMPDIR/govuk-prototype-kit-playground && rm -Rf ./* && govuk-prototype-kit create --version local . && npm start",
"start": "echo 'This project cannot be started, in order to test this project please create a prototype kit using the cli.'",
"start:package": "KIT_TEST_DIR=tmp/test-prototype-package node cypress/scripts/run-starter-prototype",
"lint": "standard '**/*.js' scripts/create-release-archive scripts/cli lib/build/dev-server lib/build/generate-assets",
"lint": "standard '**/*.js' bin/cli scripts/create-release-archive lib/build/dev-server lib/build/generate-assets",
"rapidtest": "jest --bail",
"cypress:open": "cypress open",
"test:heroku": "echo 'test:heroku' needs to be implemented",
Expand Down
5 changes: 0 additions & 5 deletions prototype-starter/package.json

This file was deleted.