source: tags/ms_r16q3/SOURCE_TOOLS/release/release_tool.pl

Last change on this file was 12429, checked in by westram, 10 years ago
  • jenkins seems to disable projects when repo-url vanishes
    • dropped a note for me (to remember enabling it again for arb6.1rc1)
  • Property svn:executable set to *
File size: 9.8 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6my $ARBHOME = $ENV{ARBHOME};
7die "ARBHOME has to be defined" if not defined $ARBHOME;
8die "ARBHOME has specify a directory (ARBHOME='$ARBHOME')" if not -d $ARBHOME;
9
10my %svn_info = ();
11
12sub retrieve_svn_info() {
13  %svn_info = ();
14  my $cmd = "(cd '$ARBHOME'; svn info)";
15  open(INFO,$cmd.'|') || die "failed to fork '$cmd' (Reason: $!)";
16  foreach (<INFO>) {
17    chomp;
18    if (/^Repository\sRoot:\s+/o) { $svn_info{ROOT} = $'; }
19    elsif (/^Revision:\s+/o) { $svn_info{REVISION} = $'; }
20    elsif (/^URL:\s+/o) { $svn_info{URL} = $'; }
21    # else { print "info='$_'\n"; }
22  }
23  close(INFO) || die "failed to execute '$cmd' (Reason: $!)";
24
25  if (not defined $svn_info{ROOT}) { die "Failed to detect SVN root"; }
26
27  {
28    my $rootlen = length($svn_info{ROOT});
29    my $prefix = substr($svn_info{URL},0,$rootlen);
30    my $suffix = substr($svn_info{URL},$rootlen+1);
31    if ($prefix ne $svn_info{ROOT}) {
32      die "prefix!=ROOT ('$prefix' != '".$svn_info{ROOT}."')";
33    }
34    $svn_info{SUB} = $suffix;
35  }
36
37  print "-------------------- [WC info]\n";
38  foreach (sort keys %svn_info) { print "$_='".$svn_info{$_}."'\n"; }
39  print "--------------------\n";
40}
41
42sub getArbVersion() {
43  my ($tag,$version) = (undef,undef);
44  eval {
45    my $arb_build    = $ARBHOME.'/TEMPLATES/arb_build.h';
46    my $version_info = $ARBHOME.'/SOURCE_TOOLS/version_info';
47
48    die "missing expected file '$arb_build'"    if not -f $arb_build;
49    die "missing expected file '$version_info'" if not -f $version_info;
50
51    open(BUILD,'<'.$arb_build) || die "can't read '$arb_build' (Reason: $!)";
52    foreach (<BUILD>) {
53      if (/define\s+ARB_VERSION\s+"(.*)"/o) { $tag = $1; }
54    }
55    close(BUILD);
56
57    {
58      my ($minor,$major) = (undef,undef);
59      open(VERSION,'<'.$version_info) || die "can't read '$version_info' (Reason: $!)";
60      foreach (<VERSION>) {
61        if (/^MINOR=([0-9]+)$/o) { $minor = $1; }
62        if (/^MAJOR=([0-9]+)$/o) { $major = $1; }
63      }
64      close(VERSION);
65      if (not defined $minor) { die "Failed to retrieve MINOR from $version_info"; }
66      if (not defined $major) { die "Failed to retrieve MAJOR from $version_info"; }
67      $version = "$major.$minor";
68    }
69
70    if (not defined $tag) { die "Failed to retrieve ARB_VERSION from $arb_build"; }
71    defined $version || die;
72  };
73  if ($@) {
74    die "Note: maybe you forgot to 'make all'?\n".
75      "Error while retrieving ARB version: $@";
76  }
77  return ($tag,$version);
78}
79
80sub getExisting($) {
81  my ($baseUrl) = @_;
82
83  my @existing = ();
84  my $cmd = "svn list '$baseUrl'";
85  open(LIST,$cmd.'|') || die "failed to fork '$cmd' (Reason: $!)";
86  foreach (<LIST>) {
87    chomp;
88    if (/\/$/o) { push @existing, $`; }
89    else { die "Unexpected content '$_' (received from '$cmd')"; }
90  }
91  close(LIST) || die "failed to execute '$cmd' (Reason: $!)";
92  return @existing;
93}
94
95my %known_branches = ();
96my %known_tags = ();
97
98sub branch_exists($) {
99  my ($branch) = @_;
100  if (not %known_branches) {
101    %known_branches = map { $_ => 1; } getExisting($svn_info{ROOT}.'/branches');
102  }
103  return exists $known_branches{$branch};
104}
105sub tag_exists($) {
106  my ($tag) = @_;
107  if (not %known_tags) {
108    %known_tags = map { $_ => 1; } getExisting($svn_info{ROOT}.'/tags');
109  }
110  return exists $known_tags{$tag};
111}
112
113sub trunkURL()   { return $svn_info{ROOT}.'/trunk'; }
114sub currentURL() { return $svn_info{ROOT}.'/'.$svn_info{SUB}; }
115sub branchURL($) { my ($branch) = @_; return $svn_info{ROOT}.'/branches/'.$branch; }
116sub tagURL($)    { my ($tag)    = @_; return $svn_info{ROOT}.'/tags/'.$tag; }
117
118sub expectSUB($) {
119  my ($expected) = @_;
120  my $got = $svn_info{SUB};
121  defined $got || die "SUB undefined";
122
123  if ($got ne $expected) {
124    die "Error: this is only possible in '$expected' (you are in '$got')";
125  }
126}
127
128sub denySUB($) {
129  my ($expected) = @_;
130  my $got = $svn_info{SUB};
131  defined $got || die "SUB undefined";
132
133  if ($got eq $expected) {
134    die "Error: this is NOT possible in '$expected'";
135  }
136}
137
138
139sub expectTrunk()   { expectSUB('trunk'); }
140sub expectBranch($) { my ($branch) = @_; expectSUB('branches/'.$branch); }
141sub denyBranch($)   { my ($branch) = @_; denySUB  ('branches/'.$branch); }
142
143sub tag_remove_command($$) {
144  my ($tag,$action) = @_;
145  return "svn delete '".tagURL($tag)."' -m \"[$action] delete tag '$tag'\"";
146}
147sub branch_remove_command($$) {
148  my ($branch,$action) = @_;
149  return "svn delete '".branchURL($branch)."' -m \"[$action] delete branch '$branch'\"";
150}
151sub die_due_to_tag($$) {
152  my ($tag,$desc) = @_;
153  my $remove_cmd = tag_remove_command($tag,$desc);
154  die "tag '$tag' already exists.\nTo remove that tag use\n$remove_cmd\n ";
155}
156
157sub get_branches() { branch_exists('xxx'); return sort keys %known_branches; }
158sub get_tags() { tag_exists('xxx'); return sort keys %known_tags; }
159
160sub perform($$) {
161  my ($action,$arg) = @_;
162  retrieve_svn_info();
163
164  my @commands = ();
165
166  my ($tag,$version) = getArbVersion();
167
168  if ($action eq 'branch_rc1') {
169    expectTrunk();
170    push @commands, "# check version and changelog in trunk are set correctly; see SOURCE_TOOLS/release/HOWTO.release";
171    if (branch_exists('rc')) {
172      push @commands, branch_remove_command('rc', $action);
173    }
174    push @commands, "svn copy '".trunkURL().'@'.$svn_info{REVISION}."' '".branchURL('rc')."' -m \"[$action] create rc1 for arb $version\"";
175    push @commands, "# increment version in trunk; see SOURCE_TOOLS/release/HOWTO.release";
176    push @commands, "# let jenkins build job 'ARB-rc' (check if job is enabled)";
177    push @commands, "svn switch '".branchURL('rc')."'";
178    push @commands, "make show_version";
179    push @commands, "SOURCE_TOOLS/release/release_tool.pl tag_rc";
180  }
181  elsif ($action eq 'branch_stable') {
182    expectBranch('rc');
183    if (branch_exists('stable')) {
184      push @commands, branch_remove_command('stable', $action);
185    }
186    push @commands, "svn copy '".branchURL('rc').'@'.$svn_info{REVISION}."' '".branchURL('stable')."' -m \"[$action] arb $version\"";
187    push @commands, "# let jenkins build job 'ARB-stable'";
188    push @commands, "svn switch '".branchURL('stable')."'";
189    push @commands, "make show_version";
190    push @commands, "SOURCE_TOOLS/release/release_tool.pl tag_stable";
191  }
192  elsif ($action eq 'tag_rc') {
193    expectBranch('rc');
194    if (($tag =~ /devel/oi) or ($tag =~ /rev/oi) or (not $tag =~ /^arb-/o)) { die "Invalid tag '$tag'"; }
195    if (tag_exists($tag)) { die_due_to_tag($tag, 'invalid rc'); }
196    push @commands, "svn copy '".branchURL('rc').'@'.$svn_info{REVISION}."' '".tagURL($tag)."' -m \"[$action] '$tag'\"";
197  }
198  elsif ($action eq 'tag_stable') {
199    expectBranch('stable');
200    if (($tag =~ /devel/oi) or ($tag =~ /rev/oi) or (not $tag =~ /^arb-/o)) { die "Invalid tag '$tag'"; }
201    if (tag_exists($tag)) { die_due_to_tag($tag, 'invalid release'); }
202    push @commands, "svn copy '".branchURL('stable').'@'.$svn_info{REVISION}."' '".tagURL($tag)."' -m \"[$action] release '$tag'\"";
203  }
204  elsif ($action eq 'tag_custom') {
205    if (not defined $arg) {
206      die "Expected additional argument 'tag'";
207    }
208
209    denyBranch('rc');
210    denyBranch('stable');
211    $tag = $arg; # use given arg as tagname
212
213    if (($tag =~ /dev/oi) or ($tag =~ /rev/oi)) { die "Invalid tag '$tag'"; }
214    if (tag_exists($tag)) {
215      my $remove_cmd = "svn delete '".tagURL($tag)."' -m \"[$action] delete invalid tag '$tag'\"";
216      die "tag '$tag' already exists.\nTo remove that tag use\n$remove_cmd\n ";
217    }
218    push @commands, "svn copy '".currentURL().'@'.$svn_info{REVISION}."' '".tagURL($tag)."' -m \"[$action] '$tag'\"";
219  }
220  elsif ($action eq 'rm') {
221    if (not defined $arg) {
222      die "Expected additional argument 'action'";
223    }
224    my $rm_action = $arg;
225    print "To remove branches:\n"; foreach (get_branches()) { print branch_remove_command($_,$rm_action)."\n"; }
226    print "To remove tags:\n";     foreach (get_tags())     { print tag_remove_command($_,$rm_action)."\n"; }
227  }
228  else {
229    die "Unknown action '$action'";
230  }
231
232  if ($action =~ /tag/) {
233    push @commands, "# 'Schedule Release Build' in jenkins job 'ARB-tagged-builder' to build and release the tagged version";
234  }
235
236  if (scalar(@commands)) {
237    print "-------------------- [Commands to execute for '$action']\n";
238    foreach (@commands) {
239      if ($_ =~ /^#\s/o) { $_ = $&.'[MANUALLY] '.$'; }
240      print $_."\n";
241    }
242    print "--------------------\n";
243  }
244
245  print "Note: Please check the above commands for errors,\n";
246  print "      then copy & paste to execute them.\n";
247  print "      (could be done automatically later, when everything is known to work)\n";
248}
249
250sub warnya() {
251  print "--------------------------------------------------------------------------------\n";
252  print "IMPORTANT: This script is for ARB adminstrators only and will modify ARB SVN!\n";
253  print "           Please do not misuse this script!\n";
254  print "--------------------------------------------------------------------------------\n";
255}
256
257sub show_usage($) {
258  my ($err) = @_;
259  warnya();
260  print "\n";
261  print "Usage: release_tool.pl [action [arg]]\n";
262  print "known 'action's:\n";
263  print "\n";
264  print "    branch_rc1           branch a new release candidate from 'trunk'           (uses WC-revision!)\n";
265  print "    branch_stable        branch a new release           from 'branches/rc'     (uses WC-revision!)\n";
266  print "\n";
267  print "    tag_rc               tag rc                         in   'branches/rc'     (uses WC-revision!)\n";
268  print "    tag_stable           tag release                    in   'branches/stable' (uses WC-revision!)\n";
269  print "    tag_custom tag       tag custom version             anywhere               (uses WC-revision!)\n";
270  print "\n";
271  print "    rm action            helper to get rid of unwanted branches/tags\n";
272  print "\n";
273  warnya();
274  if (defined $err) { print "\nError: $err\n"; }
275  exit 1;
276}
277
278sub main() {
279  my $args = scalar(@ARGV);
280  if ($args < 1 or $args > 2) {
281    show_usage(undef);
282  }
283  my $action = $ARGV[0];
284  my $arg    = $ARGV[1];
285  perform($action,$arg);
286}
287main();
Note: See TracBrowser for help on using the repository browser.