-
Notifications
You must be signed in to change notification settings - Fork 139
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
Add push command which starts a build on remote resin servers #868
Conversation
8a2dfde
to
5cd1910
Compare
5cd1910
to
1a42340
Compare
1a42340
to
ff6911a
Compare
lib/actions/push.ts
Outdated
export const push: CommandDefinition = { | ||
signature: 'push <application>', | ||
description: 'Start a remote build', | ||
help: 'TODO', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This TODO needs TODOING
lib/actions/push.ts
Outdated
}); | ||
|
||
if (applications == null || applications.length === 0) { | ||
throw new Error(`No applications found with name: ${appName}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should use exitWithExpectedError
(which stops the error being reported to Sentry).
lib/actions/push.ts
Outdated
parameter: 'source', | ||
}, | ||
], | ||
// FIXME: We shouldn't need to type options here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The general way I've been doing this is passing the types as generic args to CommandDefinition
. Something like:
export const push: CommandDefinition<{
application: string
}, {
source: string
}> = {
...
That'll then infer the type of param & options here correctly for you.
(I have a beautiful dream that one day I'll find time to rewrite Capitano in a form that makes these types totally inferrable from the definition itself, but not today)
lib/actions/push.ts
Outdated
|
||
const app: string | null = params.application; | ||
if (app == null) { | ||
throw new Error('You must specify an application'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be an expected error too.
lib/utils/remote-build.ts
Outdated
|
||
import { tarDirectory } from './compose'; | ||
|
||
const DEBUG_MODE = process.env.DEBUG === '1'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everywhere else debug is set with !!process.env.DEBUG
- i.e. any set non-empty value.
lib/utils/remote-build.ts
Outdated
process.stderr.write('Received SIGINT, cleaning up. Please wait.\n'); | ||
cancelBuildIfNecessary(build).then(() => { | ||
stream.end(); | ||
process.exit(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be 0
? I think 130 is standard for SIGINT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the workflow, I don't think it matters too much, e.g. if we're here, we know we can exit straight away. That being said, 130
is more correct, so I'll change it.
process.removeAllListeners('SIGINT'); | ||
process.on('SIGINT', () => { | ||
process.stderr.write('Received SIGINT, cleaning up. Please wait.\n'); | ||
cancelBuildIfNecessary(build).then(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the builder already checks for closed connections and cancels builds for us: https://github.com/resin-io/resin-builder/blob/92b078f85216d2d62408fde9a3ea87ae400c903c/src/run-build.ts#L173-L180
Can't we use that, instead of reimplementing this client-side too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the ELB, this doesn't always work. We have extra code in the git server to handle this too, and tbh I think redundancy on something like this is completely fine. If a user ctrl+c's a resin push
, the last thing we want is for the build to still get deployed.
lib/utils/remote-build.ts
Outdated
|
||
async function getRequestStream(build: RemoteBuild): Promise<Stream.Duplex> { | ||
// Tar the directory so that we can send it to the builder | ||
const tarStream = await tarDirectory(build.source); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Annoyingly relative paths seem to cause problems with pkg at times e.g. #824.
We need to path.resolve(build.source)
somewhere (probably here) to get the correct absolute path and make sure we avoid this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good to know, thanks!
lib/utils/remote-build.ts
Outdated
console.log('[debug] Opened builder connection. Streaming data...'); | ||
} | ||
|
||
tarStream.pipe(post); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, there's no output until the context directory is tarred and fully uploaded. That's not great if you have a large local directory. There was quite a bit of confusion from local push where people didn't understand what it was doing and why it took so long, because they accidentally had enormous local folders they were pushing over the network each time.
Can we add some initial output and a nice spinner while we do the upload?
lib/utils/remote-build.ts
Outdated
} | ||
|
||
async function cancelBuildIfNecessary(build: RemoteBuild): Promise<void> { | ||
if (build.running && build.releaseId != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need the separate running
flag? Can't we just check if we've got a release id?
c9cb547
to
3e29cbe
Compare
@CameronDiver, status checks have failed for this PR. Please make appropriate changes and recommit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The build's failing btw because you haven't rebuilt the docs or prettified. npm run build
will make sure everything's 100% up to date.
lib/actions/push.ts
Outdated
`This command can be used to start a build on the remote resin.io cloud | ||
builders. The given source directory will be added to a tarfile, which | ||
will be sent to the resin.io builder, and the build will proceed. This | ||
can be used as a drop-in replacement for git push to deploy.`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you pulled this out just because indentation with backticks is messy? There's a nicer solution to that: stripIndent
(e.g. https://github.com/resin-io/resin-cli/blob/b7214a306c6b0a5e45387f93c9142219ff6d7b60/lib/actions/api-key.ts)
import { stripIndent } from 'common-tags';
...
export const push: CommandDefinition<...> = {
help: stripIndent`
This command can be used to start a build on the remote resin.io cloud
builders. The given source directory will be added to a tarfile, which
will be sent to the resin.io builder, and the build will proceed. This
can be used as a drop-in replacement for git push to deploy.
`,
lib/actions/push.ts
Outdated
const PUSH_HELP_TEXT = | ||
`This command can be used to start a build on the remote resin.io cloud | ||
builders. The given source directory will be added to a tarfile, which | ||
will be sent to the resin.io builder, and the build will proceed. This |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd skip the tarfile
bit - I think a few users won't be familiar with tar files (especially on Windows etc), and it's not strictly necessary. Just will be send to the resin.io builder in a compressed form
is fine imo.
lib/actions/push.ts
Outdated
exitWithExpectedError( | ||
`No applications found with name: ${appName}.\n\n` + | ||
'This could mean that the application does not exist, or you do \n' + | ||
'not have the permissions required to access it.' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably want stripIndent
here and a multiline string here too.
lib/actions/push.ts
Outdated
`This command can be used to start a build on the remote resin.io cloud | ||
builders. The given source directory will be added to a tarfile, which | ||
will be sent to the resin.io builder, and the build will proceed. This | ||
can be used as a drop-in replacement for git push to deploy.`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also normally include an example command in the help text. This is what becomes the CLI docs on https://docs.resin.io/reference/cli/, and they get nicely rendered there (and they're useful here too).
https://github.com/resin-io/resin-cli/blob/b7214a306c6b0a5e45387f93c9142219ff6d7b60/lib/actions/device.coffee#L133-L143 is a nice example imo.
lib/utils/remote-build.ts
Outdated
stream.on('data', (data: BuilderMessage) => { | ||
if (!spinnerStopped) { | ||
uploadSpinner.stop(); | ||
spinnerStopped = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This spinner actually has its own check to make stop()
safe: https://github.com/resin-io-modules/resin-cli-visuals/blob/edeb543a5c83cb67b684564f7835e8a69dfeaf6a/lib/widgets/spinner.coffee#L78
You could drop spinnerStopped
entirely, and just call uploadSpinner.stop()
every time.
lib/utils/remote-build.ts
Outdated
// FIXME: Make this error nicer. | ||
console.log( | ||
'Warning: ignoring unknown builder command. You may experience odd build output. ' + | ||
'Maybe you need to update resin-cli?', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stripIndent
lib/utils/remote-build.ts
Outdated
const uploadSpinner = new visuals.Spinner('Uploading source package to resin cloud'); | ||
uploadSpinner.start(); | ||
|
||
tarStream.pipe(post); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, imo we should add a data
handler here that's tied to uploadSpinner.stop()
, and not return the spinner at all. I think that should work fine, and lets the code everywhere else ignore the spinners entirely.
3e29cbe
to
35aa8eb
Compare
lib/actions/push.ts
Outdated
> = { | ||
signature: 'push <application>', | ||
description: 'Start a remote build on the resin.io cloud build servers', | ||
help: stripIndent`This command can be used to start a build on the remote |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, if you test this help text, you'll see this doesn't work properly.
stripIndent
strips the common indent, ignoring empty lines, so you'll need to start with an empty line. If you don't, as here, then the common indent is zero (the first line has none) and text all goes wrong.
Same for the other cases here too. You want things like:
help: stripIndent`
This command can be used to start a build on the remote
resin.io cloud builders. The given source directory will be sent to the
resin.io builder, and the build will proceed. This can be used as a drop-in
replacement for git push to deploy.
Examples:
$ resin push myApp
$ resin push myApp --source <source directory>
$ resin push myApp -s <source directory>
`,
That should do what you expect.
35aa8eb
to
78b5b9a
Compare
Change-type: minor Connects-to: #843
78b5b9a
to
439d8d3
Compare
@CameronDiver, status checks have failed for this PR. Please make appropriate changes and recommit. |
20b2d74
to
439d8d3
Compare
This PR adds a module which coordinates building projects using the resin remote servers. Currently this is meant to have feature parity with
git push resin master
.Also added a function in patterns.ts which provides an interface to ask the user a question, and give several options.
Change-type: minor
Connects-to: #843
---- Autogenerated Waffleboard Connection: Connects to #843