From fdc64ce2b4d02639179c38a9c4e5236bafa634a2 Mon Sep 17 00:00:00 2001 From: sbs44 <83440025+sbs44@users.noreply.github.com> Date: Mon, 12 Jan 2026 07:10:50 -0500 Subject: [PATCH] feat(build): add github-artifacts CLI options for custom engine sources - Add --github-artifacts-repo, --github-artifacts-runid, --github-artifacts-engine-version, --github-artifacts-auth-token options - Parse options early in executable.dart before context setup - Support GITHUB_TOKEN env variable for workflow artifact authentication - Enable downloading engine artifacts from custom forks and workflow runs --- lib/src/cli/commands/build.dart | 1 + lib/src/cli/flutterpi_command.dart | 34 +++++++++++++++++++++ lib/src/context.dart | 49 +++++++++++++++++++++++++----- lib/src/executable.dart | 26 ++++++++++++++++ 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/lib/src/cli/commands/build.dart b/lib/src/cli/commands/build.dart index ba328ac..965ee82 100644 --- a/lib/src/cli/commands/build.dart +++ b/lib/src/cli/commands/build.dart @@ -38,6 +38,7 @@ class BuildCommand extends FlutterpiCommand { usesTargetOption(); usesLocalFlutterpiExecutableArg(verboseHelp: verboseHelp); usesFilesystemLayoutArg(verboseHelp: verboseHelp); + usesGithubArtifactsOptions(verboseHelp: verboseHelp); argParser ..addSeparator('Target options') diff --git a/lib/src/cli/flutterpi_command.dart b/lib/src/cli/flutterpi_command.dart index 51da8c6..4913019 100644 --- a/lib/src/cli/flutterpi_command.dart +++ b/lib/src/cli/flutterpi_command.dart @@ -273,6 +273,40 @@ mixin FlutterpiCommandMixin on fl.FlutterCommand { ); } + void usesGithubArtifactsOptions({bool verboseHelp = false}) { + argParser.addOption( + 'github-artifacts-repo', + help: + 'Use a custom GitHub repository for engine artifacts instead of ardera/flutter-ci.', + valueHelp: 'owner/repo', + hide: !verboseHelp, + ); + + argParser.addOption( + 'github-artifacts-runid', + help: + 'Download engine artifacts from a specific GitHub Actions workflow run instead of releases.', + valueHelp: 'run-id', + hide: !verboseHelp, + ); + + argParser.addOption( + 'github-artifacts-engine-version', + help: + 'Specify the engine version available in the workflow run artifacts.', + valueHelp: 'engine-hash', + hide: !verboseHelp, + ); + + argParser.addOption( + 'github-artifacts-auth-token', + help: + 'GitHub authentication token for accessing artifacts. Can also be set via GITHUB_TOKEN environment variable.', + valueHelp: 'token', + hide: !verboseHelp, + ); + } + bool getIncludeDebugSymbols() { return boolArg('debug-symbols'); } diff --git a/lib/src/context.dart b/lib/src/context.dart index 10560fe..ae6dadc 100644 --- a/lib/src/context.dart +++ b/lib/src/context.dart @@ -15,6 +15,7 @@ import 'package:flutterpi_tool/src/fltool/common.dart' as fl; import 'package:flutterpi_tool/src/fltool/globals.dart' as globals; import 'package:flutterpi_tool/src/github.dart'; import 'package:flutterpi_tool/src/more_os_utils.dart'; +import 'package:github/github.dart' as gh; // ignore: implementation_imports import 'package:flutter_tools/src/context_runner.dart' as fl; @@ -22,13 +23,30 @@ import 'package:flutter_tools/src/context_runner.dart' as fl; Future runInContext( FutureOr Function() fn, { bool verbose = false, + String? githubArtifactsRepo, + String? githubArtifactsRunId, + String? githubArtifactsEngineVersion, + String? githubArtifactsAuthToken, }) async { return await fl.runInContext( fn, overrides: { Analytics: () => const NoOpAnalytics(), fl.TemplateRenderer: () => const fl.MustacheTemplateRenderer(), - fl.Cache: () => FlutterpiCache( + fl.Cache: () { + // Check environment variable for token if not provided + final token = githubArtifactsAuthToken ?? + globals.platform.environment['GITHUB_TOKEN']; + + final github = MyGithub.caching( + httpClient: http.IOClient( + globals.httpClientFactory?.call() ?? io.HttpClient(), + ), + auth: token != null ? gh.Authentication.bearerToken(token) : null, + ); + + if (githubArtifactsRunId != null) { + return FlutterpiCache.fromWorkflow( hooks: globals.shutdownHooks, logger: globals.logger, fileSystem: globals.fs, @@ -36,12 +54,29 @@ Future runInContext( osUtils: globals.os as MoreOperatingSystemUtils, projectFactory: globals.projectFactory, processManager: globals.processManager, - github: MyGithub.caching( - httpClient: http.IOClient( - globals.httpClientFactory?.call() ?? io.HttpClient(), - ), - ), - ), + repo: githubArtifactsRepo != null + ? gh.RepositorySlug.full(githubArtifactsRepo) + : null, + runId: githubArtifactsRunId, + availableEngineVersion: githubArtifactsEngineVersion, + github: github, + ); + } else { + return FlutterpiCache( + hooks: globals.shutdownHooks, + logger: globals.logger, + fileSystem: globals.fs, + platform: globals.platform, + osUtils: globals.os as MoreOperatingSystemUtils, + projectFactory: globals.projectFactory, + processManager: globals.processManager, + repo: githubArtifactsRepo != null + ? gh.RepositorySlug.full(githubArtifactsRepo) + : null, + github: github, + ); + } + }, fl.OperatingSystemUtils: () => MoreOperatingSystemUtils( fileSystem: globals.fs, logger: globals.logger, diff --git a/lib/src/executable.dart b/lib/src/executable.dart index c9f5987..cdab29a 100644 --- a/lib/src/executable.dart +++ b/lib/src/executable.dart @@ -36,6 +36,20 @@ FlutterpiToolCommandRunner createFlutterpiCommandRunner({ return runner; } +// Helper to extract option value from args +String? _extractOption(List args, String optionName) { + for (var i = 0; i < args.length; i++) { + final arg = args[i]; + if (arg == '--$optionName' && i + 1 < args.length) { + return args[i + 1]; + } + if (arg.startsWith('--$optionName=')) { + return arg.substring('--$optionName='.length); + } + } + return null; +} + Future main(List args) async { final verbose = args.contains('-v') || args.contains('--verbose') || args.contains('-vv'); @@ -50,6 +64,14 @@ Future main(List args) async { (args.length == 1 && verbose); final verboseHelp = help && verbose; + // Parse github-artifacts options early (before context is set up) + final githubArtifactsRepo = _extractOption(args, 'github-artifacts-repo'); + final githubArtifactsRunId = _extractOption(args, 'github-artifacts-runid'); + final githubArtifactsEngineVersion = + _extractOption(args, 'github-artifacts-engine-version'); + final githubArtifactsAuthToken = + _extractOption(args, 'github-artifacts-auth-token'); + final runner = createFlutterpiCommandRunner(verboseHelp: verboseHelp); fltool.Cache.flutterRoot = await getFlutterRoot(); @@ -86,5 +108,9 @@ Future main(List args) async { } }, verbose: verbose, + githubArtifactsRepo: githubArtifactsRepo, + githubArtifactsRunId: githubArtifactsRunId, + githubArtifactsEngineVersion: githubArtifactsEngineVersion, + githubArtifactsAuthToken: githubArtifactsAuthToken, ); }