Filter release_builder targets by enabled branches.

This is to prevent running branch disabled tasks in dart-internal.

Bug: https://github.com/flutter/flutter/issues/128097
Change-Id: Ieee6c04a23fdc0f4d5c5bb8b72f82522a5b0171e
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/45380
Reviewed-by: Jesse Seales <jseales@google.com>
Commit-Queue: Godofredo Contreras <godofredoc@google.com>
(cherry picked from commit a9cd59cea3f58b8a35fccbb4ded3a576b5db91a1)
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/45421
Reviewed-by: Drew Roen <drewroen@google.com>
diff --git a/recipes/release/release_builder.expected/filter_enabled_branches.json b/recipes/release/release_builder.expected/filter_enabled_branches.json
new file mode 100644
index 0000000..a715709
--- /dev/null
+++ b/recipes/release/release_builder.expected/filter_enabled_branches.json
@@ -0,0 +1,363 @@
+[
+  {
+    "cmd": [],
+    "name": "Checkout flutter/mirrors/engine"
+  },
+  {
+    "cmd": [
+      "python3",
+      "-u",
+      "RECIPE_MODULE[depot_tools::git]/resources/git_setup.py",
+      "--path",
+      "[START_DIR]/mirrors/engine",
+      "--url",
+      "https://flutter.googlesource.com/mirrors/engine"
+    ],
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.git setup",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "fetch",
+      "origin",
+      "--recurse-submodules",
+      "--progress",
+      "--tags"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "env": {
+      "PATH": "RECIPE_REPO[depot_tools]:<PATH>"
+    },
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.git fetch",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "checkout",
+      "-f",
+      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.git checkout",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "rev-parse",
+      "HEAD"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.read revision",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_TEXT@<br/>checked out 'deadbeef'<br/>@@@",
+      "@@@SET_BUILD_PROPERTY@got_revision@\"deadbeef\"@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "clean",
+      "-f",
+      "-d",
+      "-x"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.git clean",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "submodule",
+      "sync"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.submodule sync",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "submodule",
+      "update",
+      "--init",
+      "--recursive"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Checkout flutter/mirrors/engine.submodule update",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "read ci yaml",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@yaml@@@@",
+      "@@@STEP_LOG_END@yaml@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "vpython3",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[START_DIR]/mirrors/engine/.ci.yaml",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "read ci yaml.read",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_END@.ci.yaml@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "vpython3",
+      "RECIPE_MODULE[flutter::yaml]/resources/parse_yaml.py",
+      "--yaml_file",
+      "[START_DIR]/mirrors/engine/.ci.yaml",
+      "--json_file",
+      "/path/to/tmp/json"
+    ],
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "read ci yaml.parse",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@",
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"targets\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@    {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"drone_dimensions\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"os=Linux\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      ], @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"name\": \"linux one\", @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"properties\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"$flutter/osx_sdk\": \"{\\\"sdk_version\\\": \\\"14a5294e\\\"}\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"release_build\": true@@@",
+      "@@@STEP_LOG_LINE@json.output@      }, @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"recipe\": \"engine/something\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    }, @@@",
+      "@@@STEP_LOG_LINE@json.output@    {@@@",
+      "@@@STEP_LOG_LINE@json.output@      \"drone_dimensions\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"os=Linux\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      ], @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"enabled_branches\": [@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"beta\", @@@",
+      "@@@STEP_LOG_LINE@json.output@        \"main\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      ], @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"name\": \"linux packaging one\", @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"properties\": {@@@",
+      "@@@STEP_LOG_LINE@json.output@        \"$flutter/osx_sdk\": \"{\\\"sdk_version\\\": \\\"14a5294e\\\"}\"@@@",
+      "@@@STEP_LOG_LINE@json.output@      }, @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"recipe\": \"release/something\", @@@",
+      "@@@STEP_LOG_LINE@json.output@      \"scheduler\": \"release\"@@@",
+      "@@@STEP_LOG_LINE@json.output@    }@@@",
+      "@@@STEP_LOG_LINE@json.output@  ]@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "Identify branches"
+  },
+  {
+    "cmd": [
+      "git",
+      "rev-parse",
+      "HEAD"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Identify branches.git rev-parse",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "git",
+      "branch",
+      "-a",
+      "--contains",
+      "12345abcde12345abcde12345abcde12345abcde"
+    ],
+    "cwd": "[START_DIR]/mirrors/engine",
+    "infra_step": true,
+    "luci_context": {
+      "realm": {
+        "name": "prod:try"
+      },
+      "resultdb": {
+        "current_invocation": {
+          "name": "invocations/build:8945511751514863184",
+          "update_token": "token"
+        },
+        "hostname": "rdbhost"
+      }
+    },
+    "name": "Identify branches.git branch",
+    "~followup_annotations": [
+      "@@@STEP_NEST_LEVEL@1@@@"
+    ]
+  },
+  {
+    "cmd": [],
+    "name": "launch builds"
+  },
+  {
+    "cmd": [],
+    "name": "collect builds"
+  },
+  {
+    "cmd": [],
+    "name": "display builds"
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/recipes/release/release_builder.py b/recipes/release/release_builder.py
index e595a3b..fd3c4fe 100644
--- a/recipes/release/release_builder.py
+++ b/recipes/release/release_builder.py
@@ -7,7 +7,7 @@
 # This recipe reads <engine_checkout>/.ci_yaml, and for every target
 # marked with release_build: true, and spawens a subbuild.
 
-import json
+import re
 from contextlib import contextmanager
 
 from PB.recipes.flutter.release.release import InputProperties
@@ -27,6 +27,7 @@
     'recipe_engine/path',
     'recipe_engine/platform',
     'recipe_engine/properties',
+    'recipe_engine/raw_io',
     'recipe_engine/step',
 ]
 
@@ -36,8 +37,19 @@
 RELEASE_CHANNELS = ('refs/heads/beta', 'refs/heads/stable')
 
 
-def ShouldRun(api, git_ref, target):
+def ShouldRun(api, git_ref, target, release_branch):
   """Validates if a target should run based on platform, channel and repo."""
+  # Enabled for current branch
+  enabled_branches = target.get('enabled_branches', [])
+  if enabled_branches:
+    for r in enabled_branches:
+      # Enabled branches is a list of regex
+      if re.match(r, release_branch):
+        break
+    else:
+      # Current branch didn't match any of the enabled branches.
+      return False
+
   release_build = target.get('properties', {}).get('release_build', False)
   for_this_platform = target['name'].lower().startswith(api.platform.name)
   # Postsubmit for engine and flutter repositories.
@@ -78,7 +90,7 @@
   build_results = []
   with api.step.nest('launch builds') as presentation:
     for target in ci_yaml.json.output['targets']:
-      if ShouldRun(api, git_ref, target):
+      if ShouldRun(api, git_ref, target, release_branch):
         target = api.shard_util_v2.pre_process_properties(target)
         tasks.update(
             api.shard_util_v2.schedule([
@@ -120,7 +132,8 @@
   }
   for git_ref in ['main', 'beta']:
     yield api.test(
-        'basic_linux_%s' % git_ref, api.platform.name('linux'),
+        'basic_linux_%s' % git_ref,
+        api.platform.name('linux'),
         api.properties(environment='Staging', repository='engine'),
         api.buildbucket.try_build(
             project='prod',
@@ -134,5 +147,25 @@
             subbuilds=[try_subbuild1],
             launch_step="launch builds.schedule",
             collect_step="collect builds",
-        ), api.step_data('read ci yaml.parse', api.json.output(tasks_dict))
+        ),
+        api.step_data('read ci yaml.parse', api.json.output(tasks_dict)),
     )
+
+  yield api.test(
+      'filter_enabled_branches',
+      api.properties(environment='Staging', repository='engine'),
+      api.buildbucket.try_build(
+          project='prod',
+          builder='try-builder',
+          git_repo='https://flutter.googlesource.com/mirrors/engine',
+          revision='a' * 40,
+          build_number=123,
+          git_ref='refs/heads/%s' % git_ref,
+      ),
+      api.step_data('read ci yaml.parse', api.json.output(tasks_dict)),
+      api.step_data(
+          'Identify branches.git branch',
+          stdout=api.raw_io
+          .output_text('branch1\nbranch2\nflutter-3.2-candidate.5')
+      ),
+  )