From 102de85bbc060214286a9aa3c80ab3e31eed6534 Mon Sep 17 00:00:00 2001 From: hangyu Date: Mon, 17 Nov 2025 15:10:49 -0800 Subject: [PATCH 1/8] resolve some comments new api lint lint update tests Update publish_command_test.dart Update publish_command_test.dart 2 2 Update publish_command_test.dart lint Update publish_command.dart Update release_from_batch_release.yml Update release.yml clean up code Update publish_command.dart 1 --- .github/workflows/release.yml | 21 +- .github/workflows/release_from_branches.yml | 13 ++ .github/workflows/release_from_main.yml | 13 ++ script/tool/lib/src/publish_command.dart | 31 +++ script/tool/test/publish_command_test.dart | 220 ++++++++++++++++++++ script/tool/test/util.dart | 16 ++ 6 files changed, 307 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/release_from_branches.yml create mode 100644 .github/workflows/release_from_main.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 62683962e093..f787cca80272 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,12 +1,18 @@ -name: release +name: Reusable Release on: - push: - branches: - - main - + workflow_call: + inputs: + publish-args: + required: true + type: string + workflow-name: + required: true + type: string + branch-name: + required: true + type: string # Declare default permissions as read only. permissions: read-all - jobs: release: if: github.repository_owner == 'flutter' @@ -21,6 +27,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 with: fetch-depth: 0 # Fetch all history so the tool can get all the tags to determine version. + ref: ${{ inputs.branch-name }} - name: "Install Flutter" uses: ./.github/workflows/internals/install_flutter - name: Set up tools @@ -66,5 +73,5 @@ jobs: run: | git config --global user.name ${{ secrets.USER_NAME }} git config --global user.email ${{ secrets.USER_EMAIL }} - dart ./script/tool/lib/src/main.dart publish --all-changed --base-sha=HEAD~ --skip-confirmation --remote=origin + dart ./script/tool/lib/src/main.dart publish ${{ inputs.publish-args }} env: {PUB_CREDENTIALS: "${{ secrets.PUB_CREDENTIALS }}"} diff --git a/.github/workflows/release_from_branches.yml b/.github/workflows/release_from_branches.yml new file mode 100644 index 000000000000..1c8e088369f3 --- /dev/null +++ b/.github/workflows/release_from_branches.yml @@ -0,0 +1,13 @@ +name: Batch Release +on: + push: + branches: + - 'release-go-router' +jobs: + release: + uses: ./.github/workflows/release.yml + with: + publish-args: '--all-changed --batch-release --base-sha=HEAD~ --skip-confirmation --remote=origin' + workflow-name: 'Batch Release ${{ github.ref_name }}' + branch-name: '${{ github.ref_name }}' + secrets: inherit diff --git a/.github/workflows/release_from_main.yml b/.github/workflows/release_from_main.yml new file mode 100644 index 000000000000..f6bca6b6522b --- /dev/null +++ b/.github/workflows/release_from_main.yml @@ -0,0 +1,13 @@ +name: Main Release +on: + push: + branches: + - main +jobs: + release: + uses: ./.github/workflows/release.yml + with: + publish-args: '--all-changed --base-sha=HEAD~ --skip-confirmation --remote=origin' + workflow-name: 'Main Release' + branch-name: 'main' + secrets: inherit diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index 4d9da43ddc40..5d665ef30742 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -15,6 +15,7 @@ import 'package:platform/platform.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; +import 'common/ci_config.dart'; import 'common/core.dart'; import 'common/file_utils.dart'; import 'common/output_utils.dart'; @@ -83,6 +84,10 @@ class PublishCommand extends PackageLoopingCommand { 'Release all packages that contains pubspec changes at the current commit compares to the base-sha.\n' 'The --packages option is ignored if this is on.', ); + argParser.addFlag( + _batchReleaseFlag, + help: 'only release the packages that opt-in for batch release option.', + ); argParser.addFlag( _dryRunFlag, help: @@ -109,6 +114,7 @@ class PublishCommand extends PackageLoopingCommand { static const String _pubFlagsOption = 'pub-publish-flags'; static const String _remoteOption = 'remote'; static const String _allChangedFlag = 'all-changed'; + static const String _batchReleaseFlag = 'batch-release'; static const String _dryRunFlag = 'dry-run'; static const String _skipConfirmationFlag = 'skip-confirmation'; static const String _tagForAutoPublishFlag = 'tag-for-auto-publish'; @@ -196,6 +202,31 @@ class PublishCommand extends PackageLoopingCommand { .toList(); for (final pubspecPath in changedPubspecs) { + // Read the ci_config.yaml file if it exists + + final String packageName = p.basename(p.dirname(pubspecPath)); + bool isBatchReleasePackage; + try { + final File ciConfigFile = packagesDir.fileSystem + .file(pubspecPath) + .parent + .childFile('ci_config.yaml'); + if (!ciConfigFile.existsSync()) { + isBatchReleasePackage = false; + } else { + final CIConfig ciConfig = + CIConfig.parse(ciConfigFile.readAsStringSync()); + isBatchReleasePackage = ciConfig.isBatchRelease; + } + } catch (e) { + printError('Could not parse ci_config.yaml for $packageName: $e'); + continue; + } + // Skip the package if batch release flag is not set to match the ci_config.yaml + if (getBoolArg(_batchReleaseFlag) != isBatchReleasePackage) { + continue; + } + // git outputs a relativa, Posix-style path. final File pubspecFile = childFileWithSubcomponents( packagesDir.fileSystem.directory((await gitDir).path), diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart index f106f0349561..8c9a0d163d25 100644 --- a/script/tool/test/publish_command_test.dart +++ b/script/tool/test/publish_command_test.dart @@ -1284,6 +1284,226 @@ void main() { ); }); + group('--batch-release flag', () { + test( + 'filters packages based on the existence of ci_config.yaml', + () async { + // Mock pub.dev responses. + mockHttpResponses['plugin1'] = { + 'name': 'plugin1', + 'versions': ['0.0.1'], + }; + mockHttpResponses['plugin2'] = { + 'name': 'plugin2', + 'versions': ['0.0.1'], + }; + + // Mock packages. + final RepositoryPackage plugin1 = createFakePlugin( + 'plugin1', + packagesDir, + version: '0.0.2', + batchRelease: true, + ); + + final RepositoryPackage plugin2 = createFakePlugin( + 'plugin2', + packagesDir, + version: '0.0.2', + ); + + expect(plugin1.ciConfigFile.existsSync(), true); + expect(plugin2.ciConfigFile.existsSync(), false); + + // Mock git diff to show both packages have changed. + processRunner + .mockProcessesForExecutable['git-diff'] = [ + FakeProcessInfo( + MockProcess( + stdout: + '${plugin1.pubspecFile.path}\n${plugin2.pubspecFile.path}', + ), + ), + ]; + + mockStdin.readLineOutput = 'y'; + + final List output = await runCapturingPrint( + commandRunner, + [ + 'publish', + '--all-changed', + '--base-sha=HEAD~', + '--batch-release', + ], + ); + // Package1 is published in batch realease, pacakge2 is not. + expect( + output, + containsAllInOrder([ + contains('Running `pub publish ` in ${plugin1.path}...'), + contains('Published plugin1 successfully!'), + ]), + ); + + expect( + output, + isNot( + contains( + contains('Running `pub publish ` in ${plugin2.path}...!'), + ), + ), + ); + expect( + output, + isNot(contains(contains('Published plugin2 successfully!'))), + ); + }, + ); + + test( + 'filters packages based on the batch release flag value in ci_config.yaml', + () async { + // Mock pub.dev responses. + mockHttpResponses['plugin1'] = { + 'name': 'plugin1', + 'versions': ['0.0.1'], + }; + mockHttpResponses['plugin2'] = { + 'name': 'plugin2', + 'versions': ['0.0.1'], + }; + + // Mock packages. + final RepositoryPackage plugin1 = createFakePlugin( + 'plugin1', + packagesDir, + version: '0.0.2', + batchRelease: true, + ); + + final RepositoryPackage plugin2 = createFakePlugin( + 'plugin2', + packagesDir, + version: '0.0.2', + batchRelease: false, + ); + + // Mock git diff to show both packages have changed. + processRunner + .mockProcessesForExecutable['git-diff'] = [ + FakeProcessInfo( + MockProcess( + stdout: + '${plugin1.pubspecFile.path}\n${plugin2.pubspecFile.path}', + ), + ), + ]; + + mockStdin.readLineOutput = 'y'; + + final List output = await runCapturingPrint( + commandRunner, + [ + 'publish', + '--all-changed', + '--base-sha=HEAD~', + '--batch-release', + ], + ); + // Package1 is published in batch realease, pacakge2 is not. + expect( + output, + containsAllInOrder([ + contains('Running `pub publish ` in ${plugin1.path}...'), + contains('Published plugin1 successfully!'), + ]), + ); + + expect( + output, + isNot( + contains( + contains('Running `pub publish ` in ${plugin2.path}...!'), + ), + ), + ); + expect( + output, + isNot(contains(contains('Published plugin2 successfully!'))), + ); + }, + ); + + test( + 'when --batch-release flag value is false, batch release packages are filtered out', + () async { + // Mock pub.dev responses. + mockHttpResponses['plugin1'] = { + 'name': 'plugin1', + 'versions': ['0.0.1'], + }; + mockHttpResponses['plugin2'] = { + 'name': 'plugin2', + 'versions': ['0.0.1'], + }; + + // Mock packages. + final RepositoryPackage plugin1 = createFakePlugin( + 'plugin1', + packagesDir, + version: '0.0.2', + ); + + final RepositoryPackage plugin2 = createFakePlugin( + 'plugin2', + packagesDir, + version: '0.0.2', + batchRelease: true, + ); + + // Mock git diff to show both packages have changed. + processRunner + .mockProcessesForExecutable['git-diff'] = [ + FakeProcessInfo( + MockProcess( + stdout: + '${plugin1.pubspecFile.path}\n${plugin2.pubspecFile.path}', + ), + ), + ]; + + mockStdin.readLineOutput = 'y'; + + final List output = await runCapturingPrint( + commandRunner, + ['publish', '--all-changed', '--base-sha=HEAD~'], + ); + // Package1 is published in batch realease, pacakge2 is not. + expect( + output, + containsAllInOrder([ + contains('Running `pub publish ` in ${plugin1.path}...'), + contains('Published plugin1 successfully!'), + ]), + ); + + expect( + output, + isNot( + contains( + contains('Running `pub publish ` in ${plugin2.path}...!'), + ), + ), + ); + expect( + output, + isNot(contains(contains('Published plugin2 successfully!'))), + ); + }, + ); + }); + test('Do not release flutter_plugin_tools', () async { mockHttpResponses['plugin1'] = { 'name': 'flutter_plugin_tools', diff --git a/script/tool/test/util.dart b/script/tool/test/util.dart index 493e4641309f..defd7e844b1c 100644 --- a/script/tool/test/util.dart +++ b/script/tool/test/util.dart @@ -96,6 +96,7 @@ RepositoryPackage createFakePlugin( String? version = '0.0.1', String flutterConstraint = _defaultFlutterConstraint, String dartConstraint = _defaultDartConstraint, + bool? batchRelease, }) { final RepositoryPackage package = createFakePackage( name, @@ -117,6 +118,9 @@ RepositoryPackage createFakePlugin( flutterConstraint: flutterConstraint, dartConstraint: dartConstraint, ); + if (batchRelease != null) { + createFakeCiConfig(batchRelease, package); + } return package; } @@ -287,6 +291,18 @@ $pluginSection package.pubspecFile.writeAsStringSync(yaml); } +/// Creates a `ci_config.yaml` file for [package]. +void createFakeCiConfig(bool batchRelease, RepositoryPackage package) { + final yaml = + ''' +release: + batch: $batchRelease +'''; + + package.ciConfigFile.createSync(); + package.ciConfigFile.writeAsStringSync(yaml); +} + String _pluginPlatformSection( String platform, PlatformDetails support, From bafe3ea72a8204a7aee015b7b93643c0cce36c47 Mon Sep 17 00:00:00 2001 From: hangyu Date: Tue, 13 Jan 2026 10:48:04 -0800 Subject: [PATCH 2/8] updates --- .github/workflows/release.yml | 21 +++---- .github/workflows/release_from_branches.yml | 69 +++++++++++++++++++-- .github/workflows/release_from_main.yml | 13 ---- script/tool/lib/src/publish_command.dart | 30 ++++++--- script/tool/test/publish_command_test.dart | 8 +-- 5 files changed, 95 insertions(+), 46 deletions(-) delete mode 100644 .github/workflows/release_from_main.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f787cca80272..62683962e093 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,18 +1,12 @@ -name: Reusable Release +name: release on: - workflow_call: - inputs: - publish-args: - required: true - type: string - workflow-name: - required: true - type: string - branch-name: - required: true - type: string + push: + branches: + - main + # Declare default permissions as read only. permissions: read-all + jobs: release: if: github.repository_owner == 'flutter' @@ -27,7 +21,6 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 with: fetch-depth: 0 # Fetch all history so the tool can get all the tags to determine version. - ref: ${{ inputs.branch-name }} - name: "Install Flutter" uses: ./.github/workflows/internals/install_flutter - name: Set up tools @@ -73,5 +66,5 @@ jobs: run: | git config --global user.name ${{ secrets.USER_NAME }} git config --global user.email ${{ secrets.USER_EMAIL }} - dart ./script/tool/lib/src/main.dart publish ${{ inputs.publish-args }} + dart ./script/tool/lib/src/main.dart publish --all-changed --base-sha=HEAD~ --skip-confirmation --remote=origin env: {PUB_CREDENTIALS: "${{ secrets.PUB_CREDENTIALS }}"} diff --git a/.github/workflows/release_from_branches.yml b/.github/workflows/release_from_branches.yml index 1c8e088369f3..d5f7ac83f87e 100644 --- a/.github/workflows/release_from_branches.yml +++ b/.github/workflows/release_from_branches.yml @@ -3,11 +3,68 @@ on: push: branches: - 'release-go-router' + +# Declare default permissions as read only. +permissions: read-all + jobs: release: - uses: ./.github/workflows/release.yml - with: - publish-args: '--all-changed --batch-release --base-sha=HEAD~ --skip-confirmation --remote=origin' - workflow-name: 'Batch Release ${{ github.ref_name }}' - branch-name: '${{ github.ref_name }}' - secrets: inherit + if: github.repository_owner == 'flutter' + name: release + permissions: + # Release needs to push a tag back to the repo. + contents: write + runs-on: ubuntu-latest + steps: + # Checks out a copy of the repo. + - name: Check out code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + with: + fetch-depth: 0 # Fetch all history so the tool can get all the tags to determine version. + - name: "Install Flutter" + uses: ./.github/workflows/internals/install_flutter + - name: Set up tools + run: dart pub get + working-directory: ${{ github.workspace }}/script/tool + + # Give some time for LUCI checks to start becoming populated. + # Because of latency in Github Webhooks, we need to wait for a while + # before being able to look at checks scheduled by LUCI. + - name: Give webhooks a minute + run: sleep 60s + shell: bash + + # The next step waits for all tests, but when there are issues with the + # hooks it can take a long time for the tests to even be registered. If + # "Wait on all tests" runs before that happens, it will pass immediately + # because there doesn't appear to be anything to wait for. To avoid that, + # explicitly wait for one LUCI test by name first. + - name: Wait for test check-in + uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 + with: + ref: ${{ github.sha }} + check-name: 'Linux ci_yaml packages roller' + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 30 # seconds + allowed-conclusions: success,neutral + # verbose:true will produce too many logs that hang github actions web UI. + verbose: false + + # This workflow should be the last to run. So wait for all the other tests to succeed. + - name: Wait on all tests + uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 + with: + ref: ${{ github.sha }} + running-workflow-name: 'release ${{ github.ref_name }}' + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 180 # seconds + allowed-conclusions: success,neutral + # verbose:true will produce too many logs that hang github actions web UI. + verbose: false + + - name: run release + run: | + git config --global user.name ${{ secrets.USER_NAME }} + git config --global user.email ${{ secrets.USER_EMAIL }} + dart ./script/tool/lib/src/main.dart publish --all-changed --batch-release-branch=${{ github.ref_name }} --base-sha=HEAD~ --skip-confirmation --remote=origin + env: {PUB_CREDENTIALS: "${{ secrets.PUB_CREDENTIALS }}"} diff --git a/.github/workflows/release_from_main.yml b/.github/workflows/release_from_main.yml deleted file mode 100644 index f6bca6b6522b..000000000000 --- a/.github/workflows/release_from_main.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: Main Release -on: - push: - branches: - - main -jobs: - release: - uses: ./.github/workflows/release.yml - with: - publish-args: '--all-changed --base-sha=HEAD~ --skip-confirmation --remote=origin' - workflow-name: 'Main Release' - branch-name: 'main' - secrets: inherit diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index 5d665ef30742..b4c5ead21327 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -15,7 +15,6 @@ import 'package:platform/platform.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; -import 'common/ci_config.dart'; import 'common/core.dart'; import 'common/file_utils.dart'; import 'common/output_utils.dart'; @@ -85,8 +84,8 @@ class PublishCommand extends PackageLoopingCommand { 'The --packages option is ignored if this is on.', ); argParser.addFlag( - _batchReleaseFlag, - help: 'only release the packages that opt-in for batch release option.', + _batchReleaseBranchFlag, + help: 'batch release a package from its release branch', ); argParser.addFlag( _dryRunFlag, @@ -114,7 +113,7 @@ class PublishCommand extends PackageLoopingCommand { static const String _pubFlagsOption = 'pub-publish-flags'; static const String _remoteOption = 'remote'; static const String _allChangedFlag = 'all-changed'; - static const String _batchReleaseFlag = 'batch-release'; + static const String _batchReleaseBranchFlag = 'batch-release-branch'; static const String _dryRunFlag = 'dry-run'; static const String _skipConfirmationFlag = 'skip-confirmation'; static const String _tagForAutoPublishFlag = 'tag-for-auto-publish'; @@ -214,17 +213,30 @@ class PublishCommand extends PackageLoopingCommand { if (!ciConfigFile.existsSync()) { isBatchReleasePackage = false; } else { - final CIConfig ciConfig = - CIConfig.parse(ciConfigFile.readAsStringSync()); + final ciConfig = CIConfig.parse(ciConfigFile.readAsStringSync()); isBatchReleasePackage = ciConfig.isBatchRelease; } } catch (e) { printError('Could not parse ci_config.yaml for $packageName: $e'); continue; } - // Skip the package if batch release flag is not set to match the ci_config.yaml - if (getBoolArg(_batchReleaseFlag) != isBatchReleasePackage) { - continue; + + final String batchReleaseBranchName = getStringArg(_batchReleaseBranchFlag); + + // When releasing from the main branch, skip the batch release packages. + if (batchReleaseBranchName.isEmpty) { + if (isBatchReleasePackage) { + continue; + } + } + // When releasing from a batch release branch, verify the package has + // the opt-in flag and that the package name matches the branch suffix. + // Example: branch "release-go_router" matches package "go_router". + if (batchReleaseBranchName.isNotEmpty) { + if (!(isBatchReleasePackage && + batchReleaseBranchName.contains(packageName))) { + continue; + } } // git outputs a relativa, Posix-style path. diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart index 8c9a0d163d25..c80dd9091cdf 100644 --- a/script/tool/test/publish_command_test.dart +++ b/script/tool/test/publish_command_test.dart @@ -1284,7 +1284,7 @@ void main() { ); }); - group('--batch-release flag', () { + group('--batch-release-branch flag', () { test( 'filters packages based on the existence of ci_config.yaml', () async { @@ -1334,7 +1334,7 @@ void main() { 'publish', '--all-changed', '--base-sha=HEAD~', - '--batch-release', + '--batch-release-branch=release-plugin1', ], ); // Package1 is published in batch realease, pacakge2 is not. @@ -1408,7 +1408,7 @@ void main() { 'publish', '--all-changed', '--base-sha=HEAD~', - '--batch-release', + '--batch-release-branch=release-plugin1', ], ); // Package1 is published in batch realease, pacakge2 is not. @@ -1436,7 +1436,7 @@ void main() { ); test( - 'when --batch-release flag value is false, batch release packages are filtered out', + 'when --batch-release-branch flag value is empty, batch release packages are filtered out', () async { // Mock pub.dev responses. mockHttpResponses['plugin1'] = { From 633d02687e07629b9c7d99079e810fe36997d6bc Mon Sep 17 00:00:00 2001 From: hangyu Date: Wed, 14 Jan 2026 15:57:34 -0800 Subject: [PATCH 3/8] resolve comments --- .github/workflows/release_from_branches.yml | 68 ++--------------- .github/workflows/reusable_release.yml | 84 +++++++++++++++++++++ script/tool/lib/src/publish_command.dart | 26 +++---- 3 files changed, 101 insertions(+), 77 deletions(-) create mode 100644 .github/workflows/reusable_release.yml diff --git a/.github/workflows/release_from_branches.yml b/.github/workflows/release_from_branches.yml index d5f7ac83f87e..84f12ef68f11 100644 --- a/.github/workflows/release_from_branches.yml +++ b/.github/workflows/release_from_branches.yml @@ -3,68 +3,10 @@ on: push: branches: - 'release-go-router' - -# Declare default permissions as read only. -permissions: read-all - jobs: release: - if: github.repository_owner == 'flutter' - name: release - permissions: - # Release needs to push a tag back to the repo. - contents: write - runs-on: ubuntu-latest - steps: - # Checks out a copy of the repo. - - name: Check out code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - with: - fetch-depth: 0 # Fetch all history so the tool can get all the tags to determine version. - - name: "Install Flutter" - uses: ./.github/workflows/internals/install_flutter - - name: Set up tools - run: dart pub get - working-directory: ${{ github.workspace }}/script/tool - - # Give some time for LUCI checks to start becoming populated. - # Because of latency in Github Webhooks, we need to wait for a while - # before being able to look at checks scheduled by LUCI. - - name: Give webhooks a minute - run: sleep 60s - shell: bash - - # The next step waits for all tests, but when there are issues with the - # hooks it can take a long time for the tests to even be registered. If - # "Wait on all tests" runs before that happens, it will pass immediately - # because there doesn't appear to be anything to wait for. To avoid that, - # explicitly wait for one LUCI test by name first. - - name: Wait for test check-in - uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 - with: - ref: ${{ github.sha }} - check-name: 'Linux ci_yaml packages roller' - repo-token: ${{ secrets.GITHUB_TOKEN }} - wait-interval: 30 # seconds - allowed-conclusions: success,neutral - # verbose:true will produce too many logs that hang github actions web UI. - verbose: false - - # This workflow should be the last to run. So wait for all the other tests to succeed. - - name: Wait on all tests - uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 - with: - ref: ${{ github.sha }} - running-workflow-name: 'release ${{ github.ref_name }}' - repo-token: ${{ secrets.GITHUB_TOKEN }} - wait-interval: 180 # seconds - allowed-conclusions: success,neutral - # verbose:true will produce too many logs that hang github actions web UI. - verbose: false - - - name: run release - run: | - git config --global user.name ${{ secrets.USER_NAME }} - git config --global user.email ${{ secrets.USER_EMAIL }} - dart ./script/tool/lib/src/main.dart publish --all-changed --batch-release-branch=${{ github.ref_name }} --base-sha=HEAD~ --skip-confirmation --remote=origin - env: {PUB_CREDENTIALS: "${{ secrets.PUB_CREDENTIALS }}"} + uses: ./.github/workflows/resuable_release.yml + with: + is-batch-release: true + branch-name: '${{ github.ref_name }}' + secrets: inherit diff --git a/.github/workflows/reusable_release.yml b/.github/workflows/reusable_release.yml new file mode 100644 index 000000000000..9a0894507c67 --- /dev/null +++ b/.github/workflows/reusable_release.yml @@ -0,0 +1,84 @@ +name: Reusable Release +on: + workflow_call: + inputs: + is-batch-release: + required: true + type: boolean + branch-name: + required: true + type: string +# Declare default permissions as read only. +permissions: read-all +jobs: + release: + if: github.repository_owner == 'flutter' + name: release + permissions: + # Release needs to push a tag back to the repo. + contents: write + runs-on: ubuntu-latest + steps: + # Checks out a copy of the repo. + - name: Check out code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 + with: + fetch-depth: 0 # Fetch all history so the tool can get all the tags to determine version. + ref: ${{ inputs.branch-name }} + - name: "Install Flutter" + uses: ./.github/workflows/internals/install_flutter + - name: Set up tools + run: dart pub get + working-directory: ${{ github.workspace }}/script/tool + + # Give some time for LUCI checks to start becoming populated. + # Because of latency in Github Webhooks, we need to wait for a while + # before being able to look at checks scheduled by LUCI. + - name: Give webhooks a minute + run: sleep 60s + shell: bash + + # The next step waits for all tests, but when there are issues with the + # hooks it can take a long time for the tests to even be registered. If + # "Wait on all tests" runs before that happens, it will pass immediately + # because there doesn't appear to be anything to wait for. To avoid that, + # explicitly wait for one LUCI test by name first. + - name: Wait for test check-in + uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 + with: + ref: ${{ github.sha }} + check-name: 'Linux ci_yaml packages roller' + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 30 # seconds + allowed-conclusions: success,neutral + # verbose:true will produce too many logs that hang github actions web UI. + verbose: false + + # This workflow should be the last to run. So wait for all the other tests to succeed. + - name: Wait on all tests + uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 + with: + ref: ${{ github.sha }} + running-workflow-name: 'release' + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 180 # seconds + allowed-conclusions: success,neutral + # verbose:true will produce too many logs that hang github actions web UI. + verbose: false + + - name: run release + run: | + git config --global user.name "${{ secrets.USER_NAME }}" + git config --global user.email "${{ secrets.USER_EMAIL }}" + + # Build the flag string based on the input + BATCH_FLAG="" + if [ "${{ inputs.is-batch-release }}" = "true" ]; then + BATCH_FLAG="--batch-release-branch=${{ inputs.branch-name }}" + fi + dart ./script/tool/lib/src/main.dart publish \ + --all-changed \ + $BATCH_FLAG \ + --base-sha=HEAD~ \ + --skip-confirmation + env: {PUB_CREDENTIALS: "${{ secrets.PUB_CREDENTIALS }}"} diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index b4c5ead21327..0280573bd992 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -191,6 +191,7 @@ class PublishCommand extends PackageLoopingCommand { @override Stream getPackagesToProcess() async* { + final String batchReleaseBranchName = getStringArg(_batchReleaseBranchFlag); if (getBoolArg(_allChangedFlag)) { print( 'Publishing all packages that have changed relative to "$baseSha"\n', @@ -206,10 +207,10 @@ class PublishCommand extends PackageLoopingCommand { final String packageName = p.basename(p.dirname(pubspecPath)); bool isBatchReleasePackage; try { - final File ciConfigFile = packagesDir.fileSystem - .file(pubspecPath) - .parent - .childFile('ci_config.yaml'); + final File ciConfigFile = RepositoryPackage( + packagesDir.fileSystem.file(pubspecPath).parent, + ).ciConfigFile; + if (!ciConfigFile.existsSync()) { isBatchReleasePackage = false; } else { @@ -218,23 +219,20 @@ class PublishCommand extends PackageLoopingCommand { } } catch (e) { printError('Could not parse ci_config.yaml for $packageName: $e'); - continue; + throw ToolExit(exitCommandFoundErrors); } - final String batchReleaseBranchName = getStringArg(_batchReleaseBranchFlag); - // When releasing from the main branch, skip the batch release packages. if (batchReleaseBranchName.isEmpty) { if (isBatchReleasePackage) { continue; } - } - // When releasing from a batch release branch, verify the package has - // the opt-in flag and that the package name matches the branch suffix. - // Example: branch "release-go_router" matches package "go_router". - if (batchReleaseBranchName.isNotEmpty) { - if (!(isBatchReleasePackage && - batchReleaseBranchName.contains(packageName))) { + } else { + // When releasing from a batch release branch, verify the package has + // the opt-in flag and that the package name matches the branch suffix. + // Example: branch "release-go_router" matches package "go_router". + if (!isBatchReleasePackage || + batchReleaseBranchName != 'release-$packageName') { continue; } } From 7187d667654ed586f816798d5d5083a8e3233e09 Mon Sep 17 00:00:00 2001 From: Hannah Jin Date: Thu, 15 Jan 2026 14:11:54 -0800 Subject: [PATCH 4/8] Update .github/workflows/release_from_branches.yml Co-authored-by: chunhtai <47866232+chunhtai@users.noreply.github.com> --- .github/workflows/release_from_branches.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release_from_branches.yml b/.github/workflows/release_from_branches.yml index 84f12ef68f11..a235a2576ef3 100644 --- a/.github/workflows/release_from_branches.yml +++ b/.github/workflows/release_from_branches.yml @@ -2,7 +2,7 @@ name: Batch Release on: push: branches: - - 'release-go-router' + - 'release-go_router' jobs: release: uses: ./.github/workflows/resuable_release.yml From 8972d5a2a918755b30165e0211f85de47137e023 Mon Sep 17 00:00:00 2001 From: hangyu Date: Fri, 16 Jan 2026 13:16:38 -0800 Subject: [PATCH 5/8] resolve comments --- script/tool/lib/src/publish_command.dart | 8 +- script/tool/test/publish_command_test.dart | 125 ++++++++++----------- script/tool/test/util.dart | 11 +- 3 files changed, 73 insertions(+), 71 deletions(-) diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index 0280573bd992..39aafd055462 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -83,8 +83,8 @@ class PublishCommand extends PackageLoopingCommand { 'Release all packages that contains pubspec changes at the current commit compares to the base-sha.\n' 'The --packages option is ignored if this is on.', ); - argParser.addFlag( - _batchReleaseBranchFlag, + argParser.addOption( + _batchReleaseBranchOption, help: 'batch release a package from its release branch', ); argParser.addFlag( @@ -113,7 +113,7 @@ class PublishCommand extends PackageLoopingCommand { static const String _pubFlagsOption = 'pub-publish-flags'; static const String _remoteOption = 'remote'; static const String _allChangedFlag = 'all-changed'; - static const String _batchReleaseBranchFlag = 'batch-release-branch'; + static const String _batchReleaseBranchOption = 'batch-release-branch'; static const String _dryRunFlag = 'dry-run'; static const String _skipConfirmationFlag = 'skip-confirmation'; static const String _tagForAutoPublishFlag = 'tag-for-auto-publish'; @@ -191,7 +191,7 @@ class PublishCommand extends PackageLoopingCommand { @override Stream getPackagesToProcess() async* { - final String batchReleaseBranchName = getStringArg(_batchReleaseBranchFlag); + final String batchReleaseBranchName = getStringArg(_batchReleaseBranchOption); if (getBoolArg(_allChangedFlag)) { print( 'Publishing all packages that have changed relative to "$baseSha"\n', diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart index c80dd9091cdf..77c3a15a6c3a 100644 --- a/script/tool/test/publish_command_test.dart +++ b/script/tool/test/publish_command_test.dart @@ -1289,31 +1289,32 @@ void main() { 'filters packages based on the existence of ci_config.yaml', () async { // Mock pub.dev responses. - mockHttpResponses['plugin1'] = { - 'name': 'plugin1', + mockHttpResponses['package1'] = { + 'name': 'package1', 'versions': ['0.0.1'], }; - mockHttpResponses['plugin2'] = { - 'name': 'plugin2', + mockHttpResponses['package2'] = { + 'name': 'package2', 'versions': ['0.0.1'], }; // Mock packages. - final RepositoryPackage plugin1 = createFakePlugin( - 'plugin1', + final RepositoryPackage package1 = createFakePackage( + 'package1', packagesDir, version: '0.0.2', - batchRelease: true, + includeCIConfig: true, + isBatchRelease: true, ); - final RepositoryPackage plugin2 = createFakePlugin( - 'plugin2', + final RepositoryPackage package2 = createFakePackage( + 'package2', packagesDir, version: '0.0.2', ); - expect(plugin1.ciConfigFile.existsSync(), true); - expect(plugin2.ciConfigFile.existsSync(), false); + expect(package1.ciConfigFile.existsSync(), true); + expect(package2.ciConfigFile.existsSync(), false); // Mock git diff to show both packages have changed. processRunner @@ -1321,28 +1322,26 @@ void main() { FakeProcessInfo( MockProcess( stdout: - '${plugin1.pubspecFile.path}\n${plugin2.pubspecFile.path}', + '${package1.pubspecFile.path}\n${package2.pubspecFile.path}', ), ), ]; mockStdin.readLineOutput = 'y'; - final List output = await runCapturingPrint( - commandRunner, - [ - 'publish', - '--all-changed', - '--base-sha=HEAD~', - '--batch-release-branch=release-plugin1', - ], - ); + final List output = + await runCapturingPrint(commandRunner, [ + 'publish', + '--all-changed', + '--base-sha=HEAD~', + '--batch-release-branch=release-package1', + ]); // Package1 is published in batch realease, pacakge2 is not. expect( output, containsAllInOrder([ - contains('Running `pub publish ` in ${plugin1.path}...'), - contains('Published plugin1 successfully!'), + contains('Running `pub publish ` in ${package1.path}...'), + contains('Published package1 successfully!'), ]), ); @@ -1350,13 +1349,13 @@ void main() { output, isNot( contains( - contains('Running `pub publish ` in ${plugin2.path}...!'), + contains('Running `pub publish ` in ${package2.path}...!'), ), ), ); expect( output, - isNot(contains(contains('Published plugin2 successfully!'))), + isNot(contains(contains('Published package2 successfully!'))), ); }, ); @@ -1365,28 +1364,29 @@ void main() { 'filters packages based on the batch release flag value in ci_config.yaml', () async { // Mock pub.dev responses. - mockHttpResponses['plugin1'] = { - 'name': 'plugin1', + mockHttpResponses['package1'] = { + 'name': 'package1', 'versions': ['0.0.1'], }; - mockHttpResponses['plugin2'] = { - 'name': 'plugin2', + mockHttpResponses['package2'] = { + 'name': 'package2', 'versions': ['0.0.1'], }; // Mock packages. - final RepositoryPackage plugin1 = createFakePlugin( - 'plugin1', + final RepositoryPackage package1 = createFakePackage( + 'package1', packagesDir, version: '0.0.2', - batchRelease: true, + includeCIConfig: true, + isBatchRelease: true, ); - final RepositoryPackage plugin2 = createFakePlugin( - 'plugin2', + final RepositoryPackage package2 = createFakePackage( + 'package2', packagesDir, version: '0.0.2', - batchRelease: false, + includeCIConfig: true, ); // Mock git diff to show both packages have changed. @@ -1395,28 +1395,26 @@ void main() { FakeProcessInfo( MockProcess( stdout: - '${plugin1.pubspecFile.path}\n${plugin2.pubspecFile.path}', + '${package1.pubspecFile.path}\n${package2.pubspecFile.path}', ), ), ]; mockStdin.readLineOutput = 'y'; - final List output = await runCapturingPrint( - commandRunner, - [ - 'publish', - '--all-changed', - '--base-sha=HEAD~', - '--batch-release-branch=release-plugin1', - ], - ); + final List output = + await runCapturingPrint(commandRunner, [ + 'publish', + '--all-changed', + '--base-sha=HEAD~', + '--batch-release-branch=release-package1', + ]); // Package1 is published in batch realease, pacakge2 is not. expect( output, containsAllInOrder([ - contains('Running `pub publish ` in ${plugin1.path}...'), - contains('Published plugin1 successfully!'), + contains('Running `pub publish ` in ${package1.path}...'), + contains('Published package1 successfully!'), ]), ); @@ -1424,13 +1422,13 @@ void main() { output, isNot( contains( - contains('Running `pub publish ` in ${plugin2.path}...!'), + contains('Running `pub publish ` in ${package2.path}...!'), ), ), ); expect( output, - isNot(contains(contains('Published plugin2 successfully!'))), + isNot(contains(contains('Published package2 successfully!'))), ); }, ); @@ -1439,27 +1437,28 @@ void main() { 'when --batch-release-branch flag value is empty, batch release packages are filtered out', () async { // Mock pub.dev responses. - mockHttpResponses['plugin1'] = { - 'name': 'plugin1', + mockHttpResponses['package1'] = { + 'name': 'package1', 'versions': ['0.0.1'], }; - mockHttpResponses['plugin2'] = { - 'name': 'plugin2', + mockHttpResponses['package2'] = { + 'name': 'package2', 'versions': ['0.0.1'], }; // Mock packages. - final RepositoryPackage plugin1 = createFakePlugin( - 'plugin1', + final RepositoryPackage package1 = createFakePackage( + 'package1', packagesDir, version: '0.0.2', ); - final RepositoryPackage plugin2 = createFakePlugin( - 'plugin2', + final RepositoryPackage package2 = createFakePackage( + 'package2', packagesDir, version: '0.0.2', - batchRelease: true, + includeCIConfig: true, + isBatchRelease: true, ); // Mock git diff to show both packages have changed. @@ -1468,7 +1467,7 @@ void main() { FakeProcessInfo( MockProcess( stdout: - '${plugin1.pubspecFile.path}\n${plugin2.pubspecFile.path}', + '${package1.pubspecFile.path}\n${package2.pubspecFile.path}', ), ), ]; @@ -1483,8 +1482,8 @@ void main() { expect( output, containsAllInOrder([ - contains('Running `pub publish ` in ${plugin1.path}...'), - contains('Published plugin1 successfully!'), + contains('Running `pub publish ` in ${package1.path}...'), + contains('Published package1 successfully!'), ]), ); @@ -1492,13 +1491,13 @@ void main() { output, isNot( contains( - contains('Running `pub publish ` in ${plugin2.path}...!'), + contains('Running `pub publish ` in ${package2.path}...!'), ), ), ); expect( output, - isNot(contains(contains('Published plugin2 successfully!'))), + isNot(contains(contains('Published package2 successfully!'))), ); }, ); diff --git a/script/tool/test/util.dart b/script/tool/test/util.dart index defd7e844b1c..98496f4d9b35 100644 --- a/script/tool/test/util.dart +++ b/script/tool/test/util.dart @@ -96,7 +96,6 @@ RepositoryPackage createFakePlugin( String? version = '0.0.1', String flutterConstraint = _defaultFlutterConstraint, String dartConstraint = _defaultDartConstraint, - bool? batchRelease, }) { final RepositoryPackage package = createFakePackage( name, @@ -118,9 +117,6 @@ RepositoryPackage createFakePlugin( flutterConstraint: flutterConstraint, dartConstraint: dartConstraint, ); - if (batchRelease != null) { - createFakeCiConfig(batchRelease, package); - } return package; } @@ -135,6 +131,8 @@ RepositoryPackage createFakePlugin( /// /// If non-null, [directoryName] will be used for the directory instead of /// [name]. +/// If [includeCIConfig] is true, a fake CI config file will be created. +/// [isBatchRelease] will be used in the CI config file. RepositoryPackage createFakePackage( String name, Directory parentDirectory, { @@ -147,6 +145,8 @@ RepositoryPackage createFakePackage( bool includeCommonFiles = true, String? directoryName, String? publishTo, + bool includeCIConfig = false, + bool isBatchRelease = false, }) { final package = RepositoryPackage( parentDirectory.childDirectory(directoryName ?? name), @@ -163,6 +163,9 @@ RepositoryPackage createFakePackage( dartConstraint: dartConstraint, publishTo: publishTo, ); + if (includeCIConfig) { + createFakeCiConfig(isBatchRelease, package); + } if (includeCommonFiles) { package.changelogFile.writeAsStringSync(''' ## $version From 0f8447b347b0dee68672cb3cfd4d93f5cce02d1c Mon Sep 17 00:00:00 2001 From: hangyu Date: Fri, 16 Jan 2026 13:44:21 -0800 Subject: [PATCH 6/8] Update publish_command_test.dart --- script/tool/test/publish_command_test.dart | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart index 77c3a15a6c3a..eaca13d8d637 100644 --- a/script/tool/test/publish_command_test.dart +++ b/script/tool/test/publish_command_test.dart @@ -1501,6 +1501,60 @@ void main() { ); }, ); + test(' throw tool exit when could not parse ci config file', () async { + // Mock pub.dev responses. + mockHttpResponses['package1'] = { + 'name': 'package1', + 'versions': ['0.0.1'], + }; + + // Mock packages. + final RepositoryPackage package1 = createFakePackage( + 'package1', + packagesDir, + includeCIConfig: true, + version: '0.0.2', + ); + + package1.ciConfigFile.writeAsStringSync( + 'wrong format of ci config file', + ); + + // Mock git diff to show both packages have changed. + processRunner.mockProcessesForExecutable['git-diff'] = + [ + FakeProcessInfo( + MockProcess(stdout: '${package1.pubspecFile.path}\n'), + ), + ]; + + mockStdin.readLineOutput = 'y'; + + Error? commandError; + // Package1 is published in batch realease, pacakge2 is not. + final List output = await runCapturingPrint( + commandRunner, + [ + 'publish', + '--all-changed', + '--base-sha=HEAD~', + '--batch-release-branch=release-package1', + ], + errorHandler: (Error e) { + commandError = e; + }, + ); + + expect(commandError, isA()); + expect( + output, + containsAllInOrder([ + contains( + 'Could not parse ci_config.yaml for package1: FormatException: Root of ci_config.yaml must be a map.', + ), + ]), + ); + }); }); test('Do not release flutter_plugin_tools', () async { From d55dbd8164f8061b4413bf6dfe9dbb794afed9fb Mon Sep 17 00:00:00 2001 From: hangyu Date: Fri, 16 Jan 2026 14:14:17 -0800 Subject: [PATCH 7/8] lint --- script/tool/lib/src/publish_command.dart | 4 +++- script/tool/test/util.dart | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index 39aafd055462..126c2274d326 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -191,7 +191,9 @@ class PublishCommand extends PackageLoopingCommand { @override Stream getPackagesToProcess() async* { - final String batchReleaseBranchName = getStringArg(_batchReleaseBranchOption); + final String batchReleaseBranchName = getStringArg( + _batchReleaseBranchOption, + ); if (getBoolArg(_allChangedFlag)) { print( 'Publishing all packages that have changed relative to "$baseSha"\n', diff --git a/script/tool/test/util.dart b/script/tool/test/util.dart index 98496f4d9b35..9577e1e52bf7 100644 --- a/script/tool/test/util.dart +++ b/script/tool/test/util.dart @@ -131,8 +131,8 @@ RepositoryPackage createFakePlugin( /// /// If non-null, [directoryName] will be used for the directory instead of /// [name]. -/// If [includeCIConfig] is true, a fake CI config file will be created. -/// [isBatchRelease] will be used in the CI config file. +/// If [includeCIConfig] is true, a fake CI config file will be created. +/// [isBatchRelease] will be used in the CI config file. RepositoryPackage createFakePackage( String name, Directory parentDirectory, { From a00c2fd672acc01612eafd3f144d2bbcce4e1c03 Mon Sep 17 00:00:00 2001 From: hangyu Date: Wed, 21 Jan 2026 13:26:02 -0800 Subject: [PATCH 8/8] resolve comments --- script/tool/lib/src/publish_command.dart | 3 +-- script/tool/test/publish_command_test.dart | 15 +++++---------- script/tool/test/util.dart | 12 ++++-------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/script/tool/lib/src/publish_command.dart b/script/tool/lib/src/publish_command.dart index 126c2274d326..d043da0a60c3 100644 --- a/script/tool/lib/src/publish_command.dart +++ b/script/tool/lib/src/publish_command.dart @@ -205,9 +205,8 @@ class PublishCommand extends PackageLoopingCommand { for (final pubspecPath in changedPubspecs) { // Read the ci_config.yaml file if it exists - final String packageName = p.basename(p.dirname(pubspecPath)); - bool isBatchReleasePackage; + final bool isBatchReleasePackage; try { final File ciConfigFile = RepositoryPackage( packagesDir.fileSystem.file(pubspecPath).parent, diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart index eaca13d8d637..c12d91f71721 100644 --- a/script/tool/test/publish_command_test.dart +++ b/script/tool/test/publish_command_test.dart @@ -1303,9 +1303,8 @@ void main() { 'package1', packagesDir, version: '0.0.2', - includeCIConfig: true, - isBatchRelease: true, ); + createFakeCiConfig(package: package1, batchRelease: true); final RepositoryPackage package2 = createFakePackage( 'package2', @@ -1378,16 +1377,14 @@ void main() { 'package1', packagesDir, version: '0.0.2', - includeCIConfig: true, - isBatchRelease: true, ); - + createFakeCiConfig(package: package1, batchRelease: true); final RepositoryPackage package2 = createFakePackage( 'package2', packagesDir, version: '0.0.2', - includeCIConfig: true, ); + createFakeCiConfig(package: package2, batchRelease: false); // Mock git diff to show both packages have changed. processRunner @@ -1457,9 +1454,8 @@ void main() { 'package2', packagesDir, version: '0.0.2', - includeCIConfig: true, - isBatchRelease: true, ); + createFakeCiConfig(package: package2, batchRelease: true); // Mock git diff to show both packages have changed. processRunner @@ -1512,10 +1508,9 @@ void main() { final RepositoryPackage package1 = createFakePackage( 'package1', packagesDir, - includeCIConfig: true, version: '0.0.2', ); - + createFakeCiConfig(package: package1, batchRelease: false); package1.ciConfigFile.writeAsStringSync( 'wrong format of ci config file', ); diff --git a/script/tool/test/util.dart b/script/tool/test/util.dart index 9577e1e52bf7..a6d94f6fa928 100644 --- a/script/tool/test/util.dart +++ b/script/tool/test/util.dart @@ -131,8 +131,6 @@ RepositoryPackage createFakePlugin( /// /// If non-null, [directoryName] will be used for the directory instead of /// [name]. -/// If [includeCIConfig] is true, a fake CI config file will be created. -/// [isBatchRelease] will be used in the CI config file. RepositoryPackage createFakePackage( String name, Directory parentDirectory, { @@ -145,8 +143,6 @@ RepositoryPackage createFakePackage( bool includeCommonFiles = true, String? directoryName, String? publishTo, - bool includeCIConfig = false, - bool isBatchRelease = false, }) { final package = RepositoryPackage( parentDirectory.childDirectory(directoryName ?? name), @@ -163,9 +159,6 @@ RepositoryPackage createFakePackage( dartConstraint: dartConstraint, publishTo: publishTo, ); - if (includeCIConfig) { - createFakeCiConfig(isBatchRelease, package); - } if (includeCommonFiles) { package.changelogFile.writeAsStringSync(''' ## $version @@ -295,7 +288,10 @@ $pluginSection } /// Creates a `ci_config.yaml` file for [package]. -void createFakeCiConfig(bool batchRelease, RepositoryPackage package) { +void createFakeCiConfig({ + required RepositoryPackage package, + required bool batchRelease, +}) { final yaml = ''' release: