On Aug 26, 2009, at 9:27 AM, Steven Jenkins wrote:

> Recently, Luke, James and I were discussing adding some tasks to help
> people stay consisent with the workflow documented at
>
> http://reductivelabs.com/trac/puppet/wiki/Development/DevelopmentLifecycle
>
> This patch adds subsumes the existing mail_patches task, and adds  
> three new ones:
>
> rake start_feature[feature,branch]  # Do git setup to start work on  
> a feature
>
> Will set up your git repo to have the correct branch (based on  
> 'branch',
> with 'master' as the default starting point).  Note that you can  
> invoke it
> with or without a branch:  e.g.,
>
> rake start_feature[events]

I'm a little confused by this syntax -- is it literally  
'start_feature[events]'?  If so, doesn't the shell expand that  
weirdly?  Or at least, couldn't it?  Is this a rake thing?

>
> creates a branch named feature/master/events, starting at the  
> current HEAD of master
>
> while
>
> rake start_feature[events,0.24.8]
>
> creates a branch named feature/0.24.8/events, starting at the 0.24.8  
> ref.
>
> rake start_ticket[ticket,branch]    # Do git setup to start work on  
> a Redmine ticket
>
> Will set up your git repo to have the correct branch (based on  
> 'branch',
> with 'master' as the default starting point).  This task also takes
> an optional branch as it's starting point.
>
> rake push_changes[remote]           # Push out changes
>
> Will push out the current branch to the specified remote -- it's a  
> pretty
> trivial task, but I put it there so that we might add  more complex
> tasks down the road (e.g., add a dependency for the rake spec task to
> this task so that before pushes are done, all spec tests pass).
> Also, I toyed with using the git-ruby library (http://git.rubyforge.org/ 
> )
> and replacing the shell invocations with Ruby code, but I thought
> that would be more appropriate for a later version.  If someone  
> would like
> to see that, feel free to let me know (or, better yet, submit  
> code..).  I was
> also a little hesitant to add another gem dependency.

I like the idea of using this - it's something we'd probably start to  
use a lot more of.

>
> Comments, feedback welcome.  Also, this patch is available on my  
> github account
> at http://github.com/stevenjenkins/puppet/tree/rake_git_branch
>
> Thanks,
> Steven Jenkins
> End Point Corporation
>
> >
> From 1c7110a672371e62466a2142e9a4e4e41fe0086f Mon Sep 17 00:00:00 2001
> From: Steven Jenkins <[email protected]>
> Date: Tue, 25 Aug 2009 20:41:11 -0400
> Subject: [PATCH/puppet] Implement tasks for git-based workflow
>
>
> Signed-off-by: Steven Jenkins <[email protected]>
> ---
> tasks/rake/git_workflow.rake |   93 +++++++++++++++++++++++++++++++++ 
> +++++++++
> tasks/rake/mail_patches.rake |   35 ----------------
> 2 files changed, 93 insertions(+), 35 deletions(-)
> create mode 100644 tasks/rake/git_workflow.rake
> delete mode 100644 tasks/rake/mail_patches.rake

Does the Rakefile automatically load all rake task files, or should  
there be a require in here, or what?  It seems weird you can move the  
mail_patches task without having to change a require.

Either way, though, I'm all for this kind of thing -- adding  
automation around our process is great.

>
> diff --git a/tasks/rake/git_workflow.rake b/tasks/rake/ 
> git_workflow.rake
> new file mode 100644
> index 0000000..98f487a
> --- /dev/null
> +++ b/tasks/rake/git_workflow.rake
> @@ -0,0 +1,93 @@
> +# This set of tasks helps automate the workflow as described on
> +# http://reductivelabs.com/trac/puppet/wiki/Development/DevelopmentLifecycle
> +
> +# This should be changed as new versions get released
> +...@next_release = "0.26.x"

We often won't actually know this.  E.g., I actually hope the next  
release (after 0.25) is 1.0, but we're going to start on the  
assumption it'll be 0.26.

>
> +def find_start(start)
> +# This is a case statement, as we might want to map certain
> +# git tags to starting points that are not currently in git.
> +     case start
> +             when @next_release: return "master"
> +             else return start
> +     end
> +end
> +
> +desc "Do git setup to start work on a feature"
> +task :start_feature, [:feature,:branch] do |t, args|

I take it this is how rake deals with the start_feature[events] syntax?

>
> +     args.with_defaults(:branch => @next_release)
> +     start_at = find_start(args.branch)
> +     command = "git checkout -b feature/#{start_at}/#{args.feature}  
> #{start_at}"
> +     %x{#{command}}
> +     if $? != 0
> +             raise <<EOS
> +Was not able to create branch for #{args.feature} on branch  
> #{args.branch}, starting at #{start_at}: error code was: #{$?}
> +Git command used was: #{command}
> +
> +The most common error is to specify a non-existent starting point.
> +EOS
> +     end
> +end
> +
> +desc "Do git setup to start work on a Redmine ticket"
> +task :start_ticket, [:ticket, :branch] do |t, args|
> +     args.with_defaults(:branch => @next_release)
> +
> +     start_at = find_start(args.branch)
> +     command = "git checkout -b ticket/#{args.branch}/#{args.ticket}  
> #{start_at}"
> +     %x{#{command}}
> +     if $? != 0
> +             raise <<EOS
> +Was not able to create branch for ticket #{args.ticket} on branch  
> #{args.branch}, starting at #{start_at}: error code was: #{$?}
> +Git command used was: #{command}
> +
> +The most common error is to specify a non-existent starting point.
> +EOS
> +     end
> +end

I like the idea of these tasks, but I think it'd be nice if they made  
the corresponding remote setups.  E.g., adding something like the  
following to the git config:

[branch "tickets/master/2296"]
     remote = luke
     merge = refs/heads/tickets/master/2296

I think there are git commands to do so.  We could easily require a  
git config option that specified the default remote, and then set  
these up.  That way all of the 'git push' stuff works just fine.

I've also got a 'git-cleanup-branch' script that cleans up things like  
this by looking through the git history to see if a given commit (as  
determined by its summary, rather than its commit, since that will  
change on a rebase) is merged, and if so removes the local and remote  
branches.  90% of its code is abstracting git into an OO interface, so  
it makes sense to start using the lib at that point.

>
> +# This isn't very useful by itself, but we might enhance it later,  
> or use it
> +# in a dependency for a more complex task.
> +desc "Push out changes"
> +task :push_changes, [:remote] do |t, arg|
> +     branch = %x{git branch | grep "^" | awk '{print $2}'}
> +     %x{git push #{arg.remote} #{branch}}
> +     raise "Unable to push to #{arg.remote}" if $? != 0
> +end

With the above setup, this becomes a bit unnecessary.

>
> +desc "Send patch information to the puppet-dev list"
> +task :mail_patches do
> +    if Dir.glob("00*.patch").length > 0
> +        raise "Patches already exist matching '00*.patch'; clean up  
> first"
> +    end
> +
> +    unless %x{git status} =~ /On branch (.+)/
> +        raise "Could not get branch from 'git status'"
> +    end
> +    branch = $1
> +
> +    unless branch =~ %r{^([^\/]+)/([^\/]+)/([^\/]+)$}
> +        raise "Branch name does not follow <type>/<parent>/<name>  
> model; cannot autodetect parent branch"
> +    end
> +
> +    type, parent, name = $1, $2, $3
> +
> +    # Create all of the patches
> +    sh "git format-patch -C -M -s -n --subject-prefix='PATCH/ 
> puppet' #{parent}..HEAD"
> +
> +    # And then mail them out.
> +
> +    # If we've got more than one patch, add --compose
> +    if Dir.glob("00*.patch").length > 1
> +        compose = "--compose"
> +    else
> +        compose = ""
> +    end
> +
> +    # Now send the mail.
> +    sh "git send-email #{compose} --no-signed-off-by-cc --suppress- 
> from --to [email protected] 00*.patch"
> +
> +    # Finally, clean up the patches
> +    sh "rm 00*.patch"
> +end
> +
> diff --git a/tasks/rake/mail_patches.rake b/tasks/rake/ 
> mail_patches.rake
> deleted file mode 100644
> index 82455e8..0000000
> --- a/tasks/rake/mail_patches.rake
> +++ /dev/null
> @@ -1,35 +0,0 @@
> -desc "Send patch information to the puppet-dev list"
> -task :mail_patches do
> -    if Dir.glob("00*.patch").length > 0
> -        raise "Patches already exist matching '00*.patch'; clean up  
> first"
> -    end
> -
> -    unless %x{git status} =~ /On branch (.+)/
> -        raise "Could not get branch from 'git status'"
> -    end
> -    branch = $1
> -
> -    unless branch =~ %r{^([^\/]+)/([^\/]+)/([^\/]+)$}
> -        raise "Branch name does not follow <type>/<parent>/<name>  
> model; cannot autodetect parent branch"
> -    end
> -
> -    type, parent, name = $1, $2, $3
> -
> -    # Create all of the patches
> -    sh "git format-patch -C -M -s -n --subject-prefix='PATCH/ 
> puppet' #{parent}..HEAD"
> -
> -    # And then mail them out.
> -
> -    # If we've got more than one patch, add --compose
> -    if Dir.glob("00*.patch").length > 1
> -        compose = "--compose"
> -    else
> -        compose = ""
> -    end
> -
> -    # Now send the mail.
> -    sh "git send-email #{compose} --no-signed-off-by-cc --suppress- 
> from --to [email protected] 00*.patch"
> -
> -    # Finally, clean up the patches
> -    sh "rm 00*.patch"
> -end
> -- 
> 1.6.1.rc3
>


-- 
The only really good place to buy lumber is at a store where the lumber
has already been cut and attached together in the form of furniture,
finished, and put inside boxes. --Dave Barry
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://madstop.com


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to