mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
135 lines
4.8 KiB
Dart
135 lines
4.8 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
|
|
import 'package:meta/meta.dart';
|
|
|
|
import '../persistent_tool_state.dart';
|
|
import 'io.dart';
|
|
import 'net.dart';
|
|
import 'platform.dart';
|
|
|
|
class BotDetector {
|
|
BotDetector({
|
|
required HttpClientFactory httpClientFactory,
|
|
required Platform platform,
|
|
required PersistentToolState persistentToolState,
|
|
}) :
|
|
_platform = platform,
|
|
_azureDetector = AzureDetector(
|
|
httpClientFactory: httpClientFactory,
|
|
),
|
|
_persistentToolState = persistentToolState;
|
|
|
|
final Platform _platform;
|
|
final AzureDetector _azureDetector;
|
|
final PersistentToolState _persistentToolState;
|
|
|
|
Future<bool> get isRunningOnBot async {
|
|
if (
|
|
// Explicitly stated to not be a bot.
|
|
_platform.environment['BOT'] == 'false'
|
|
|
|
// Set by the IDEs to the IDE name, so a strong signal that this is not a bot.
|
|
|| _platform.environment.containsKey('FLUTTER_HOST')
|
|
// When set, GA logs to a local file (normally for tests) so we don't need to filter.
|
|
|| _platform.environment.containsKey('FLUTTER_ANALYTICS_LOG_FILE')
|
|
) {
|
|
_persistentToolState.setIsRunningOnBot(false);
|
|
return false;
|
|
}
|
|
|
|
if (_persistentToolState.isRunningOnBot != null) {
|
|
return _persistentToolState.isRunningOnBot!;
|
|
}
|
|
|
|
final bool result = _platform.environment['BOT'] == 'true'
|
|
|
|
// https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
|
|
|| _platform.environment['TRAVIS'] == 'true'
|
|
|| _platform.environment['CONTINUOUS_INTEGRATION'] == 'true'
|
|
|| _platform.environment.containsKey('CI') // Travis and AppVeyor
|
|
|
|
// https://www.appveyor.com/docs/environment-variables/
|
|
|| _platform.environment.containsKey('APPVEYOR')
|
|
|
|
// https://cirrus-ci.org/guide/writing-tasks/#environment-variables
|
|
|| _platform.environment.containsKey('CIRRUS_CI')
|
|
|
|
// https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html
|
|
|| (_platform.environment.containsKey('AWS_REGION') &&
|
|
_platform.environment.containsKey('CODEBUILD_INITIATOR'))
|
|
|
|
// https://wiki.jenkins.io/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-belowJenkinsSetEnvironmentVariables
|
|
|| _platform.environment.containsKey('JENKINS_URL')
|
|
|
|
// https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables
|
|
|| _platform.environment.containsKey('GITHUB_ACTIONS')
|
|
|
|
// Properties on Flutter's Chrome Infra bots.
|
|
|| _platform.environment['CHROME_HEADLESS'] == '1'
|
|
|| _platform.environment.containsKey('BUILDBOT_BUILDERNAME')
|
|
|| _platform.environment.containsKey('SWARMING_TASK_ID')
|
|
|
|
// Property when running on borg.
|
|
|| _platform.environment.containsKey('BORG_ALLOC_DIR')
|
|
|
|
// Property when running on Azure.
|
|
|| await _azureDetector.isRunningOnAzure;
|
|
|
|
_persistentToolState.setIsRunningOnBot(result);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
// Are we running on Azure?
|
|
// https://docs.microsoft.com/en-us/azure/virtual-machines/linux/instance-metadata-service
|
|
@visibleForTesting
|
|
class AzureDetector {
|
|
AzureDetector({
|
|
required HttpClientFactory httpClientFactory,
|
|
}) : _httpClientFactory = httpClientFactory;
|
|
|
|
static const String _serviceUrl = 'http://169.254.169.254/metadata/instance';
|
|
|
|
final HttpClientFactory _httpClientFactory;
|
|
|
|
bool? _isRunningOnAzure;
|
|
|
|
Future<bool> get isRunningOnAzure async {
|
|
if (_isRunningOnAzure != null) {
|
|
return _isRunningOnAzure!;
|
|
}
|
|
const Duration connectionTimeout = Duration(milliseconds: 250);
|
|
const Duration requestTimeout = Duration(seconds: 1);
|
|
final HttpClient client = _httpClientFactory()
|
|
..connectionTimeout = connectionTimeout;
|
|
try {
|
|
final HttpClientRequest request = await client.getUrl(
|
|
Uri.parse(_serviceUrl),
|
|
).timeout(requestTimeout);
|
|
request.headers.add('Metadata', true);
|
|
await request.close();
|
|
} on SocketException {
|
|
// If there is an error on the socket, it probably means that we are not
|
|
// running on Azure.
|
|
return _isRunningOnAzure = false;
|
|
} on HttpException {
|
|
// If the connection gets set up, but encounters an error condition, it
|
|
// still means we're on Azure.
|
|
return _isRunningOnAzure = true;
|
|
} on TimeoutException {
|
|
// The HttpClient connected to a host, but it did not respond in a timely
|
|
// fashion. Assume we are not on a bot.
|
|
return _isRunningOnAzure = false;
|
|
} on OSError {
|
|
// The HttpClient might be running in a WSL1 environment.
|
|
return _isRunningOnAzure = false;
|
|
}
|
|
// We got a response. We're running on Azure.
|
|
return _isRunningOnAzure = true;
|
|
}
|
|
}
|