Skip to content

Conversation

@royarg02
Copy link
Contributor

@royarg02 royarg02 commented Jan 25, 2022

This PR makes the tool skip checking for version freshness if the remote being tracked by the current channel/branch is "not-standard".

A standard remote is either https://github.com/flutter/flutter.git/[email protected]:flutter/flutter.git or the one set in the environment variable FLUTTER_GIT_URL.

This makes the tool check for freshness from the same repo it will fetch the updates when running the upgrade sub-command. Another added bonus, it prevents the unnecessary check for freshness from a user's forked repo, however the user can still configure FLUTTER_GIT_URL for freshness check anyway in that case.

Fixes #14120.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Jan 25, 2022
@royarg02 royarg02 changed the title [WIP] [flutter_tools] Skip version freshness check for non-standard remotes [flutter_tools] Skip version freshness check for non-standard remotes Jan 25, 2022
@royarg02 royarg02 marked this pull request as ready for review January 25, 2022 12:53
@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch from d5b20da to cf122c3 Compare January 30, 2022 16:22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than hard-coding here, could you also store this in globals, next to flutterGit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting back to this, why does this need to be in globals? This and flutterGit would be only used in version.dart. We could probably remove them from globals and instead pass globals.platform around.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch 2 times, most recently from 14afae7 to 7045442 Compare February 18, 2022 13:58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this context platform never gets called in the test, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless the test doesn't call globals.flutterGit, which it definitely does :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see that before we were injecting the platform, we were accidentally leaking the real system platform into the test suite, which is a huge cause of flakiness in our tool test suite. For the tests that only depend on a created instance of VersionUpstreamValidator, can you use testWithoutContext() instead of testUsingContext()? With testWithoutContext(), any test that tries to call context.get() via the globals. or any other method will throw. This way we know exactly what our the code depends on, and we don't get tests accidentally passing because the system they were running on had the correct platform setup. I imagine you will have to also inject flutterGitSshUrl via the constructor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would also need to provide globals.flutterGit too if that's the case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. I know it's a pain, but it's the best way we have right now for ensuring that we're not leaking global state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...which adds two parameters which similar semantics?

VersionUpstreamValidator({
  required this.version,
  required this.platform,
  required this.flutterGitUrl,
  required this.flutterGitSshUrl,
});

Can't think of a better name to give to these parameters.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that feels bad. However, the only other way I can think of would be to define a class for GitHubRemote, that takes in an org and project name, and has two getters for httpsUrl and sshUrl, but that seems like overkill?

@royarg02
Copy link
Contributor Author

royarg02 commented Feb 23, 2022

Adding to my comment here and my inference of the usage of globals.dart:

globals.flutterGit is only used twice in version.dart(it is also used in upgrade.dart, which this PR removes):

static Future<String> fetchRemoteFrameworkCommitDate(String branch) async {
await _removeVersionCheckRemoteIfExists();
try {
await _run(<String>[
'git',
'remote',
'add',
_versionCheckRemote,
globals.flutterGit,
]);

This will be redundant once this PR lands(and can be removed).


static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
if (fetchTags) {
final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
} else {
_runGit('git fetch ${globals.flutterGit} --tags -f', processUtils, workingDirectory);
}

From what I can see, this is used for version resolution, before which the tool fetches in the newer tags. An interesting consequence of using FLUTTER_GIT_URL here that if the custom remote does not have the newer tags (which is the case for forks updated through git pull upstream master && git push origin master), a wrong version is calculated(#15529).

I confirmed this by running FLUTTER_GIT_URL='https://github.com/RoyARG02/flutter/flutter.git' ./bin/flutter --version --verbose on a fresh clone of my fork which does not have the newer tags, and the tool gives me a version of 1.24.0-0.0.pre.7043 😱

Not sure if allowing FLUTTER_GIT_URL here would be considered a bug or feature, but we should remove globals.flutterGit here as well if it's the former. This would be a bad idea for users facing problems accessing GitHub.

@christopherfujino
Copy link
Contributor

Adding to my comment here and my inference of the usage of globals.dart:

globals.flutterGit is only used twice in version.dart(it is also used in upgrade.dart, which this PR removes):

static Future<String> fetchRemoteFrameworkCommitDate(String branch) async {
await _removeVersionCheckRemoteIfExists();
try {
await _run(<String>[
'git',
'remote',
'add',
_versionCheckRemote,
globals.flutterGit,
]);

This will be redundant once this PR lands(and can be removed).

static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
if (fetchTags) {
final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
} else {
_runGit('git fetch ${globals.flutterGit} --tags -f', processUtils, workingDirectory);
}

From what I can see, this is used for version resolution, before which the tool fetches in the newer tags. An interesting consequence of using FLUTTER_GIT_URL here that if the custom remote does not have the newer tags (which is the case for forks updated through git pull upstream master && git push origin master), a wrong version is calculated(#15529).
I confirmed this by running FLUTTER_GIT_URL='https://github.com/RoyARG02/flutter/flutter.git' ./bin/flutter --version --verbose on a fresh clone of my fork which does not have the newer tags, and the tool gives me a version of 1.24.0-0.0.pre.7043 😱

Yeah, I don't think there's much we can do about this, other than deprecating the use of git tags for version resolution, which I would like to do but don't really have time for.

@royarg02
Copy link
Contributor Author

royarg02 commented Feb 25, 2022

@christopherfujino to solve the issue you mentioned at #97202 (comment), can we instead do #97202 (comment) and use a different _flutterGit in VersionUpstreamValidator? So that would look like the following:

   VersionUpstreamValidator({
     required this.version,
     required this.platform,
-    required this.flutterGitSshUrl,
-    required this.flutterGitUrl,
-  });
+  }) : _flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git';

-  final String flutterGitSshUrl;
-  final String flutterGitUrl;
+  final String _flutterGit;
   final FlutterVersion version;
   final Platform platform;
...
     // Strip `.git` suffix before comparing the remotes
-    final String sanitizedRepositoryUrl = stripDotGit(repositoryUrl);
-    final String sanitizedFlutterGitUrl = stripDotGit(flutterGitUrl);
-    final String sanitizedFlutterGitSshUrl = stripDotGit(flutterGitSshUrl);
+    final List<String> sanitizedStandardRemotes = <String>[
+      _flutterGit,
+      '[email protected]:flutter/flutter.git',
+    ].map((String remote) => stripDotGit(remote)).toList();

A similar change can be made(in a future PR) where FLUTTER_GIT_URL is used:

-  static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
+  static GitTagVersion determine(
+    ProcessUtils processUtils,
+    Platform platform, {
+      String? workingDirectory,
+      bool fetchTags = false,
+      String gitRef = 'HEAD'
+    }) {
     if (fetchTags) {
       final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
       if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
         globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
       } else {
-        _runGit('git fetch ${globals.flutterGit} --tags -f', processUtils, workingDirectory);
+        final String flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git';
+        _runGit('git fetch $flutterGit --tags -f', processUtils, workingDirectory);

@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch 2 times, most recently from fa51406 to 720a22a Compare February 26, 2022 05:56
@christopherfujino
Copy link
Contributor

@christopherfujino to solve the issue you mentioned at #97202 (comment), can we instead do #97202 (comment) and use a different _flutterGit in VersionUpstreamValidator? So that would look like the following:

   VersionUpstreamValidator({
     required this.version,
     required this.platform,
-    required this.flutterGitSshUrl,
-    required this.flutterGitUrl,
-  });
+  }) : _flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git';

-  final String flutterGitSshUrl;
-  final String flutterGitUrl;
+  final String _flutterGit;
   final FlutterVersion version;
   final Platform platform;
...
     // Strip `.git` suffix before comparing the remotes
-    final String sanitizedRepositoryUrl = stripDotGit(repositoryUrl);
-    final String sanitizedFlutterGitUrl = stripDotGit(flutterGitUrl);
-    final String sanitizedFlutterGitSshUrl = stripDotGit(flutterGitSshUrl);
+    final List<String> sanitizedStandardRemotes = <String>[
+      _flutterGit,
+      '[email protected]:flutter/flutter.git',
+    ].map((String remote) => stripDotGit(remote)).toList();

A similar change can be made(in a future PR) where FLUTTER_GIT_URL is used:

-  static GitTagVersion determine(ProcessUtils processUtils, {String? workingDirectory, bool fetchTags = false, String gitRef = 'HEAD'}) {
+  static GitTagVersion determine(
+    ProcessUtils processUtils,
+    Platform platform, {
+      String? workingDirectory,
+      bool fetchTags = false,
+      String gitRef = 'HEAD'
+    }) {
     if (fetchTags) {
       final String channel = _runGit('git rev-parse --abbrev-ref HEAD', processUtils, workingDirectory);
       if (channel == 'dev' || channel == 'beta' || channel == 'stable') {
         globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
       } else {
-        _runGit('git fetch ${globals.flutterGit} --tags -f', processUtils, workingDirectory);
+        final String flutterGit = platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git';
+        _runGit('git fetch $flutterGit --tags -f', processUtils, workingDirectory);

SGTM

@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch from 720a22a to e145881 Compare March 6, 2022 07:13
@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch from 7e00826 to c24c877 Compare March 13, 2022 07:28
@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch from c24c877 to 89e9739 Compare March 21, 2022 06:56
Copy link
Contributor

@christopherfujino christopherfujino Mar 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a little unusual for the API of this method to be void while it is the responsibility of the caller to catch a VersionCheckError. Could you instead have this method return VersionCheckError? and then in the method, instead of throwing, simply return the error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@christopherfujino christopherfujino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overall LGTM, with the nit about the validator.run returning a nullable error rather than throwing.

@royarg02 royarg02 force-pushed the nonstandard-freshness-skip branch from 89e9739 to efb5d35 Compare March 21, 2022 20:29
Copy link
Contributor

@christopherfujino christopherfujino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • Please get at least one approved review if you are already a member or two member reviews if you are not a member before re-applying this label. Reviewers: If you left a comment approving, please use the "approve" review action instead.

@christopherfujino
Copy link
Contributor

@Jasguerrero can you take a look too?

Copy link
Contributor

@Jasguerrero Jasguerrero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fluttergithubbot fluttergithubbot merged commit 74f08c7 into flutter:master Mar 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Mar 29, 2022
@royarg02 royarg02 deleted the nonstandard-freshness-skip branch May 7, 2022 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flutter upgrade should refuse to run or run properly on a branch that comes from a fork.

4 participants