Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

an implementation of the init command #293

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mono_repo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Global options:
Available commands:
check Check the state of the repository.
generate Generates the CI configuration for child packages.
init Scaffold a new mono repo.
presubmit Run the CI presubmits locally.
pub Run `pub get` or `pub upgrade` against all packages.
travis (Deprecated, use `generate`) Configure Travis-CI for child packages.
Expand Down
105 changes: 105 additions & 0 deletions mono_repo/lib/src/commands/init.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright (c) 2020, 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:io';

import 'package:args/command_runner.dart';
import 'package:io/ansi.dart';
import 'package:path/path.dart' as p;

const _pubspecFileName = 'pubspec.yaml';
const _pkgCfgFileName = 'mono_pkg.yaml';
const _repoCfgFileName = 'mono_repo.yaml';
const _recursiveScanFlag = 'recursive';

const _repoCfgContents = r'''
# See with https://github.com/dart-lang/mono_repo for details on this file
self_validate: analyze_and_format

github:
# Setting just `cron` keeps the defaults for `push` and `pull_request`
cron: '0 0 * * 0'
on_completion:
- name: "Notify failure"
runs-on: ubuntu-latest
# Run only if other jobs have failed and this is a push or scheduled build.
if: (github.event_name == 'push' || github.event_name == 'schedule') && failure()
steps:
- run: >
curl -H "Content-Type: application/json" -X POST -d \
"{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \
"${CHAT_WEBHOOK_URL}"
env:
CHAT_WEBHOOK_URL: ${{ secrets.BUILD_AND_TEST_TEAM_CHAT_WEBHOOK_URL }}
Comment on lines +27 to +34
Copy link
Collaborator

@jakemac53 jakemac53 Dec 17, 2020

Choose a reason for hiding this comment

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

This section should be commented out, as it won't work without some repo level configuration and it is also specific to the expected payload for google chat webhooks and won't work for slack, etc.

Suggested change
if: (github.event_name == 'push' || github.event_name == 'schedule') && failure()
steps:
- run: >
curl -H "Content-Type: application/json" -X POST -d \
"{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \
"${CHAT_WEBHOOK_URL}"
env:
CHAT_WEBHOOK_URL: ${{ secrets.BUILD_AND_TEST_TEAM_CHAT_WEBHOOK_URL }}
# if: (github.event_name == 'push' || github.event_name == 'schedule') && failure()
# steps:
# - run: >
# curl -H "Content-Type: application/json" -X POST -d \
# # Note that this is specific to google chat webhook format - other services expect
# # a different looking JSON payload.
# "{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \
# "${CHAT_WEBHOOK_URL}"
# env:
# CHAT_WEBHOOK_URL: ${{ secrets.<your-github-secret-id> }}


merge_stages:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
merge_stages:
# Merges all tasks from this stage across all packages into a single job, where possible.
# This speeds up CI runs when you have lots of very small tasks.
merge_stages:

- analyze_and_format
''';

const _pkgCfgContents = r'''
dart:
- dev
- stable

os:
- linux

stages:
- analyze_and_format:
- dartanalyzer: --fatal-infos --fatal-warnings .
- dartfmt: sdk
- unit_test:
- test:
''';

class InitCommand extends Command<void> {
@override
String get name => 'init';

@override
String get description => 'Scaffold a new mono repo.';

@override
void run() => scaffold(p.current, globalResults[_recursiveScanFlag] as bool);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This command should use its own arg parser and then use argResults here - see the generatecommand for an example. Then we can set the default as well (it should be false, imo).

}

void scaffold(String rootDir, bool recursive) {
configureDirectory(rootDir, recursive: recursive);
}

void configureDirectory(String rootDir,
{String currentDir, bool recursive = false}) {
currentDir ??= rootDir;

if (currentDir == rootDir) {
final repoCfgPath = p.join(rootDir, _repoCfgFileName);
if (!File(repoCfgPath).existsSync()) {
File(repoCfgPath).writeAsStringSync(_repoCfgContents);
print(styleBold.wrap('Added $_repoCfgFileName to $rootDir'));
} else {
print(yellow.wrap('$_repoCfgFileName already present in $rootDir.'));
}
} else {
final pkgCfgPath = p.join(currentDir, _pkgCfgFileName);
final pubspecPath = p.join(currentDir, _pubspecFileName);

if (File(pubspecPath).existsSync()) {
if (!File(pkgCfgPath).existsSync()) {
File(pkgCfgPath).writeAsStringSync(_pkgCfgContents);
print(styleBold.wrap('Added $_pkgCfgFileName to $currentDir'));
} else {
print(yellow.wrap('$_pkgCfgFileName already present in $currentDir'));
}
}
}

final subdirs =
Directory(currentDir).listSync().whereType<Directory>().toList();
for (var subdir in subdirs) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am a bit on the fence about this behavior - especially in the case of pre-existing packages we wouldn't want to go creating a whole bunch of pubspecs in all nested packages.

I am somewhat inclined to just not support this for the init command at all - or we could remove the behavior that creates a new package in all directories where a pubspec did not exist before.

Copy link
Author

@hathibelagal-dev hathibelagal-dev Dec 11, 2020

Choose a reason for hiding this comment

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

If we add the mono_pkg.yaml only to directories that already have a pubspec.yaml, we're assuming the user is never starting from scratch.

And I was initially adding the mono_pkg.yaml file only to the immediate subdirectories of root. But directory structures such as root/pkgs/package1,package2 are common too, so doing it recursively seemed to make more sense. But this would add the files in the pkgs directory too, which would be wrong.

Copy link
Author

Choose a reason for hiding this comment

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

I think it would be safest to add the mono_pkg.yaml only to directories that have a pubspec.yaml.

if (recursive || currentDir == rootDir) {
configureDirectory(rootDir,
currentDir: subdir.path, recursive: recursive);
}
}
}
2 changes: 2 additions & 0 deletions mono_repo/lib/src/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:args/command_runner.dart';

import 'commands/check.dart';
import 'commands/generate.dart';
import 'commands/init.dart';
import 'commands/mono_repo_command.dart';
import 'commands/presubmit.dart';
import 'commands/pub.dart';
Expand All @@ -19,6 +20,7 @@ final commands = List<Command<void>>.unmodifiable(
[
CheckCommand(),
GenerateCommand(),
InitCommand(),
PresubmitCommand(),
PubCommand(),
TravisCommand(),
Expand Down
32 changes: 32 additions & 0 deletions mono_repo/test/init_command_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

import 'package:mono_repo/src/commands/init.dart';

void main() {
const repoCfgFileName = 'mono_repo.yaml';
const pkgCfgFileName = 'mono_pkg.yaml';

test('scaffold a new mono repo', () async {
await d.dir('top_level', [
d.dir('package1', [d.file('pubspec.yaml')]),
d.dir('package2', [d.file('pubspec.yaml')])
]).create();
final rootDirectory = '${d.sandbox}/top_level';
final package1Directory = '${d.sandbox}/top_level/package1';
final package2Directory = '${d.sandbox}/top_level/package2';

final repoCfg = p.join(rootDirectory, repoCfgFileName);
final pkg1Cfg = p.join(package1Directory, pkgCfgFileName);
final pkg2Cfg = p.join(package2Directory, pkgCfgFileName);
scaffold(rootDirectory, false);
expect(
File(repoCfg).existsSync() &&
File(pkg1Cfg).existsSync() &&
File(pkg2Cfg).existsSync(),
equals(true));
});
}
1 change: 1 addition & 0 deletions mono_repo/test/mono_repo_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Global options:
Available commands:
check Check the state of the repository.
generate Generates the CI configuration for child packages.
init Scaffold a new mono repo.
presubmit Run the CI presubmits locally.
pub Run `pub get` or `pub upgrade` against all packages.
travis (Deprecated, use `generate`) Configure Travis-CI for child packages.
Expand Down