mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* Update project.pbxproj files to say Flutter rather than Chromium Also, the templates now have an empty organization so that we don't cause people to give their apps a Flutter copyright. * Update the copyright notice checker to require a standard notice on all files * Update copyrights on Dart files. (This was a mechanical commit.) * Fix weird license headers on Dart files that deviate from our conventions; relicense Shrine. Some were already marked "The Flutter Authors", not clear why. Their dates have been normalized. Some were missing the blank line after the license. Some were randomly different in trivial ways for no apparent reason (e.g. missing the trailing period). * Clean up the copyrights in non-Dart files. (Manual edits.) Also, make sure templates don't have copyrights. * Fix some more ORGANIZATIONNAMEs
171 lines
5.5 KiB
Dart
171 lines
5.5 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 'package:meta/meta.dart';
|
|
import 'package:platform/platform.dart';
|
|
import 'package:yaml/yaml.dart';
|
|
|
|
import 'utils.dart';
|
|
|
|
Platform get platform => _platform ??= const LocalPlatform();
|
|
Platform _platform;
|
|
|
|
/// Loads manifest data from `manifest.yaml` file or from [yaml], if present.
|
|
Manifest loadTaskManifest([ String yaml ]) {
|
|
final dynamic manifestYaml = yaml == null
|
|
? loadYaml(file('manifest.yaml').readAsStringSync())
|
|
: loadYamlNode(yaml);
|
|
|
|
_checkType(manifestYaml is Map, manifestYaml, 'Manifest', 'dictionary');
|
|
return _validateAndParseManifest(manifestYaml);
|
|
}
|
|
|
|
/// Contains CI task information.
|
|
class Manifest {
|
|
Manifest._(this.tasks);
|
|
|
|
/// CI tasks.
|
|
final List<ManifestTask> tasks;
|
|
}
|
|
|
|
/// A CI task.
|
|
class ManifestTask {
|
|
ManifestTask._({
|
|
@required this.name,
|
|
@required this.description,
|
|
@required this.stage,
|
|
@required this.requiredAgentCapabilities,
|
|
@required this.isFlaky,
|
|
@required this.timeoutInMinutes,
|
|
}) {
|
|
final String taskName = 'task "$name"';
|
|
_checkIsNotBlank(name, 'Task name', taskName);
|
|
_checkIsNotBlank(description, 'Task description', taskName);
|
|
_checkIsNotBlank(stage, 'Task stage', taskName);
|
|
_checkIsNotBlank(requiredAgentCapabilities, 'requiredAgentCapabilities', taskName);
|
|
}
|
|
|
|
/// Task name as it appears on the dashboard.
|
|
final String name;
|
|
|
|
/// A human-readable description of the task.
|
|
final String description;
|
|
|
|
/// The stage this task should run in.
|
|
final String stage;
|
|
|
|
/// Capabilities required of the build agent to be able to perform this task.
|
|
final List<String> requiredAgentCapabilities;
|
|
|
|
/// Whether this test is flaky.
|
|
///
|
|
/// Flaky tests are not considered when deciding if the build is broken.
|
|
final bool isFlaky;
|
|
|
|
/// An optional custom timeout specified in minutes.
|
|
final int timeoutInMinutes;
|
|
|
|
/// Whether the task is supported by the current host platform
|
|
bool isSupportedByHost() {
|
|
final Set<String> supportedHosts = Set<String>.from(
|
|
requiredAgentCapabilities.map<String>(
|
|
(String str) => str.split('/')[0]
|
|
)
|
|
);
|
|
String hostPlatform = platform.operatingSystem;
|
|
if (hostPlatform == 'macos') {
|
|
hostPlatform = 'mac'; // package:platform uses 'macos' while manifest.yaml uses 'mac'
|
|
}
|
|
return supportedHosts.contains(hostPlatform);
|
|
}
|
|
}
|
|
|
|
/// Thrown when the manifest YAML is not valid.
|
|
class ManifestError extends Error {
|
|
ManifestError(this.message);
|
|
|
|
final String message;
|
|
|
|
@override
|
|
String toString() => '$ManifestError: $message';
|
|
}
|
|
|
|
// There's no good YAML validator, at least not for Dart, so we validate
|
|
// manually. It's not too much code and produces good error messages.
|
|
Manifest _validateAndParseManifest(Map<dynamic, dynamic> manifestYaml) {
|
|
_checkKeys(manifestYaml, 'manifest', const <String>['tasks']);
|
|
return Manifest._(_validateAndParseTasks(manifestYaml['tasks']));
|
|
}
|
|
|
|
List<ManifestTask> _validateAndParseTasks(dynamic tasksYaml) {
|
|
_checkType(tasksYaml is Map, tasksYaml, 'Value of "tasks"', 'dictionary');
|
|
final List<dynamic> sortedKeys = tasksYaml.keys.toList()..sort();
|
|
return sortedKeys.map<ManifestTask>((dynamic taskName) => _validateAndParseTask(taskName, tasksYaml[taskName])).toList();
|
|
}
|
|
|
|
ManifestTask _validateAndParseTask(dynamic taskName, dynamic taskYaml) {
|
|
_checkType(taskName is String, taskName, 'Task name', 'string');
|
|
_checkType(taskYaml is Map, taskYaml, 'Value of task "$taskName"', 'dictionary');
|
|
_checkKeys(taskYaml, 'Value of task "$taskName"', const <String>[
|
|
'description',
|
|
'stage',
|
|
'required_agent_capabilities',
|
|
'flaky',
|
|
'timeout_in_minutes',
|
|
]);
|
|
|
|
final dynamic isFlaky = taskYaml['flaky'];
|
|
if (isFlaky != null) {
|
|
_checkType(isFlaky is bool, isFlaky, 'flaky', 'boolean');
|
|
}
|
|
|
|
final dynamic timeoutInMinutes = taskYaml['timeout_in_minutes'];
|
|
if (timeoutInMinutes != null) {
|
|
_checkType(timeoutInMinutes is int, timeoutInMinutes, 'timeout_in_minutes', 'integer');
|
|
}
|
|
|
|
final List<dynamic> capabilities = _validateAndParseCapabilities(taskName, taskYaml['required_agent_capabilities']);
|
|
return ManifestTask._(
|
|
name: taskName,
|
|
description: taskYaml['description'],
|
|
stage: taskYaml['stage'],
|
|
requiredAgentCapabilities: capabilities,
|
|
isFlaky: isFlaky ?? false,
|
|
timeoutInMinutes: timeoutInMinutes,
|
|
);
|
|
}
|
|
|
|
List<String> _validateAndParseCapabilities(String taskName, dynamic capabilitiesYaml) {
|
|
_checkType(capabilitiesYaml is List, capabilitiesYaml, 'required_agent_capabilities', 'list');
|
|
for (int i = 0; i < capabilitiesYaml.length; i++) {
|
|
final dynamic capability = capabilitiesYaml[i];
|
|
_checkType(capability is String, capability, 'required_agent_capabilities[$i]', 'string');
|
|
}
|
|
return capabilitiesYaml.cast<String>();
|
|
}
|
|
|
|
void _checkType(bool isValid, dynamic value, String variableName, String typeName) {
|
|
if (!isValid) {
|
|
throw ManifestError(
|
|
'$variableName must be a $typeName but was ${value.runtimeType}: $value',
|
|
);
|
|
}
|
|
}
|
|
|
|
void _checkIsNotBlank(dynamic value, String variableName, String ownerName) {
|
|
if (value == null || value.isEmpty) {
|
|
throw ManifestError('$variableName must not be empty in $ownerName.');
|
|
}
|
|
}
|
|
|
|
void _checkKeys(Map<dynamic, dynamic> map, String variableName, List<String> allowedKeys) {
|
|
for (String key in map.keys) {
|
|
if (!allowedKeys.contains(key)) {
|
|
throw ManifestError(
|
|
'Unrecognized property "$key" in $variableName. '
|
|
'Allowed properties: ${allowedKeys.join(', ')}');
|
|
}
|
|
}
|
|
}
|