(List (Com {[LIT_CHARS set]} {[LIT_CHARS -eu]}) (Com {[LIT_OTHER ":"]} {[VarSub RELEASE_REPOSITORIES test_op=VS_TEST_COLON_EQUALS {[DQ [LIT_CHARS "git@github.com:bazelbuild/bazel"]]}]}) (Com {[LIT_OTHER ":"]} {[VarSub MASTER_REPOSITORIES test_op=VS_TEST_COLON_EQUALS {[DQ [LIT_CHARS "https://bazel.googlesource.com/bazel"]]}]}) (Com {[LIT_OTHER ":"]} {[VarSub EDITOR test_op=VS_TEST_EQUALS {[LIT_CHARS vi]}]}) (Com {[LIT_OTHER ":"]} {[VarSub RELEASE_AUTHOR test_op=VS_TEST_EQUALS {[DQ [LIT_CHARS "Bazel Release System "]]}]}) (= scope= flags=0 words=[] bindings=[('SCRIPT_DIR', {[ComSub (AndOr OP_AND_IF (Com {[LIT_CHARS cd]} {[DQ [ComSub (Com {[LIT_CHARS dirname]} {[DQ [VarSub BASH_SOURCE bracket_op=(Index {A Atom NODE_ARITH_WORD {[AS_NUM_LITERAL 0]}})]]})]]}) (Com {[LIT_CHARS pwd]}) )]})]) (Com {[LIT_CHARS source]} {[VarSub SCRIPT_DIR] [LIT_CHARS /relnotes.sh]}) (Com {[LIT_CHARS source]} {[VarSub SCRIPT_DIR] [LIT_CHARS /common.sh]}) (= scope= flags=0 words=[] bindings=[('RELEASE_NOTE_MESSAGE', {[SQ ]})]) (FunctionDef set_release_name [] (List (AndOr OP_OR_IF (Com {[LIT_CHARS git]} {[LIT_CHARS notes]} {[LIT_CHARS --ref] [LIT_OTHER "="] [LIT_CHARS release]} {[LIT_CHARS remove]} < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 2), > ) (Com {[LIT_CHARS true]}) ) (AndOr OP_OR_IF (Com {[LIT_CHARS git]} {[LIT_CHARS notes]} {[LIT_CHARS --ref] [LIT_OTHER "="] [LIT_CHARS release-candidate]} {[LIT_CHARS remove]} < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 2), > ) (Com {[LIT_CHARS true]}) ) (Com {[LIT_CHARS git]} {[LIT_CHARS notes]} {[LIT_CHARS --ref] [LIT_OTHER "="] [LIT_CHARS release]} {[LIT_CHARS append]} {[LIT_CHARS -m]} {[DQ [VarSub 1]]}) (= scope= flags=0 words=[] bindings=[('relname', {[DQ [VarSub 1]]})]) (If (DBracket {B! {B1 UNARY_STRING_z {[DQ [VarSub 2 test_op=VS_TEST_HYPHEN {}]]}}}) (List (Com {[LIT_CHARS git]} {[LIT_CHARS notes]} {[LIT_CHARS --ref] [LIT_OTHER "="] [LIT_CHARS release-candidate]} {[LIT_CHARS append]} {[LIT_CHARS -m]} {[DQ [VarSub 2]]}) (= scope= flags=0 words=[] bindings=[('relname', {[DQ [VarSub relname][LIT_CHARS RC][VarSub 2]]})]) ) ) (Com {[LIT_CHARS echo]} {[DQ [VarSub relname]]}) ) ) (FunctionDef trim_empty_lines [] (List (= scope= flags=0 words=[] bindings=[('f', {[DQ [ComSub (Com {[LIT_CHARS echo]} {[SQ ]})]]})]) (Pipeline (Com {[LIT_CHARS tr]} {[SQ ]} {[SQ ]}) (Com {[LIT_CHARS sed]} {[LIT_CHARS -e]} {[DQ [LIT_CHARS "s/^"][VarSub f][LIT_CHARS "*//"]]} {[LIT_CHARS -e]} {[DQ [LIT_CHARS s/][VarSub f][LIT_CHARS "*"][LIT_OTHER "$"][LIT_CHARS //]]}) (Com {[LIT_CHARS tr]} {[SQ ]} {[SQ ]}) ) ) ) (FunctionDef release_note_editor [] (List (= scope= flags=0 words=[] bindings=[('tmpfile', {[DQ [VarSub 1]]})]) (= scope= flags=0 words=[] bindings=[('origin_branch', {[DQ [VarSub 2]]})]) (= scope= flags=0 words=[] bindings=[('branch_name', {[DQ [VarSub 3 test_op=VS_TEST_HYPHEN {}]]})]) (AndOr OP_OR_IF (Com {[VarSub EDITOR]} {[VarSub tmpfile]}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Editor failed, cancelling release creation..."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[LIT_CHARS -q]} {[VarSub origin_branch]} < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (AndOr OP_OR_IF (Com {[LIT_OTHER "["]} {[LIT_CHARS -z]} {[DQ [VarSub branch_name]]} {[LIT_OTHER "]"]}) (Com {[LIT_CHARS git]} {[LIT_CHARS branch]} {[LIT_CHARS -D]} {[VarSub branch_name]}) ) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (= scope= flags=0 words=[] bindings=[('relnotes', {[DQ [ComSub (Pipeline (Com {[LIT_CHARS cat]} {[VarSub tmpfile]}) (Com {[LIT_CHARS grep]} {[LIT_CHARS -v]} {[SQ ]}) (Com {[LIT_CHARS trim_empty_lines]}) )]]})]) (If (Com {[LIT_OTHER "["]} {[LIT_CHARS -z]} {[DQ [VarSub relnotes]]} {[LIT_OTHER "]"]}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Release notes are empty, cancelling release creation..."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[LIT_CHARS -q]} {[VarSub origin_branch]} < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (AndOr OP_OR_IF (Com {[LIT_OTHER "["]} {[LIT_CHARS -z]} {[DQ [VarSub branch_name]]} {[LIT_OTHER "]"]}) (Com {[LIT_CHARS git]} {[LIT_CHARS branch]} {[LIT_CHARS -D]} {[VarSub branch_name]}) ) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (Com {[LIT_CHARS echo]} {[DQ [VarSub relnotes]]} < (FilenameRedirectNode filename={[VarSub tmpfile]} "> 1), > ) ) ) (FunctionDef create_release_commit [] (List (= scope= flags=0 words=[] bindings=[('release_title', {[DQ [VarSub 1]]})]) (= scope= flags=0 words=[] bindings=[('release_name', {[DQ [VarSub 2]]})]) (= scope= flags=0 words=[] bindings=[('relnotes', {[DQ [VarSub 3]]})]) (= scope= flags=0 words=[] bindings=[('tmpfile', {[DQ [VarSub 4]]})]) (= scope= flags=0 words=[] bindings=[('baseline', {[DQ [VarSub 5]]})]) (Com {[LIT_CHARS shift]} {[LIT_CHARS 5]}) (= scope= flags=0 words=[] bindings=[('cherrypicks', {[VarSub @]})]) (= scope= flags=0 words=[] bindings=[('changelog_path', {[DQ [VarSub PWD][LIT_CHARS /CHANGELOG.md]]})]) (= scope= flags=0 words=[] bindings=[('version_info', {[ComSub (Com {[LIT_CHARS create_revision_information]} {[VarSub baseline]} {[VarSub cherrypicks]})]})]) (Com {[LIT_CHARS cat]} < (FilenameRedirectNode filename={[VarSub tmpfile]} "> 1), (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [LIT_CHARS "## "][VarSub release_title][LIT_CHARS "\n"][LIT_CHARS "\n"]]} 0), > ) (If (Com {[LIT_OTHER "["]} {[LIT_CHARS -n]} {[DQ [VarSub version_info]]} {[LIT_OTHER "]"]}) (Com {[LIT_CHARS cat]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [\ LIT_ESCAPED_CHAR "\\`"][\ LIT_ESCAPED_CHAR "\\`"][\ LIT_ESCAPED_CHAR "\\`"][LIT_CHARS "\n"][VarSub version_info][LIT_CHARS "\n"][\ LIT_ESCAPED_CHAR "\\`"][\ LIT_ESCAPED_CHAR "\\`"][\ LIT_ESCAPED_CHAR "\\`"][LIT_CHARS "\n"]]} 0), > ) ) (Com {[LIT_CHARS cat]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [LIT_CHARS "\n"][VarSub relnotes][LIT_CHARS "\n"]]} 0), > ) (If (Com {[LIT_OTHER "["]} {[LIT_CHARS -f]} {[DQ [VarSub changelog_path]]} {[LIT_OTHER "]"]}) (List (Com {[LIT_CHARS echo]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), > ) (Com {[LIT_CHARS cat]} {[DQ [VarSub changelog_path]]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), > ) ) ) (Com {[LIT_CHARS cat]} {[VarSub tmpfile]} < (FilenameRedirectNode filename={[VarSub changelog_path]} "> 1), > ) (Com {[LIT_CHARS git]} {[LIT_CHARS add]} {[VarSub changelog_path]}) (Com {[LIT_CHARS cat]} < (FilenameRedirectNode filename={[VarSub tmpfile]} "> 1), (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [VarSub release_title][LIT_CHARS "\n"][LIT_CHARS "\n"][VarSub version_info][LIT_CHARS "\n"][LIT_CHARS "\n"][VarSub relnotes][LIT_CHARS "\n"]]} 0), > ) (Com {[LIT_CHARS git]} {[LIT_CHARS commit]} {[LIT_CHARS --no-verify]} {[LIT_CHARS -F]} {[VarSub tmpfile]} {[LIT_CHARS --no-edit]} {[LIT_CHARS --author]} {[DQ [VarSub RELEASE_AUTHOR]]}) ) ) (FunctionDef apply_cherry_picks [] (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Applying cherry-picks"]]}) (For i [{[VarSub @]}]) (List (= scope= flags=0 words=[] bindings=[('previous_head', {[DQ [ComSub (Com {[LIT_CHARS git]} {[LIT_CHARS rev-parse]} {[LIT_CHARS HEAD]})]]})]) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " Cherry-picking "][VarSub i]]}) (AndOr OP_OR_IF (Com {[LIT_CHARS git]} {[LIT_CHARS cherry-pick]} {[VarSub i]} < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Failed to cherry-pick "][VarSub i][LIT_CHARS ". please resolve the conflict and exit."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " Use 'git cherry-pick --abort; exit' to abort the cherry-picks."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " Use 'git cherry-pick --continue; exit' to resolve the conflict."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS bash]}) (If (Com {[LIT_OTHER "["]} {[DQ [ComSub (Com {[LIT_CHARS git]} {[LIT_CHARS rev-parse]} {[LIT_CHARS HEAD]})]]} {[LIT_OTHER "="] [LIT_OTHER "="]} {[DQ [VarSub previous_head]]} {[LIT_OTHER "]"]}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Cherry-pick aborted, aborting the whole command..."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS return]} {[LIT_CHARS 1]}) ) ) ) ) ) ) (Com {[LIT_CHARS return]} {[LIT_CHARS 0]}) ) ) (FunctionDef create_release [] (List (= scope= flags=0 words=[] bindings=[('release_name', {[DQ [VarSub 1]]})]) (= scope= flags=0 words=[] bindings=[('baseline', {[DQ [VarSub 2]]})]) (Com {[LIT_CHARS shift]} {[LIT_CHARS 2]}) (= scope= flags=0 words=[] bindings=[('origin_branch', {[ComSub (Com {[LIT_CHARS git_get_branch]})]})]) (= scope= flags=0 words=[] bindings=[('branch_name', {[DQ [LIT_CHARS release-][VarSub release_name]]})]) (= scope= flags=0 words=[] bindings=[('release_title', {[DQ [LIT_CHARS "Release "][VarSub release_name][LIT_CHARS " ("][ComSub (Com {[LIT_CHARS date]} {[LIT_OTHER "+"] [LIT_OTHER "%"] [LIT_CHARS Y-] [LIT_OTHER "%"] [LIT_CHARS m-] [LIT_OTHER "%"] [LIT_CHARS d]})][LIT_CHARS ")"]]})]) (= scope= flags=0 words=[] bindings=[('tmpfile', {[ComSub (Com {[LIT_CHARS mktemp]} {[VarSub TMPDIR test_op=VS_TEST_COLON_HYPHEN {[LIT_SLASH /] [LIT_CHARS tmp]}] [LIT_CHARS /relnotes-XXXXXXXX]})]})]) (= scope= flags=0 words=[] bindings=[('tmpfile2', {[ComSub (Com {[LIT_CHARS mktemp]} {[VarSub TMPDIR test_op=VS_TEST_COLON_HYPHEN {[LIT_SLASH /] [LIT_CHARS tmp]}] [LIT_CHARS /relnotes-XXXXXXXX]})]})]) (Com {[LIT_CHARS trap]} {[SQ ]} {[LIT_CHARS EXIT]}) (= scope= flags=0 words=[] bindings=[('rc', {[LIT_CHARS 1]})]) (If (Com {[LIT_OTHER "["]} {[LIT_CHARS -n]} {[DQ [ComSub (Com {[LIT_CHARS git]} {[LIT_CHARS branch]} {[LIT_CHARS --list]} {[LIT_CHARS --column]} {[VarSub branch_name]})]]} {[LIT_OTHER "]"]}) (= scope= flags=0 words=[] bindings=[('rc', {[ArithSub {A2 AS_OP_PLUS {A Atom NODE_ARITH_WORD {[ComSub (Com {[LIT_CHARS get_release_candidate]} {[DQ [VarSub branch_name]]})]}} {A Atom NODE_ARITH_WORD {[AS_NUM_LITERAL 1]}}}]})]) ) (AndOr OP_OR_IF (Com {[LIT_CHARS git]} {[LIT_CHARS show]} {[LIT_CHARS master] [LIT_OTHER ":"] [LIT_CHARS CHANGELOG.md]} < (FilenameRedirectNode filename={[VarSub tmpfile2]} "> 1), (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 2), > ) (Com {[LIT_CHARS echo]} < (FilenameRedirectNode filename={[VarSub tmpfile2]} "> 1), > ) ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Creating new release branch "][VarSub branch_name][LIT_CHARS " for release "][VarSub release_name]]}) (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[LIT_CHARS -B]} {[VarSub branch_name]} {[VarSub baseline]}) (AndOr OP_OR_IF (Com {[LIT_CHARS apply_cherry_picks]} {[VarSub @]}) (List (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[VarSub origin_branch]}) (Com {[LIT_CHARS git]} {[LIT_CHARS branch]} {[LIT_CHARS -D]} {[VarSub branch_name]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Creating release notes"]]}) (Com {[LIT_CHARS echo]} {[DQ [VarSub RELEASE_NOTE_MESSAGE]]} < (FilenameRedirectNode filename={[VarSub tmpfile]} "> 1), > ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "# "][VarSub release_title]]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), > ) (Com {[LIT_CHARS echo]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), > ) (Com {[LIT_CHARS create_release_notes]} {[DQ [VarSub tmpfile2]]} < (FilenameRedirectNode filename={[VarSub tmpfile]} >"> 1), > ) (Com {[LIT_CHARS release_note_editor]} {[VarSub tmpfile]} {[DQ [VarSub origin_branch]]} {[DQ [VarSub branch_name]]}) (= scope= flags=0 words=[] bindings=[('relnotes', {[DQ [ComSub (Com {[LIT_CHARS cat]} {[VarSub tmpfile]})]]})]) (Com {[LIT_CHARS create_release_commit]} {[DQ [VarSub release_title]]} {[DQ [VarSub release_name]]} {[DQ [VarSub relnotes]]} {[DQ [VarSub tmpfile]]} {[DQ [VarSub baseline]]} {[VarSub @]}) (= scope= flags=0 words=[] bindings=[('release_name', {[ComSub (Com {[LIT_CHARS set_release_name]} {[DQ [VarSub release_name]]} {[DQ [VarSub rc]]})]})]) (Fork (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[VarSub origin_branch]}) ) (Com < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Created "][VarSub release_name][LIT_CHARS " on branch "][VarSub branch_name][LIT_CHARS .]]}) (Com {[LIT_CHARS rm]} {[LIT_CHARS -f]} {[VarSub tmpfile]} {[VarSub tmpfile2]}) (Com {[LIT_CHARS trap]} {[LIT_CHARS -]} {[LIT_CHARS EXIT]}) ) ) (FunctionDef push_release_candidate [] (List (= scope= flags=0 words=[] bindings=[('branch', {[DQ [ComSub (Com {[LIT_CHARS get_release_branch]})]]})]) (For repo [{[VarSub RELEASE_REPOSITORIES]}]) (List (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[LIT_CHARS -f]} {[VarSub repo]} {[LIT_OTHER "+"] [VarSub branch]}) (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[LIT_CHARS -f]} {[VarSub repo]} {[LIT_OTHER "+"] [LIT_CHARS refs/notes/release]}) (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[LIT_CHARS -f]} {[VarSub repo]} {[LIT_OTHER "+"] [LIT_CHARS refs/notes/release-candidate]}) ) ) ) ) (FunctionDef cleanup_branches [] (List (= scope= flags=0 words=[] bindings=[('tag_name', {[VarSub 1]})]) (= scope= flags=0 words=[{[LIT_CHARS i]}] bindings=[]) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Destroying the release branches for release "][VarSub tag_name]]}) (Fork (Com {[LIT_CHARS git]} {[LIT_CHARS branch]} {[LIT_CHARS -D]} {[LIT_CHARS release-] [VarSub tag_name]}) ) (AndOr OP_OR_IF (Com < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (Com {[LIT_CHARS true]}) ) (For i [{[VarSub RELEASE_REPOSITORIES]}]) (List (Fork (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[LIT_CHARS -f]} {[VarSub i]} {[LIT_OTHER ":"] [LIT_CHARS release-] [VarSub tag_name]}) ) (AndOr OP_OR_IF (Com < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (Com {[LIT_CHARS true]}) ) ) ) ) ) (FunctionDef do_release [] (List (= scope= flags=0 words=[] bindings=[('branch', {[ComSub (Com {[LIT_CHARS get_release_branch]})]})]) (= scope= flags=0 words=[] bindings=[('tag_name', {[ComSub (Com {[LIT_CHARS get_release_name]})]})]) (Com {[LIT_CHARS echo]} {[LIT_CHARS -n]} {[DQ [LIT_CHARS "You are about to release branch "][VarSub branch][LIT_CHARS " in tag "][VarSub tag_name][LIT_CHARS ", confirm? [y/N] "]]}) (Com {[LIT_CHARS read]} {[LIT_CHARS answer]}) (If (Com {[LIT_OTHER "["]} {[DQ [VarSub answer]]} {[LIT_OTHER "="]} {[DQ [LIT_CHARS y]]} {[LIT_CHARS -o]} {[DQ [VarSub answer]]} {[LIT_OTHER "="]} {[DQ [LIT_CHARS Y]]} {[LIT_OTHER "]"]}) (List (Com {[LIT_CHARS set_release_name]} {[DQ [VarSub tag_name]]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Creating the tag"]]}) (Com {[LIT_CHARS git]} {[LIT_CHARS tag]} {[VarSub tag_name]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Cherry-picking CHANGELOG.md modification into master"]]}) (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[LIT_CHARS master]}) (Com {[LIT_CHARS git]} {[LIT_CHARS pull]} {[LIT_CHARS --rebase]} {[ComSub (Pipeline (Com {[LIT_CHARS echo]} {[DQ [VarSub MASTER_REPOSITORIES]]}) (Com {[LIT_CHARS cut]} {[LIT_CHARS -d]} {[DQ [LIT_CHARS " "]]} {[LIT_CHARS -f]} {[LIT_CHARS 1]}) )]} {[LIT_CHARS master]}) (= scope= flags=0 words=[] bindings=[('changelog_path', {[DQ [VarSub PWD][LIT_CHARS /CHANGELOG.md]]})]) (Com {[LIT_CHARS git]} {[LIT_CHARS show]} {[VarSub branch] [LIT_OTHER ":"] [LIT_CHARS CHANGELOG.md]} < (FilenameRedirectNode filename={[VarSub changelog_path]} "> 1), > ) (= scope= flags=0 words=[] bindings=[('tmpfile', {[ComSub (Com {[LIT_CHARS mktemp]} {[VarSub TMPDIR test_op=VS_TEST_COLON_HYPHEN {[LIT_SLASH /] [LIT_CHARS tmp]}] [LIT_CHARS /relnotes-XXXXXXXX]})]})]) (Com {[LIT_CHARS trap]} {[SQ ]} {[LIT_CHARS EXIT]}) (Com {[LIT_CHARS git_commit_msg]} {[VarSub branch]} < (FilenameRedirectNode filename={[VarSub tmpfile]} "> 1), > ) (Com {[LIT_CHARS git]} {[LIT_CHARS add]} {[VarSub changelog_path]}) (Com {[LIT_CHARS git]} {[LIT_CHARS commit]} {[LIT_CHARS --no-verify]} {[LIT_CHARS -F]} {[VarSub tmpfile]} {[LIT_CHARS --no-edit]} {[LIT_CHARS --author]} {[DQ [VarSub RELEASE_AUTHOR]]}) (Com {[LIT_CHARS rm]} {[LIT_CHARS -f]} {[VarSub tmpfile]}) (Com {[LIT_CHARS trap]} {[LIT_CHARS -]} {[LIT_CHARS EXIT]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Pushing the change to remote repositories"]]}) (For i [{[VarSub MASTER_REPOSITORIES]}]) (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[VarSub i]} {[LIT_OTHER "+"] [LIT_CHARS master]}) ) (For i [{[VarSub RELEASE_REPOSITORIES]}]) (List (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[VarSub i]} {[LIT_OTHER "+"] [LIT_CHARS refs/tags/] [VarSub tag_name]}) (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[VarSub i]} {[LIT_OTHER "+"] [LIT_CHARS refs/notes/release-candidate]}) (Com {[LIT_CHARS git]} {[LIT_CHARS push]} {[VarSub i]} {[LIT_OTHER "+"] [LIT_CHARS refs/notes/release]}) ) ) (Com {[LIT_CHARS cleanup_branches]} {[VarSub tag_name]}) ) ) ) ) (FunctionDef abandon_release [] (List (= scope= flags=0 words=[] bindings=[('branch_info', {[ComSub (Com {[LIT_CHARS get_release_branch]})]})]) (= scope= flags=0 words=[] bindings=[('tag_name', {[ComSub (Com {[LIT_CHARS get_release_name]})]})]) (Com {[LIT_CHARS echo]} {[LIT_CHARS -n]} {[DQ [LIT_CHARS "You are about to abandon release "][VarSub tag_name][LIT_CHARS ", confirm? [y/N] "]]}) (Com {[LIT_CHARS read]} {[LIT_CHARS answer]}) (If (Com {[LIT_OTHER "["]} {[DQ [VarSub answer]]} {[LIT_OTHER "="]} {[DQ [LIT_CHARS y]]} {[LIT_CHARS -o]} {[DQ [VarSub answer]]} {[LIT_OTHER "="]} {[DQ [LIT_CHARS Y]]} {[LIT_OTHER "]"]}) (List (Com {[LIT_CHARS git]} {[LIT_CHARS checkout]} {[LIT_CHARS -q]} {[LIT_CHARS master]} < (FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 1), > ) (Com {[LIT_CHARS cleanup_branches]} {[VarSub tag_name]}) ) ) ) ) (FunctionDef usage [] (List (Com {[LIT_CHARS cat]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [LIT_CHARS "Usage: "][VarSub 1][LIT_CHARS " command [arguments]\n"][LIT_CHARS "Available commands are:\n"][LIT_CHARS " - create RELEASE_NAME BASELINE [COMMIT1 ... COMMITN]: creates a new\n"][LIT_CHARS " release branch for release named RELEASE_NAME, cutting it at\n"][LIT_CHARS " the commit BASELINE and cherry-picking COMMIT1 ... COMMITN.\n"][LIT_CHARS " - push: push the current release branch to release repositories.\n"][LIT_CHARS " - release: do the actual release of the current release branch.\n"][LIT_CHARS " - abandon: abandon the current release branch.\n"][LIT_CHARS "\n"][LIT_CHARS "The typical workflow for the release manager is:\n"][LIT_CHARS "1. Create the release branch using the decided name for the release\n"][LIT_CHARS " (usually a version number). The BASELINE is generally a baseline\n"][LIT_CHARS " that has been tested extensively including inside Google.\n"][LIT_CHARS "2. Push to the repository and wait for the continuous integration\n"][LIT_CHARS " to rebuild and deploy the various artifacts and send the annoucement\n"][LIT_CHARS " mails about a new release candidate being available.\n"][LIT_CHARS "3. If necessary, creates a new release branch with the same name to\n"][LIT_CHARS " address return from the users and go back to 2.\n"][LIT_CHARS "4. Either abandon or release the branch depending on if too much\n"][LIT_CHARS " problems are reported or if the release is considered viable. The\n"][LIT_CHARS " CI system should then rebuild from the tag and deploy the artifact\n"][LIT_CHARS " to GitHub and sends the announcement mails about the new release.\n"]]} 0), > ) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (AndOr OP_OR_IF (Com {[LIT_CHARS git]} {[LIT_CHARS diff-index]} {[LIT_CHARS --quiet]} {[LIT_CHARS HEAD]} {[LIT_CHARS --]}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "There are pending changes in this git repository."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "Please commit or stash them before using that script."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (AndOr OP_OR_IF (Com {[LIT_OTHER "["]} {[DQ [ComSub (Com {[LIT_CHARS git]} {[LIT_CHARS rev-parse]} {[LIT_CHARS --show-toplevel]})]]} {[LIT_OTHER "="] [LIT_OTHER "="]} {[DQ [VarSub PWD]]} {[LIT_OTHER "]"]}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "You should run this script from the root of the git repository."]]} < (DescriptorRedirectNode target={[LIT_CHARS 2]} &"> 1), > ) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (= scope= flags=0 words=[] bindings=[('progname', {[VarSub 0]})]) (= scope= flags=0 words=[] bindings=[('cmd', {[VarSub 1 test_op=VS_TEST_HYPHEN {}]})]) (AndOr OP_OR_IF (Com {[LIT_CHARS shift]}) (Com {[LIT_CHARS usage]} {[VarSub progname]}) ) (Case to_match={[VarSub cmd]}, pat_word_list=[[{[LIT_CHARS create]}], [{[LIT_CHARS push]}], [{[LIT_CHARS release]}], [{[LIT_CHARS abandon]}], [{[LIT_OTHER "*"]}]] (List (AndOr OP_OR_IF (DParen {A2 AS_OP_GE {A Atom NODE_ARITH_WORD {[VarSub #]}} {A Atom NODE_ARITH_WORD {[AS_NUM_LITERAL 2]}}}) (Com {[LIT_CHARS usage]} {[VarSub progname]}) ) (Com {[LIT_CHARS create_release]} {[DQ [VarSub @]]}) ) (Com {[LIT_CHARS push_release_candidate]}) (Com {[LIT_CHARS do_release]}) (Com {[LIT_CHARS abandon_release]}) (Com {[LIT_CHARS usage]} {[VarSub progname]}) ) )