# Note: release description is now the release month, not just # a number # “all” does this except the last step # ╔══════════════╦════════╗ # ║ Local ║ Server ║ # ╠══════════════╬════════╣ # ║ human-1 ║ ║ # ╠══════════════╬════════╣ # ║ ║ nqp ║ # ╠══════════════╬════════╣ # ║ human-2 ║ ║ # ╠══════════════╬════════╣ # ║ ║ rakudo ║ # ╠══════════════╬════════╣ # ║ human-3 ║ ║ # ╠══════════════╬════════╣ # ║ human-upload ║ ║ # ╚══════════════╩════════╝ use File::Directory::Tree; my $THREADS = 7; my $WIKIPEDIA-NAME = %*ENV; # currently not used my $ANTIFLAP = 3; # TODO automatically use local paths if possible my $MOAR-REPO = ‘https://github.com/MoarVM/MoarVM.git’; my $MOAR-PATH = ‘moar’.IO; my $NQP-REPO = ‘https://github.com/perl6/nqp.git’; my $NQP-PATH = ‘nqp’.IO; my $RAKUDO-REPO = ‘https://github.com/rakudo/rakudo.git’; my $RAKUDO-PATH = ‘rakudo’.IO; # TODO BRANCH_MOAR makes no difference now because it uses version claimed in NQP my $version = %*ENV // (try slurp ‘VERSION’) // (sprintf “%02d.%02d”, .year, .month given Date.today); my $version-moar = %*ENV // (try slurp ‘VERSION_MOAR’ ) // $version; my $version-nqp = %*ENV // (try slurp ‘VERSION_NQP’ ) // $version; my $version-rakudo = %*ENV // (try slurp ‘VERSION_RAKUDO’) // $version; my $branch = %*ENV // (try slurp ‘BRANCH’) // ‘main’; my $branch-moar = %*ENV // (try slurp ‘BRANCH_MOAR’ ) // $branch; my $branch-nqp = %*ENV // (try slurp ‘BRANCH_NQP’ ) // $branch; my $branch-rakudo = %*ENV // (try slurp ‘BRANCH_RAKUDO’ ) // $branch; my $branch-roast = %*ENV // (try slurp ‘BRANCH_ROAST’ ) // $branch; my $jvm = ?%*ENV; # ↓ TODO this approach is LTA but it kinda works spurt ‘VERSION’, $version; spurt ‘VERSION_MOAR’, $version-moar; spurt ‘VERSION_NQP’, $version-nqp; spurt ‘VERSION_RAKUDO’, $version-rakudo; spurt ‘BRANCH’, $branch; spurt ‘BRANCH_MOAR’, $branch-moar; spurt ‘BRANCH_NQP’, $branch-nqp; spurt ‘BRANCH_RAKUDO’, $branch-rakudo; spurt ‘BRANCH_ROAST’, $branch-roast; my $temp = “temp”.IO; my $nqp-archive = “$NQP-PATH/nqp-{$version-nqp}.tar.gz”; my $rakudo-archive = “$RAKUDO-PATH/rakudo-{$version-rakudo}.tar.gz”; my $nqp-test-dir = $temp.add: ‘nqp-test’; my $rakudo-test-dir = $temp.add: ‘rakudo-test’; my @tarball-distributors = [‘2222’, ‘rakudo.org@lavm-perl6infra-1.atikon.io:public_html/downloads/’], [‘22’, ‘rakudo@www.p6c.org:public_html/downloads/’]; my @canary-distributors = ‘rakudo@www.p6c.org:public_html/downloads/’; my @months = ; task ‘foo’, { say ‘It barks!’; } task ‘all’ => ‘clean’, { # except human-upload run ; run ; run ; run ; run ; say ‘Now run 「ake human-upload」 to publish your changes’; True } task ‘all-rakudo-only’ => ‘clean’, { # TODO maybe don't runout but just depend on other tasks # You may need to *prepend* PATH modifications in bashrc run ; # just 「get-all」 instead of 「human-1」 run ; run ; run ; run ; say ‘Now run 「ake human-upload-rakudo-only」 to publish your changes’; True } ########## Aggregates ########## task ‘human-1’ => ; # TODO ensure human-1 task ‘nqp’ => ; task ‘human-2’ => ; task ‘human-2-extra’ => ; task ‘rakudo’ => ; task ‘human-3’ => ; task ‘human-upload’ => ; task ‘human-upload-rakudo-only’ => ; task ‘human-canary-upload’ => ; #task ‘release’ => , { … } ########## Misc ########## task ‘clean’, { rmtree $MOAR-PATH if $MOAR-PATH.e; rmtree $NQP-PATH if $NQP-PATH.e; rmtree $RAKUDO-PATH if $RAKUDO-PATH.e; rmtree $temp if $temp.e; unlink ‘VERSION’; unlink ‘VERSION_MOAR’; unlink ‘VERSION_NQP’; unlink ‘VERSION_RAKUDO’; unlink ‘BRANCH’; unlink ‘BRANCH_MOAR’; unlink ‘BRANCH_NQP’; unlink ‘BRANCH_RAKUDO’; unlink ‘BRANCH_ROAST’; } task ‘get-all’, { for ( $MOAR-REPO, $MOAR-PATH, $branch-moar), ( $NQP-REPO, $NQP-PATH, $branch-nqp), ($RAKUDO-REPO, $RAKUDO-PATH, $branch-rakudo) { if .[1].IO.e { run , :cwd(.[1]) } else { run , .[2], ‘--’, .[0], .[1] } } True } task ‘nqp-push-check’, { # Step ??? (nqp release guide) run :cwd($NQP-PATH), , $branch-nqp; run :cwd($NQP-PATH), , $version-nqp; True } task ‘nqp-push’, { # Step ??? (nqp release guide) run :cwd($NQP-PATH), , $branch-nqp; run :cwd($NQP-PATH), , $version-nqp; True } task ‘rakudo-push-check’, { # Step ??? (rakudo release guide) run :cwd($RAKUDO-PATH), , $branch-rakudo; run :cwd($RAKUDO-PATH), , $version-rakudo; True } task ‘rakudo-push’, { # Step ??? (rakudo release guide) run :cwd($RAKUDO-PATH), , $branch-rakudo; run :cwd($RAKUDO-PATH), , $version-rakudo; True } task ‘nqp-upload’, { # Step ❽ (nqp release guide) for @tarball-distributors { run ‘scp’, “-P{$_[0]}”, $nqp-archive, “{$nqp-archive}.asc”, “{$_[1]}/nqp/” } True } task ‘rakudo-upload’, { # Step ⓲ (rakudo release guide) for @tarball-distributors { run ‘scp’, “-P{$_[0]}”, $rakudo-archive, “{$rakudo-archive}.asc”, “{$rakudo-archive}.checksums.txt”, “{$_[1]}/rakudo/” } True } task ‘nqp-canary-upload’, { # No separate NQP canary yet #for @canary-distributors { # run ‘scp’, $nqp-archive, “$_/prerelease/nqp-prerelease.tar.gz”; # run ‘scp’, “{$nqp-archive}.asc”, “$_/prerelease/nqp-prerelease.asc”; #} True } task ‘rakudo-canary-upload’, { for @canary-distributors { run ‘scp’, $rakudo-archive, “$_/prerelease/rakudo-prerelease.tar.gz”; run ‘scp’, “{$rakudo-archive}.asc”, “$_/prerelease/rakudo-prerelease.asc”; } True } ########## NQP ########## task ‘nqp-bump-moar’, sub ($?) { # Step ❶ (nqp release guide) if $version-moar eq trim-trailing slurp “$NQP-PATH/tools/templates/MOAR_REVISION” { note “MoarVM version is already bumped to $version-moar”; return } my $check = $version-moar.contains(‘-g’) # TODO better check? ?? $version-moar # not a tag (for dry runs) !! $version-moar ~ ‘^{tag}’; if not run :cwd($MOAR-PATH), :out(Nil), :err(Nil), , $check { # TODO -- die “MoarVM tag $version-moar does not exist” } run :cwd($MOAR-PATH), :out(Nil), , $version-moar; # TODO -- my $actual-version-moar = slurp “$MOAR-PATH/VERSION”; if !$version-moar.contains(‘-g’) # custom Moar version and $version-moar.chomp ne $actual-version-moar.chomp { # TODO \n ? die “Incorrect VERSION file on $version-moar tag ($actual-version-moar)” } spurt “$NQP-PATH/tools/templates/MOAR_REVISION”, “$version-moar\n”; run , “[release] Bump MoarVM revision to $version-moar”, ‘--’, ‘tools/templates/MOAR_REVISION’, :cwd($NQP-PATH); # TODO ensure signing True } task ‘nqp-bump’, { # Step ❷ (nqp release guide) spurt “$NQP-PATH/VERSION”, “$version-nqp\n”; run , “[release] Bump VERSION to $version-nqp”, ‘--’, ‘VERSION’, :cwd($NQP-PATH); # TODO ensure signing True } sub nqp-build($path) { if $path.add(‘Makefile’).e { run :cwd($path), } run :cwd($path), , ‘--backend=moar’ ~ ($jvm ?? ‘,jvm’ !! ‘’); run :cwd($path), , $THREADS; True } sub nqp-test($path) { run , :cwd($path); run , :cwd($path) if $jvm; True } task ‘nqp-build’, { # Step ❸ (nqp release guide) nqp-build $NQP-PATH; True } task ‘nqp-test’, { # still Step ❸ (nqp release guide) nqp-test $NQP-PATH; True } task ‘nqp-post-build’ => ‘nqp-extract’, { # Step ❺ (nqp release guide) my $path = $nqp-test-dir.add: “nqp-$version-nqp”; die ‘No nqp for post-build/post-test found’ unless $path.d; nqp-build $path; True } task ‘nqp-post-test’, { # still Step ❺ (nqp release guide) my $path = $nqp-test-dir.add: “nqp-$version-nqp”; die ‘No nqp for post-build/post-test found’ unless $path.d; nqp-test $path; rmtree $nqp-test-dir if $nqp-test-dir.e; True } task ‘nqp-archive’, { # Step ❹ (nqp release guide) run :cwd($NQP-PATH), ‘make’, ‘release’, “VERSION=$version-nqp”; die ‘No tarball created’ unless $nqp-archive.IO.e; True } task ‘nqp-extract’, { rmtree $nqp-test-dir if $nqp-test-dir.e; mkdir $nqp-test-dir; run , “--directory=$nqp-test-dir”, “--file=$nqp-archive”; True } task ‘nqp-tag’, { # Step ❻ (nqp release guide) run :cwd($NQP-PATH), , ‘-m’, “Tag release $version-nqp”, $version-nqp; True } task ‘nqp-sign’, { # Step ❼ (nqp release guide) run , #`{‘--output’, $nqp-signature,} ‘--’, $nqp-archive; True } ########## Rakudo ########## # TODO ↓ kinda useless task ‘rakudo-manual-check’, { # Step ❶ (rakudo release guide) say ‘If it's not too late:’; say ‘ + Remind people of the upcoming release’; say ‘ + Invite people to update the ChangeLog file’; say ‘ + Update the ROADMAP’; say ‘’; say ‘Definitely make sure to:’; say ‘ + Check for DEPRECATED code’; say ‘ + Review the RT queue’; say ‘ + Update the release announcement draft’; say ‘’; say ‘Everything else will be done for you by this Akefile’; # TODO more? } task ‘rakudo-leap-seconds’, { # Step ❷ (rakudo release guide) ; # TODO } task ‘rakudo-changelog’, { # Step ❸ (rakudo release guide) ; # TODO nothing here, just ask the bot? } task ‘rakudo-announcement’, { # Step ❹ (rakudo release guide) my $announcement-path = “$RAKUDO-PATH/docs/announce/$version-rakudo.md”; die ‘No release announcement found’ if not $announcement-path.IO.e; if $version-rakudo ~~ /$=[\d**4] ‘.’ $=[\d**2]/ { die ‘Confused. Rakudo version is weird’ } my $year = ~$; my $month = @months[$ + 1]; my $text = slurp $announcement-path; if $text !~~ /^‘# Announce: Rakudo Perl 6 compiler, Release #’$=\d+‘ ($version-rakudo)’/ { die ‘Unexpected format of the first line’ } my $release-id = +$; if $text !~~ /^^「On behalf of the Rakudo development team, I’m very happy to announce the」\n $=\w+ ‘ ’ $=\d+ ‘ release of Rakudo Perl 6 #’ $=\d+/ { die ‘Cannot find ‘happy to announce’ line’; } die ‘Incorrect month mentioned’ if $month ne $; die ‘Incorrect year mentioned’ if $year ≠ $; die ‘Incorrect release id mentioned’ if $release-id ≠ $; “The next release of Rakudo (#{$release-id + 1}), is tentatively scheduled for 2017-08-19.” } task ‘rakudo-release-guide’, { # Step ❺ (rakudo release guide) ; # TODO ? } task ‘rakudo-ensure-moarvm’, { # Step ❻ (rakudo release guide) ; # TODO # Practically this is not needed because # NQP stuff won't proceed without MoarVM tag } task ‘rakudo-nqp’, { # Step ❼ (rakudo release guide) ;# TODO just depend on nqp targets? } task ‘rakudo-bump-nqp’, sub ($?) { # Step ❽ (rakudo release guide) if $version-nqp eq trim-trailing slurp “$RAKUDO-PATH/tools/templates/NQP_REVISION” { note “NQP version is already bumped to $version-nqp”; return } my $check = $version-nqp.contains(‘-g’) # TODO better check? ?? $version-nqp # not a tag (for dry runs) !! $version-nqp ~ ‘^{tag}’; if not run :cwd($NQP-PATH), :out(Nil), :err(Nil), , $check { # TODO -- die “NQP tag $version-nqp does not exist” } run :cwd($NQP-PATH), :out(Nil), ‘git’, ‘checkout’, $version-nqp; # TODO -- my $actual-version-nqp = slurp “$NQP-PATH/VERSION”; if $version-nqp.chomp ne $actual-version-nqp.chomp { # TODO \n ? die “Incorrect VERSION file on $version-nqp tag ($actual-version-nqp)” } spurt “$RAKUDO-PATH/tools/templates/NQP_REVISION”, “$version-nqp\n”; run , “[release] Bump NQP revision to $version-nqp”, ‘--’, ‘tools/templates/NQP_REVISION’, :cwd($RAKUDO-PATH); # TODO ensure signing True } task ‘rakudo-bump’, { # Step ❾ (rakudo release guide) spurt “$RAKUDO-PATH/VERSION”, “$version-rakudo\n”; run , “[release] Bump VERSION to $version-rakudo”, ‘--’, ‘VERSION’, :cwd($RAKUDO-PATH); # TODO ensure signing True } # Step ❿ (rakudo release guide) task ‘rakudo-status’, { ; # This step is useless, move on } sub rakudo-build($path) { if $path.add(‘Makefile’).e { run :cwd($path), ; } run :cwd($path), , $branch-nqp, $NQP-PATH.absolute, ‘nqp’; run :cwd($path), , ‘--backend=moar’ ~ ($jvm ?? ‘,jvm’ !! ‘’); run :cwd($path), , $THREADS; run :cwd($path), ; # TODO install? Really? True } sub rakudo-test($path, :$checkout-roast=True) { my %env = %*ENV; %env = $THREADS; antiflap-run :cwd($path), :%env, ; if $checkout-roast { run :cwd($path), :%env, ; # ensure roast checkout run :cwd($path.add: ‘t/spec’), , $branch-roast; } antiflap-run :cwd($path), :%env, ; True } task ‘rakudo-build’, { # Step ⓫ (rakudo release guide) rakudo-build $RAKUDO-PATH } task ‘rakudo-test’, { # still Step # Step ⓫ (rakudo release guide) rakudo-test $RAKUDO-PATH } task ‘rakudo-post-build’ => ‘rakudo-extract’, { # Step ⓯ (rakudo release guide) my $path = $rakudo-test-dir.add: “rakudo-$version-rakudo”; die ‘No rakudo for post-build/post-test found’ unless $path.d; rakudo-build $path; True } task ‘rakudo-post-test’, { # still Step ⓯ (rakudo release guide) my $path = $rakudo-test-dir.add: “rakudo-$version-rakudo”; die ‘No rakudo for post-build/post-test found’ unless $path.d; rakudo-test $path, :!checkout-roast; rmtree $rakudo-test-dir if $rakudo-test-dir.e; True } task ‘rakudo-archive’, { # Step ⓮ (rakudo release guide) run :cwd($RAKUDO-PATH), , “VERSION=$version-rakudo”; die ‘No tarball created’ unless $rakudo-archive.IO.e; True } task ‘rakudo-extract’, { rmtree $rakudo-test-dir if $rakudo-test-dir.e; mkdir $rakudo-test-dir; run , “--directory=$rakudo-test-dir”, “--file=$rakudo-archive”; True } sub custom-env() { my %env = %*ENV; # TODO does it have to be absolute? %env = $RAKUDO-PATH.add(‘install/bin’).absolute ~ ‘:’ ~ %env; %env = $RAKUDO-PATH.add(‘install/share/perl6/site/bin’).absolute ~ ‘:’ ~ %env; %env = $THREADS; return %env; } task ‘rakudo-inline-perl5’, { # Step ⓬ (rakudo release guide) run :cwd($RAKUDO-PATH), , ‘https://github.com/ugexe/zef’; my %env = custom-env; run :cwd($RAKUDO-PATH.add: ‘zef’), :%env, ; run :cwd($RAKUDO-PATH), :%env, ; True } task ‘rakudo-stress’, { # Step ⓭ (rakudo release guide) # TODO we run rakudo-test and then rakudo-stress (rakudo-test not needed) my %env = custom-env; run :cwd($RAKUDO-PATH.add: ‘t/spec’), , $branch-roast; antiflap-run :cwd($RAKUDO-PATH), :%env, ; # test latest language spec True } task ‘rakudo-stress-errata’, { # Step ⓭ (rakudo release guide) # TODO we run rakudo-test and then rakudo-stress (rakudo-test not needed) note ‘Ignore missing file warnings:’; my %env = custom-env; run :cwd($RAKUDO-PATH.add: ‘t/spec’), ; antiflap-run :cwd($RAKUDO-PATH), :%env, ; # test stable language spec run :cwd($RAKUDO-PATH.add: ‘t/spec’), ; antiflap-run :cwd($RAKUDO-PATH), :%env, ; # test stable language spec True } task ‘rakudo-tag’, { # Step ⓰ (rakudo release guide) run :cwd($RAKUDO-PATH), , ‘-m’, “Tag release $version-rakudo”, $version-rakudo; True } task ‘rakudo-sign’, { # Step ⓱ (rakudo release guide) my $sig-file = $rakudo-archive ~ ‘.checksums.txt’; my $unsigned-sig-file = $sig-file ~ '.unsigned'; run , $rakudo-archive; for -> $tool { my $proc = run $tool, ‘--tag’, $rakudo-archive, :out; my $sig = $proc.out.slurp: :close; $unsigned-sig-file.IO.spurt: $sig, :append; } run , $sig-file, ‘--’, $unsigned-sig-file; $unsigned-sig-file.IO.unlink; True } task ‘email’, { # Step ⓳ (rakudo release guide) ; # TODO } task ‘wikipedia’, { # Step ⓴ (rakudo release guide) #`「 use Inline::Perl5; use MediaWiki::Bot:from; #my $pass = run(:out, ‘pass’, ‘Wikipedia’).out.lines.head; my $pass = ‘…’; # TODO my $x = %( agent => ‘MediaWiki::Bot 3.0.0 (https://github.com/perl6/whateverable)’, assert => ‘user’, protocol => ‘https’, host => ‘en.wikipedia.org’, path => ‘w’, operator => $WIKIPEDIA-NAME, login_data => { username => $WIKIPEDIA-NAME ~ ‘@Releasable’, password => $pass, }, ); my $announce-io = $RAKUDO-PATH.add(“docs/announce/$version-rakudo.md”); die ‘Weird announcement’ unless slurp($announce-io).lines.head ~~ /Release \s (‘#’\d+)/; my $release-id = ~$0; my $date = run(‘git’, ‘log’, ‘-1’, ‘--format=%ai’, $version-rakudo, :out, :cwd($RAKUDO-PATH)).out.words.head; my $bot = MediaWiki::Bot.new: $x; my $text = $bot.get_text(‘Rakudo Perl 6’, Nil, 0); # section 0 #spurt ‘before’, $text; if not $text ~~ s/(‘| latest release version’ \s* ‘=’ \s* ‘’) ‘#’\d+(‘ "’) 2017.08(\N+)(‘|accessdate=’)\d\d\d\d‘-’\d\d‘-’\d\d /$0$release-id$1$version-rakudo$2$3$date/ { die ‘Can't parse the wikitext (latest release version)’ } my $pipe-date = $date.trans: ‘-’ => ‘|’; if not $text ~~ s/(‘| latest release date’ \s* ‘=’ \s* ‘{{Start date and age|’) \d\d\d\d‘|’\d\d‘|’\d\d /$0$pipe-date/ { die ‘Can't parse the wikitext (latest release date)’ } spurt ‘after’, $text; #my $x-edit = ; $bot.edit: %( page => ‘Rakudo Perl 6’, text => $text, summary => ‘Update latest release’, section => 0, ) 」 True } task ‘rakudo-done’, { # Step ⓴❶ (rakudo release guide) say ‘You're done! Celebrate with the appropriate amount of fun.’ } sub antiflap-run(|c) { for ^$ANTIFLAP { run |c; CATCH { default { next } } NEXT { note ‘Let's try again?’ } return } note ‘Well, maybe not…’; $!.rethrow } task ‘wait’, { # say ‘⚠⚠⚠ PUBLISHING ⚠⚠⚠’; note ‘⚠⚠⚠ PUBLISHING ⚠⚠⚠’; sleep 5; True } # vim: expandtab shiftwidth=4 ft=perl6