blob: 9b45f7c661d60d238e23dcca106c1ae88f74cfe4 [file] [log] [blame]
// Copyright 2024, the Dart project authors. Please see the AUTHORS file
// for details. 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:convert';
import 'package:crypto/crypto.dart';
import 'package:file/file.dart';
import 'command.dart';
import 'package.dart';
import 'provenance.dart';
/// A [Package] whose artifacts are uploaded to "go/cipd".
///
/// The [upload] method uploads the files in the artifacts directory to a CIPD
/// package. The [name] becomes the packages CIPD path.
/// In [dryRun] mode, the [upload] method merely prints the 1st level contents
/// instead of uploading them.
abstract class CipdPackage extends Package {
final String version;
CipdPackage(String name, Uri source, this.version) : super(name, source);
/// Upload the files in the [artifacts] directory to go/cipd.
@override
Future<void> upload(Directory artifacts, bool provenance) async {
if (await isAlreadyUploaded()) {
throw StateError('Attempted to re-upload existing CIPD version');
}
final zip = artifacts.parent.childFile('${artifacts.basename}.zip');
final jsonOutput = artifacts.parent.childFile('${artifacts.basename}.json');
final buildArguments = [
'pkg-build',
'-name',
name,
'-in',
artifacts.path,
'-install-mode',
'copy',
'-out',
zip.path,
'-json-output',
jsonOutput.path,
];
log.info('Running cipd ${buildArguments.join(' ')}...');
await Command('cipd', buildArguments).run(raise: true);
final instanceId =
jsonDecode(await jsonOutput.readAsString())['result']['instance_id'];
final digest = sha256.convert(await zip.readAsBytes()).toString();
final registerArguments = [
'pkg-register',
zip.path,
'-ref',
'latest',
'-tag',
'version:$version',
];
log.info('Produced $name instance $instanceId with digest $digest');
log.info('Running cipd ${registerArguments.join(' ')}...');
if (isDryRun) {
final files = (await artifacts.list(recursive: true).toList()).join('\n');
log.info("Files that would've been included:\n $files");
} else {
await Command('cipd', registerArguments).run(raise: true);
if (provenance) {
provenanceReportCipd(name, digest, instanceId);
}
}
log.info('Finished running cipd create for $name.');
}
Future<bool> isAlreadyUploaded() async {
final arguments = [
'resolve',
'-version',
'version:$version',
name,
];
log.info('Running cipd ${arguments.join(' ')}...');
final result = await Command('cipd', arguments).run();
return result.exitCode == 0;
}
}