summaryrefslogtreecommitdiffstats
path: root/tasks/rake/git_workflow.rake
blob: c275bba3f9a2a6069789a6d61a84cfb269995696 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# This set of tasks helps automate the workflow as described on
# http://reductivelabs.com/trac/puppet/wiki/Development/DevelopmentLifecycle


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 nil?:
		when @next_release: return "master"
		else return start
	end
end

desc "Set up git for working with Puppet"
task :git_setup do
	# This should be changed as new versions get released
	@next_release = '0.26.x'
	@remote = {}
	default_remote = {}
	default_remote[:url] = 'git://github.com/reductivelabs/puppet'
	default_remote[:name] = 'origin'
	@remote[:name] = %x{git config puppet.defaultremote}.chomp
	@remote[:name] = @remote[:name].empty? ? default_remote[:name] : @remote[:name]
	@remote[:url] = default_remote[:url] if @remote[:name] == default_remote[:name]
	default_fetch = '+refs/heads/*:refs/remotes/puppet/*'
	@remote[:fetch] = %x{git config puppet.#{@remote[:name]}.fetch}.chomp
	@remote[:fetch] = @remote[:fetch].empty? ?  default_fetch : @remote[:fetch]
end

desc "Start work on a feature"
task :start_feature, [:feature,:remote,:branch] => :git_setup do |t, args|
	args.with_defaults(:remote => @remote[:name])
	args.with_defaults(:branch => @next_release)
	start_at = find_start(args.branch)
	branch = "feature/#{start_at}/#{args.feature}"
	sh "git checkout -b #{branch} #{start_at}" do |ok, res|
		if ! ok
			raise <<EOS
Was not able to create branch for #{args.feature} on branch #{args.branch}, starting at #{start_at}: error code was: #{res.exitstatus}
EOS
		end
	end
	sh "git config branch.#{branch}.remote #{args.remote}" do |ok, res|
		raise "Could not set remote: #{$?}" unless ok
	end

	sh "git config branch.#{branch}.merge refs/heads/#{branch}" do |ok, res|
		raise "Could not configure merge: #{$?}" unless ok
	end
end

desc "Do git prep to start work on a Redmine ticket"
task :start_ticket, [:ticket, :remote, :branch] => :git_setup do |t, args|
	args.with_defaults(:remote => @remote[:name])
	args.with_defaults(:branch => @next_release)
	start_at = find_start(args.branch)
	branch = "tickets/#{start_at}/#{args.ticket}"
	sh "git checkout -b #{branch} #{start_at}" do |ok, res|
		unless ok
			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}
EOS
		end
	end
    sh "git config branch.#{branch}.remote #{args.remote}" do |ok, res|
    	raise "Could not set remote: #{$?}" unless ok
	end

    sh "git config branch.#{branch}.merge refs/heads/#{branch}" do |ok, res|
    	raise "Could not configure merge: #{$?}" unless ok
	end
end

# 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}'}
	sh "git push #{arg.remote} #{branch}" do |ok, res|
		raise "Unable to push to #{arg.remote}" unless ok
	end
end

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"

    # Add info to the patches
    additional_info = "Local-branch: #{branch}\n"
    files = Dir.glob("00*.patch")
    files.each do |file|
        contents = File.read(file)
        contents.sub!(/^---$/, "#{additional_info}---")
        File.open(file, 'w') do |file_handle|
            file_handle.print contents
        end
    end

    # And then mail them out.

    # If we've got more than one patch, add --compose
    if files.length > 1
        compose = "--compose"
    else
        compose = ""
    end

    # Now send the mail.
    sh "git send-email #{compose} --no-signed-off-by-cc --suppress-from --to puppet-dev@googlegroups.com 00*.patch"

    # Finally, clean up the patches
    sh "rm 00*.patch"
end