Skip to content

Commit 9010299

Browse files
authored
[batch-release] Step2 : Publish packages from the release branch (#10459)
issue: flutter/flutter#176944 Add a batch Release Flag in the publish command. The main branch will only publish packages that are opted out of batch release. The release branch will only publish packages that are opted into batch release. ## Pre-Review Checklist **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent e6955be commit 9010299

5 files changed

Lines changed: 421 additions & 0 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Batch Release
2+
on:
3+
push:
4+
branches:
5+
- 'release-go_router'
6+
jobs:
7+
release:
8+
uses: ./.github/workflows/resuable_release.yml
9+
with:
10+
is-batch-release: true
11+
branch-name: '${{ github.ref_name }}'
12+
secrets: inherit
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: Reusable Release
2+
on:
3+
workflow_call:
4+
inputs:
5+
is-batch-release:
6+
required: true
7+
type: boolean
8+
branch-name:
9+
required: true
10+
type: string
11+
# Declare default permissions as read only.
12+
permissions: read-all
13+
jobs:
14+
release:
15+
if: github.repository_owner == 'flutter'
16+
name: release
17+
permissions:
18+
# Release needs to push a tag back to the repo.
19+
contents: write
20+
runs-on: ubuntu-latest
21+
steps:
22+
# Checks out a copy of the repo.
23+
- name: Check out code
24+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
25+
with:
26+
fetch-depth: 0 # Fetch all history so the tool can get all the tags to determine version.
27+
ref: ${{ inputs.branch-name }}
28+
- name: "Install Flutter"
29+
uses: ./.github/workflows/internals/install_flutter
30+
- name: Set up tools
31+
run: dart pub get
32+
working-directory: ${{ github.workspace }}/script/tool
33+
34+
# Give some time for LUCI checks to start becoming populated.
35+
# Because of latency in Github Webhooks, we need to wait for a while
36+
# before being able to look at checks scheduled by LUCI.
37+
- name: Give webhooks a minute
38+
run: sleep 60s
39+
shell: bash
40+
41+
# The next step waits for all tests, but when there are issues with the
42+
# hooks it can take a long time for the tests to even be registered. If
43+
# "Wait on all tests" runs before that happens, it will pass immediately
44+
# because there doesn't appear to be anything to wait for. To avoid that,
45+
# explicitly wait for one LUCI test by name first.
46+
- name: Wait for test check-in
47+
uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79
48+
with:
49+
ref: ${{ github.sha }}
50+
check-name: 'Linux ci_yaml packages roller'
51+
repo-token: ${{ secrets.GITHUB_TOKEN }}
52+
wait-interval: 30 # seconds
53+
allowed-conclusions: success,neutral
54+
# verbose:true will produce too many logs that hang github actions web UI.
55+
verbose: false
56+
57+
# This workflow should be the last to run. So wait for all the other tests to succeed.
58+
- name: Wait on all tests
59+
uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79
60+
with:
61+
ref: ${{ github.sha }}
62+
running-workflow-name: 'release'
63+
repo-token: ${{ secrets.GITHUB_TOKEN }}
64+
wait-interval: 180 # seconds
65+
allowed-conclusions: success,neutral
66+
# verbose:true will produce too many logs that hang github actions web UI.
67+
verbose: false
68+
69+
- name: run release
70+
run: |
71+
git config --global user.name "${{ secrets.USER_NAME }}"
72+
git config --global user.email "${{ secrets.USER_EMAIL }}"
73+
74+
# Build the flag string based on the input
75+
BATCH_FLAG=""
76+
if [ "${{ inputs.is-batch-release }}" = "true" ]; then
77+
BATCH_FLAG="--batch-release-branch=${{ inputs.branch-name }}"
78+
fi
79+
dart ./script/tool/lib/src/main.dart publish \
80+
--all-changed \
81+
$BATCH_FLAG \
82+
--base-sha=HEAD~ \
83+
--skip-confirmation
84+
env: {PUB_CREDENTIALS: "${{ secrets.PUB_CREDENTIALS }}"}

script/tool/lib/src/publish_command.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ class PublishCommand extends PackageLoopingCommand {
8383
'Release all packages that contains pubspec changes at the current commit compares to the base-sha.\n'
8484
'The --packages option is ignored if this is on.',
8585
);
86+
argParser.addOption(
87+
_batchReleaseBranchOption,
88+
help: 'batch release a package from its release branch',
89+
);
8690
argParser.addFlag(
8791
_dryRunFlag,
8892
help:
@@ -109,6 +113,7 @@ class PublishCommand extends PackageLoopingCommand {
109113
static const String _pubFlagsOption = 'pub-publish-flags';
110114
static const String _remoteOption = 'remote';
111115
static const String _allChangedFlag = 'all-changed';
116+
static const String _batchReleaseBranchOption = 'batch-release-branch';
112117
static const String _dryRunFlag = 'dry-run';
113118
static const String _skipConfirmationFlag = 'skip-confirmation';
114119
static const String _tagForAutoPublishFlag = 'tag-for-auto-publish';
@@ -186,6 +191,9 @@ class PublishCommand extends PackageLoopingCommand {
186191

187192
@override
188193
Stream<PackageEnumerationEntry> getPackagesToProcess() async* {
194+
final String batchReleaseBranchName = getStringArg(
195+
_batchReleaseBranchOption,
196+
);
189197
if (getBoolArg(_allChangedFlag)) {
190198
print(
191199
'Publishing all packages that have changed relative to "$baseSha"\n',
@@ -196,6 +204,40 @@ class PublishCommand extends PackageLoopingCommand {
196204
.toList();
197205

198206
for (final pubspecPath in changedPubspecs) {
207+
// Read the ci_config.yaml file if it exists
208+
final String packageName = p.basename(p.dirname(pubspecPath));
209+
final bool isBatchReleasePackage;
210+
try {
211+
final File ciConfigFile = RepositoryPackage(
212+
packagesDir.fileSystem.file(pubspecPath).parent,
213+
).ciConfigFile;
214+
215+
if (!ciConfigFile.existsSync()) {
216+
isBatchReleasePackage = false;
217+
} else {
218+
final ciConfig = CIConfig.parse(ciConfigFile.readAsStringSync());
219+
isBatchReleasePackage = ciConfig.isBatchRelease;
220+
}
221+
} catch (e) {
222+
printError('Could not parse ci_config.yaml for $packageName: $e');
223+
throw ToolExit(exitCommandFoundErrors);
224+
}
225+
226+
// When releasing from the main branch, skip the batch release packages.
227+
if (batchReleaseBranchName.isEmpty) {
228+
if (isBatchReleasePackage) {
229+
continue;
230+
}
231+
} else {
232+
// When releasing from a batch release branch, verify the package has
233+
// the opt-in flag and that the package name matches the branch suffix.
234+
// Example: branch "release-go_router" matches package "go_router".
235+
if (!isBatchReleasePackage ||
236+
batchReleaseBranchName != 'release-$packageName') {
237+
continue;
238+
}
239+
}
240+
199241
// git outputs a relativa, Posix-style path.
200242
final File pubspecFile = childFileWithSubcomponents(
201243
packagesDir.fileSystem.directory((await gitDir).path),

0 commit comments

Comments
 (0)