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

Added deployTags option #4

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

jesseditson
Copy link
Contributor

Added new options & documentation to support auto creation of tags, and optionally pushing them to origin. From new docs:

You may also provide a tag if you'd like to automatically create a new tag (and optionally push it up to origin):

grunt.initConfig({
 pkg: grunt.file.readJSON('package.json'),
 'heroku-deploy' : {
     production : {
         deployTag : 'v<%= pkg.version %>',
         pushTag : true,
         origin : 'origin'
     }
 }
})

This will create a new tag, push it to origin, and deploy that tag to heroku:

git tag v0.1.1  # create a new tag
git push origin v0.1.1 # push the tag to origin (this is skipped if pushTag is missing or false)
git push -f heroku v0.1.1^{}:master

As this is a tag, it will skip the merge step because the current changes will be present in the tag.

If you would like to specify the name of the heroku remote, you can add it to the options as herokuRemote:

grunt.initConfig({
  'heroku-deploy' : {
       production : {
           deployBranch : 'prod',
           herokuRemote : 'heroku'
       }
   }
})

@hitsthings
Copy link
Owner

I'm cleaning this up now for merging and I'm writing some tests (if other people are using this, it's probably about time...).

One thing that scares me is that you git push -f for tags (the -f is the scary bit). Could you explain the workflow you're using there? The part that gets me is you create a tag first (so I'm assuming the code is new), then you force the push (which means you are expecting to remove commits - so I'm assuming you move back to old code). Those seem at odds.

Understanding your workflow would help me out on this one.

Cheers!

@jesseditson
Copy link
Contributor Author

Hey!

So the use case I'm working with is that I'd like to auto create & deploy tags in a continuous deployment scenario - so, the tags don't necessarily originate from the same place. For instance, I could be working on a branch, and deploy directly from there (without merging to master). That scenario would cause git to come back with an error, as heroku could have been updated from a different branch.

The other (probably more common) use case is in the case of rollbacks - if I want to deploy a previous tag over the existing one, it will never work unless it's forced. You definitely have a good point about not attempting to create a new tag in a rollback scenario - I'll add some code to prevent tag creation when the tag already exists to make this clearer.

I agree though that -f is a little scary, but I think the user-intent is to deploy whatever they're looking at, it would be up to the user to make sure they have their test runner tasks before this task.

The alternative would be to make this optional, and return an error if heroku refuses the push unless you've added forcePush : true to the config. If that sounds better I'll stick it in to this pull.

Thanks!

Jesse

@jesseditson
Copy link
Contributor Author

Ok, so that commit will only use -f if forcePush is set to true. In addition, it will fail if the tag that you're trying to create already exists, unless forcePush is set.

@hitsthings
Copy link
Owner

Ok so from that and my own experiences the common usages are:

  1. I want to do the existing workflow (merge into deploy branch and push from there). If I could create a tag off the merge commit to mark the occasion, that would be cool.
  2. I want to rollback to an existing tag. In this case, a push -f makes sense, but creating a tag is unnecessary, and pushing the tag is probably unnecessary.

You also mentioned deploying from a branch that you don't want merged, but rather you want to push -f to overwrite (your CI scenario). To me, it sounds like a basic task or just a cli method instead of a multi task is the right way to go for that. I could see someone doing:

> grunt heroku-deploy-as:v0.1.1

I think it's best to ignore that usage for now and handle it separately. Let me know if you disagree.

So the other 2 cases...

1

If you specify deployBranch, it will do the merge to your deploy branch. If you also specify deployTag, it will tag the merge commit with that tag name. If you specify neither, the default is still deployBranch: 'deploy'. Default options are:

{
    deployBranch: 'deploy'
    deployTag : null, // 'v<%= pkg.version %>',
    pushTagTo : [], // none by default. List of remote names. E.g.,  [ 'origin', 'heroku' ], 'origin'
    force : false // when true, will force-update the git tag if it already exists. When false, will fail the task.
}

Corresponds to:

git checkout deploy
git merge current-branch
# git tag v0.1.1
# git push origin v0.1.1
# git push heroku v0.1.1
git push
git checkout current-branch

2

If you specify deployTag only, it will deploy an existing tag to heroku using push -f by default. Default options are:

{
    deployTag : 'v<%= pkg.version %>',
    pushTagTo : [], // none by default. List of remote names. E.g.,  [ 'origin', 'heroku' ], 'origin'
    force : true
}

Corresponds to:

git checkout v0.1.1
# git push origin v0.1.1
# git push heroku v0.1.1
git -f heroku v0.1.1^{}:master

Lemme know if you see any weirdness in there.

Also if you are touching this again, please fix up JSHint errors. "use strict"; can be added to all files.

@hitsthings
Copy link
Owner

(thumbsup) and since we're now forcing tag creation as well as push, maybe
force is a better name than forcePush.
On 14/02/2013 8:18 AM, "Jesse Ditson" [email protected] wrote:

Ok, so that commit will only use -f if forcePush is set to true. In
addition, it will fail if the tag that you're trying to create already
exists, unless forcePush is set.


Reply to this email directly or view it on GitHubhttps://github.com//pull/4#issuecomment-13518653.

@jesseditson
Copy link
Contributor Author

Sounds good! I'll add use strict and lint all the files, and add replace forcePush with force, as well as make pushTagTo an array.

I think that will make everything work as you mentioned in the above reply.

@hitsthings
Copy link
Owner

Awesome!
On 14/02/2013 8:53 AM, "Jesse Ditson" [email protected] wrote:

Sounds good! I'll add use strict and lint all the files, and add replace
forcePush with force, as well as make pushTagTo an array.

I think that will make everything work as you mentioned in the above reply.


Reply to this email directly or view it on GitHubhttps://github.com//pull/4#issuecomment-13520437.

@jesseditson
Copy link
Contributor Author

Cool, so writing this stuff, looks like 2 things are necessary to make it work:

  • retention of the herokuRemote config var - this should default to heroku, but I'll need a remote name to push to. As it's very unlikely that this will not be heroku, may want to omit it and hardcode it to heroku, but couldn't hurt to have it in.
  • git checkout is unnecessary when pushing a tag - since we're specifying the tag to push, I'll skip the checkout step when pushing and/or creating a tag.

I'll shoot an update with the rest in a few minutes.

@hitsthings
Copy link
Owner

Makes perfect sense. I'll take a look and merge after work tonight. (it's
morning for me). Cheers!
On 14/02/2013 9:12 AM, "Jesse Ditson" [email protected] wrote:

Cool, so writing this stuff, looks like 2 things are necessary to make it
work:

retention of the herokuRemote config var - this should default to
heroku, but I'll need a remote name to push to. As it's very unlikely
that this will not be heroku, may want to omit it and hardcode it to
heroku, but couldn't hurt to have it in.

git checkout is unnecessary when pushing a tag - since we're
specifying the tag to push, I'll skip the checkout step when pushing and/or
creating a tag.

I'll shoot an update with the rest in a few minutes.


Reply to this email directly or view it on GitHubhttps://github.com//pull/4#issuecomment-13521406.

@jesseditson
Copy link
Contributor Author

Ok, updates are in. I'm actively using this at work, so it's pretty well manually tested.

}

function tagExists(tag,next){
exec('git tag | grep ' + tag,function(err,stdout,stderr){
Copy link
Owner

Choose a reason for hiding this comment

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

Using grep is going to stop this from working on Windows. Also would fail if they were tagging 1.0 and 0.1.0 already existed. I think this would work instead (I haven't tested though):

function escapeRE(s) {
    return s.replace(/[\-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
// ...
exec('git tag', function(err,stdout, stderr) {
  var tagRE = new RegExp('^\\s*' + escapeRE(tag) + '\\s*$');
  var isListed = stdout.split('\n').some(tagRE.test.bind(tagRE));
  next(isListed);
});

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call - thanks!

On Feb 14, 2013, at 3:26 AM, hitsthings [email protected] wrote:

In tasks/lib/heroku-deploy.js:

+}
+
+function allOutput(proc, next) {

  • var out = '';
  • proc.stdout.on('data', function(data) { out += data; });
  • proc.stdout.on('end', function() {
  • next(null, out);
  • });
    +}
    +
    +function trim(str){
  • return str.replace(/^\s+/,'').replace(/\s+$/,'');
    +}

+function tagExists(tag,next){

  • exec('git tag | grep ' + tag,function(err,stdout,stderr){

Using grep is going to stop this from working on Windows. Also would fail
if they were tagging 1.0 and 0.1.0 already existed. I think this would work
instead (I haven't tested though):

function escapeRE(s) {
return s.replace(/[-/^$+?.()|[]{}]/g, '$&');
}
// ...
exec('git tag', function(err,stdout, stderr) {
var tagRE = new RegExp('^\s
' + escapeRE(tag) + '\s*$');
var isListed = stdout.split('\n').some(tagRE.test.bind(tagRE));
next(isListed);
});


Reply to this email directly or view it on
GitHubhttps://github.com//pull/4/files#r3011521.

@ghost ghost assigned hitsthings Feb 14, 2013
@hitsthings
Copy link
Owner

I'll do the rest of the cleanup, but I'm going to take a couple days, so I hope you're not in a rush to get it on npm for any reason. I can release a milestone version pre-cleanup if you need.

Cheers and thanks again for sharing!

@jesseditson
Copy link
Contributor Author

No hurry! I'm pointing directly to my fork for now, I'll switch back to
npm whenever it's out! Thanks for the merge!

On Feb 14, 2013, at 3:31 AM, hitsthings [email protected] wrote:

I'll do the rest of the cleanup, but I'm going to take a couple days, so I
hope you're not in a rush to get it on npm for any reason. I can release a
milestone version pre-cleanup if you need.

Cheers and thanks again for sharing!


Reply to this email directly or view it on
GitHubhttps://github.com//pull/4#issuecomment-13543614.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants