Skip to content

Commit

Permalink
Add blog post.
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj committed Aug 14, 2023
1 parent f896c74 commit a7fe662
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 19 deletions.
36 changes: 17 additions & 19 deletions nextgen/task-builder/src/tasks_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ use std::hash::Hash;
use std::path::Path;
use tracing::trace;

// This is a standalone function as recursive closures are not possible!
fn extract_config<'builder, 'proj>(
task_id: &'builder Id,
tasks_map: &'builder FxHashMap<&'proj Id, &'proj TaskConfig>,
configs: &'builder mut Vec<&'proj TaskConfig>,
) {
if let Some(config) = tasks_map.get(task_id) {
if let Some(extend_task_id) = &config.extends {
extract_config(extend_task_id, tasks_map, configs);
}

configs.push(*config);
}
}

#[derive(Debug)]
pub struct DetectPlatformEvent {
pub enabled_platforms: Vec<PlatformType>,
Expand Down Expand Up @@ -529,25 +544,8 @@ impl<'proj> TasksBuilder<'proj> {
fn get_config_inherit_chain(&self, id: &Id) -> Vec<&TaskConfig> {
let mut configs = vec![];

if let Some(config) = self.global_tasks.get(id) {
if let Some(extends_from) = &config.extends {
if let Some(extends_config) = self.global_tasks.get(extends_from) {
configs.push(*extends_config);
}
}

configs.push(*config);
}

if let Some(config) = self.local_tasks.get(id) {
if let Some(extends_from) = &config.extends {
if let Some(extends_config) = self.local_tasks.get(extends_from) {
configs.push(*extends_config);
}
}

configs.push(*config);
}
extract_config(id, &self.global_tasks, &mut configs);
extract_config(id, &self.local_tasks, &mut configs);

configs
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ tasks:
options:
mergeArgs: prepend

extend-args-again:
extends: extend-args
args: --bail
options:
mergeArgs: append

extend-inputs:
extends: base
inputs:
Expand Down
10 changes: 10 additions & 0 deletions nextgen/task-builder/tests/tasks_builder_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,5 +1197,15 @@ mod tasks_builder {
assert!(task.options.persistent);
assert_eq!(task.options.retry_count, 3);
}

#[tokio::test]
async fn can_create_extends_chains() {
let sandbox = create_sandbox("builder");
let tasks = build_tasks(sandbox.path(), "extends/moon.yml").await;
let task = tasks.get("extend-args-again").unwrap();

assert_eq!(task.command, "lint");
assert_eq!(task.args, vec!["./src", "--fix", "--bail"]);
}
}
}
7 changes: 7 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Unreleased

#### 🚀 Updates

- Added an `extends` field to task configurations. This allows tasks to extend and inherit settings
from sibling tasks.

## 1.11.1

#### 🐞 Fixes
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/tasks-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface PartialTaskConfig {
command?: PartialTaskCommandArgs | null;
deps?: string[] | null;
env?: Record<string, string> | null;
extends?: string | null;
inputs?: string[] | null;
local?: boolean | null;
options?: PartialTaskOptionsConfig | null;
Expand Down Expand Up @@ -82,6 +83,7 @@ export interface TaskConfig {
command: TaskCommandArgs;
deps: string[];
env: Record<string, string>;
extends: string | null;
inputs: string[] | null;
local: boolean | null;
options: TaskOptionsConfig;
Expand Down
92 changes: 92 additions & 0 deletions website/blog/2023-08-21_moon-v1.12.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
slug: moon-v1.12
title: moon v1.12 - Task extending
authors: [milesj]
tags: [tasks, inheritance]
# image: ./img/moon/v1.11.png
---

???

<!--truncate-->

## Extending sibling or inherited tasks

Three months ago, we posted an
[RFC on how to support task extending / task variants](https://github.com/moonrepo/moon/issues/849).
On paper this doesn't sound like a hard problem to solve, but internally it would of been an uphill
battle to implement. Thanks to previous releases from the past few months, and the rewrite of the
project graph, task builder, and more, this implementation was a breeze. To finalize the RFC, we
went with option 2, by adding a new `extends` field to task configurations.

With this new addition, we can now rewrite this old configuration, which was needlessly
repetitive...

```yaml title="moon.yml"
tasks:
lint:
command: 'eslint .'
inputs:
- '@globs(sources)'
- '@globs(tests)'
- '*.js'
- '.eslintrc.js'
- 'tsconfig.json'
- '/.eslintignore'
- '/.eslintrc.js'
- '/tsconfig.eslint.json'
- '/tsconfig.options.json'

lint-fix:
command: 'eslint . --fix'
local: true
inputs:
- '@globs(sources)'
- '@globs(tests)'
- '*.js'
- '.eslintrc.js'
- 'tsconfig.json'
- '/.eslintignore'
- '/.eslintrc.js'
- '/tsconfig.eslint.json'
- '/tsconfig.options.json'
```

Into the following configuration.

```yaml title="moon.yml"
tasks:
lint:
command: 'eslint .'
inputs:
- '@globs(sources)'
- '@globs(tests)'
- '*.js'
- '.eslintrc.js'
- 'tsconfig.json'
- '/.eslintignore'
- '/.eslintrc.js'
- '/tsconfig.eslint.json'
- '/tsconfig.options.json'

lint-fix:
extends: 'lint'
args: '--fix'
local: true
```

We're very happy with this solution, as it's far more readable, maintainable, and doesn't introduce
yet another paradigm to learn. Our goal was to be as familiar as possible, while providing extensive
functionality behind the scenes, which we believe to have achieved.

Some other interesting facts around task extending:

- When extending a task, [merge strategies](/docs/concepts/task#merge-strategies) are applied in a
similar fashion to inheritance.
- Inherited tasks can be extended from by project-level tasks.
- It's possible to create multiple extended chains.

## Other changes

View the [official release](https://github.com/moonrepo/moon/releases/tag/v1.12.0) for a full list
of changes.
24 changes: 24 additions & 0 deletions website/docs/config/project.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,30 @@ tasks:
command: 'tsc'
```

### `extends`<VersionLabel version="1.12.0" />

<HeadingApiLink to="/api/types/interface/TaskConfig#extends" />

The `extends` field can be used to extend the settings from a sibling task within the same project,
or [inherited from the global scope](../concepts/task#inheritance). This is useful for composing
similar tasks with different arguments or options.

When extending another task, the same [merge strategies](../concepts/task#merge-strategies) used for
inheritance are applied.

```yaml title="moon.yml"
tasks:
lint:
command: 'eslint .'
inputs:
- 'src/**/*'
lint-fix:
extends: 'lint'
args: '--fix'
local: true
```

### `command`<RequiredLabel />

<HeadingApiLink to="/api/types/interface/TaskConfig#command" />
Expand Down
10 changes: 10 additions & 0 deletions website/static/schemas/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,16 @@
}
]
},
"extends": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"inputs": {
"anyOf": [
{
Expand Down
10 changes: 10 additions & 0 deletions website/static/schemas/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,16 @@
}
]
},
"extends": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"inputs": {
"anyOf": [
{
Expand Down

0 comments on commit a7fe662

Please sign in to comment.