Skip to content

Commit f61d682

Browse files
authored
Merge pull request #17 from stellarwp/feature/workflows
Implement pup workflows and add docs
2 parents f868375 + 430116d commit f61d682

30 files changed

+741
-12
lines changed

.puprc-defaults

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"build": [],
33
"build_dev": [],
4+
"workflows": {},
45
"checks": {
56
"tbd": {
67
"fail_method": "error",

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ This is a CLI utility built by [StellarWP](https://stellarwp.com) for running pr
2020
* [`pup check:tbd`](/docs/commands.md#pup-checktbd)
2121
* [`pup check:version-conflict`](/docs/commands.md#pup-checkversion-conflict)
2222
* [`pup clean`](/docs/commands.md#pup-clean)
23+
* [`pup do`](/docs/commands.md#pup-do)
2324
* [`pup get-version`](/docs/commands.md#pup-get-version)
2425
* [`pup help`](/docs/commands.md#pup-help)
2526
* [`pup i18n`](/docs/commands.md#pup-i18n)
2627
* [`pup info`](/docs/commands.md#pup-info)
2728
* [`pup package`](/docs/commands.md#pup-package)
29+
* [`pup workflow`](/docs/commands.md#pup-workflow)
2830
* [`pup zip`](/docs/commands.md#pup-zip)
2931
* [`pup zip-name`](/docs/commands.md#pup-zip-name)
3032
* [Command flow for `pup zip`](/docs/flow.md)
@@ -35,5 +37,9 @@ This is a CLI utility built by [StellarWP](https://stellarwp.com) for running pr
3537
* [Creating custom checks](#creating-custom-checks)
3638
* [Simple checks](#simple-checks)
3739
* [Class-based checks](#class-based-checks)
40+
* [Workflows](/docs/workflows.md)
41+
* [Defining workflows](/docs/workflows.md#defining-workflows)
42+
* [Calling workflows](/docs/workflows.md#calling-workflows)
43+
* [Pseudo-workflows](/docs/workflows.md#pseudo-workflows)
3844
* Examples
3945
* [GitHub Workflow: Zipping](/examples/workflows/zip.yml) - Breaks up the `pup zip` command into multiple steps so debugging is easy.

docs/commands.md

+68
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
* [`pup check:tbd`](/docs/commands.md#pup-checktbd)
66
* [`pup check:version-conflict`](/docs/commands.md#pup-checkversion-conflict)
77
* [`pup clean`](/docs/commands.md#pup-clean)
8+
* [`pup do`](/docs/commands.md#pup-do)
89
* [`pup get-version`](/docs/commands.md#pup-get-version)
910
* [`pup help`](/docs/commands.md#pup-help)
1011
* [`pup i18n`](/docs/commands.md#pup-i18n)
1112
* [`pup info`](/docs/commands.md#pup-info)
1213
* [`pup package`](/docs/commands.md#pup-package)
14+
* [`pup workflow`](/docs/commands.md#pup-workflow)
1315
* [`pup zip`](/docs/commands.md#pup-zip)
1416
* [`pup zip-name`](/docs/commands.md#pup-zip-name)
1517

@@ -129,6 +131,24 @@ composer -- pup clean
129131
|----------|------------------------------------------------------------------------------|
130132
| `--root` | **Optional.** Run the command from a different directory from the current. |
131133

134+
135+
## `pup do`
136+
Alias for `pup workflow`. See `pup help workflow` for more information.
137+
138+
### Usage
139+
```bash
140+
pup do <workflow>
141+
# or
142+
composer -- pup do <workflow>
143+
```
144+
145+
### Arguments
146+
| Argument | Description |
147+
|----------|----------------------------------------------------------------------------------------------------------------------------------------------------|
148+
| `workflow` | **Required.** The workflow you would like to run. |
149+
| `--root` | **Optional.** Run the command from a different directory from the current. |
150+
151+
132152
## `pup get-version`
133153
Gets your project's version number.
134154

@@ -250,6 +270,54 @@ composer -- pup package <version>
250270
| `version` | **Required.** The version number to use when packaging. You can generate this using [`pup get-version`](/docs/commands.md#pup-get-version) if desired. | |
251271
| `--root` | **Optional.** Run the command from a different directory from the current. |
252272

273+
274+
## `pup workflow`
275+
Run a command workflow.
276+
277+
An example workflow might look like this:
278+
279+
```json
280+
{
281+
"workflow": {
282+
"my-workflow": [
283+
"npm ci",
284+
"npm run build",
285+
"@composer run some-script"
286+
]
287+
}
288+
}
289+
```
290+
291+
Executing this workflow would work like this:
292+
293+
```bash
294+
pup workflow my-workflow
295+
# OR
296+
pup do my-workflow
297+
# OR
298+
composer -- pup workflow my-workflow
299+
# OR
300+
composer -- pup do my-workflow
301+
```
302+
303+
### Usage
304+
```bash
305+
pup workflow <workflow>
306+
# or
307+
pup do <workflow>
308+
# or
309+
composer -- pup workflow <workflow>
310+
# or
311+
composer -- pup do <workflow>
312+
```
313+
314+
### Arguments
315+
| Argument | Description |
316+
|----------|----------------------------------------------------------------------------------------------------------------------------------------------------|
317+
| `workflow` | **Required.** The workflow you would like to run. |
318+
| `--root` | **Optional.** Run the command from a different directory from the current. |
319+
320+
253321
## `pup zip`
254322
Runs the full `pup` set of commands to create a zip file.
255323

docs/configuration.md

+11-10
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ root of the project. This file is a JSON file that contains the configuration op
55

66
## Top-level properties
77

8-
| Property | Type | Description |
9-
|-------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------|
10-
| `build` | `array` | An array of CLI commands to execute for the build process of your project. |
11-
| `build_dev` | `array` | An array of CLI commands to execute for the `--dev` build process of your project. If empty, it defaults to the value of `build` |
12-
| `checks` | `object` | An object of check configurations indexed by the check's slug. See the [docs for checks](/docs/checks.md) for more info. |
13-
| `paths` | `object` | An object containing paths used by `pup`. [See below](#paths). |
14-
| `repo` | `string`/`null` | The git repo used to clone the project. If not provided, at github URL is generated based on the `name` property of `composer.json` |
15-
| `zip_use_default_ignore` | `boolean` | Whether or not additionally ignore files based on the [`.distignore-defaults`](/.distignore-defaults) file. Defaults to `true`. |
16-
| `zip_name` | `string` | The name of the zip file to be generated. Defaults to the name of the project as set in `composer.json`. |
8+
| Property | Type | Description |
9+
|-------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
10+
| `build` | `array` | An array of CLI commands to execute for the build process of your project. |
11+
| `build_dev` | `array` | An array of CLI commands to execute for the `--dev` build process of your project. If empty, it defaults to the value of `build` |
12+
| `checks` | `object` | An object of check configurations indexed by the check's slug. See the [docs for checks](/docs/checks.md) for more info. |
13+
| `paths` | `object` | An object containing paths used by `pup`. [See below](#paths). |
14+
| `repo` | `string`/`null` | The git repo used to clone the project in the format of `<org>/<repo>`. If not provided, at github URL is generated based on the `name` property of `composer.json` |
15+
| `workflows` | `object` | An object of workflow configurations. The index is the workflow slug and the values are arrays of strings that hold commands. See the [docs for workflows](/docs/workflows.md) for more info. |
16+
| `zip_use_default_ignore` | `boolean` | Whether or not additionally ignore files based on the [`.distignore-defaults`](/.distignore-defaults) file. Defaults to `true`. |
17+
| `zip_name` | `string` | The name of the zip file to be generated. Defaults to the name of the project as set in `composer.json`. |
1718

1819
## Paths
1920

@@ -135,4 +136,4 @@ This is what you should add as a `paths.versions` entry:
135136
]
136137
}
137138
}
138-
```
139+
```

docs/workflows.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Workflows
2+
3+
Workflows are a way to declare a series of commands that you want to run in a specific order. This allows you to specify
4+
workflows that differ from the `build` and `build_dev` commands.
5+
6+
* [Defining workflows](#defining-workflows)
7+
* [Calling workflows](#calling-workflows)
8+
* [Pseudo-workflows](#pseudo-workflows)
9+
10+
## Defining workflows
11+
12+
Workflows are defined in the `workflows` property of your `.puprc` file.
13+
14+
```json
15+
{
16+
"workflows": {
17+
"my-workflow": [
18+
"npm ci",
19+
"npm run build",
20+
"@composer run some-script"
21+
],
22+
"my-other-workflow": [
23+
"@composer run some-other-script",
24+
"@composer run make-pot"
25+
]
26+
}
27+
}
28+
```
29+
30+
## Calling workflows
31+
32+
You can call a workflow by running the `workflow` command (or its alias `do`) with the name of the workflow as an argument.
33+
34+
```bash
35+
pup workflow my-workflow
36+
# OR
37+
pup do my-workflow
38+
```
39+
40+
## Pseudo-workflows
41+
42+
The `build` and `build_dev` properties within your `.puprc` file are also callable via the `workflow` command.
43+
44+
```bash
45+
pup workflow build
46+
```

pup

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace StellarWP\Pup;
55

6-
const PUP_VERSION = '1.2.5';
6+
const PUP_VERSION = '1.3.0';
77
define( '__PUP_DIR__', __DIR__ );
88

99
if ( ! \Phar::running() ) {

src/App.php

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public function __construct( string $version ) {
6161
$this->add( new Commands\I18n() );
6262
$this->add( new Commands\Info() );
6363
$this->add( new Commands\Package() );
64+
$this->add( new Commands\Workflow() );
6465
$this->add( new Commands\Zip() );
6566
$this->add( new Commands\ZipName() );
6667

src/Commands/Workflow.php

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace StellarWP\Pup\Commands;
4+
5+
use StellarWP\Pup\App;
6+
use StellarWP\Pup\Exceptions\BaseException;
7+
use StellarWP\Pup\Command\Command;
8+
use Symfony\Component\Console\Input\InputArgument;
9+
use Symfony\Component\Console\Input\InputInterface;
10+
use Symfony\Component\Console\Input\InputOption;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
13+
class Workflow extends Command {
14+
/**
15+
* @inheritDoc
16+
*
17+
* @return void
18+
*/
19+
protected function configure() {
20+
$this->setName( 'workflow' )
21+
->setAliases( [ 'do' ] )
22+
->addArgument( 'workflow', InputArgument::REQUIRED, 'The workflow you would like to run.' )
23+
->addOption( 'root', null, InputOption::VALUE_REQUIRED, 'Set the root directory for running commands.' )
24+
->setDescription( 'Run a command workflow.' )
25+
->setHelp( 'Run a command workflow.' );
26+
}
27+
28+
/**
29+
* @inheritDoc
30+
*/
31+
protected function execute( InputInterface $input, OutputInterface $output ) {
32+
parent::execute( $input, $output );
33+
$config = App::getConfig();
34+
$root = $input->getOption( 'root' );
35+
$workflow_slug = $input->getArgument( 'workflow' );
36+
$io = $this->getIO();
37+
$application = $this->getApplication();
38+
if ( ! $application ) {
39+
throw new BaseException( 'Could not run pup.' );
40+
}
41+
42+
$collection = $config->getWorkflows();
43+
44+
if ( $collection->count() === 0 ) {
45+
$io->writeln( '📣 The .puprc does not have any workflows configured.' );
46+
$io->writeln( '💡 If you would like to use workflows, simply add a "<comment>workflows</comment>" property in <comment>.puprc</comment> similar to:' );
47+
$io->writeln( '' );
48+
$io->writeln( '"workflows": {' );
49+
$io->writeln( ' "my-workflow": [' );
50+
$io->writeln( ' "composer install",' );
51+
$io->writeln( ' "npm run build"' );
52+
$io->writeln( ' ]' );
53+
$io->writeln( '}' );
54+
$io->writeln( '' );
55+
return 0;
56+
}
57+
58+
$workflow = $collection->get( $workflow_slug );
59+
if ( ! $workflow ) {
60+
$io->writeln( "<error>The workflow '{$workflow_slug}' does not exist.</error>" );
61+
return 1;
62+
}
63+
64+
if ( $root ) {
65+
chdir( $root );
66+
}
67+
68+
$io->writeln( "<comment>Running {$workflow_slug} workflow steps...</comment>" );
69+
foreach ( $workflow->getCommands() as $step ) {
70+
$bail_on_failure = true;
71+
if ( strpos( $step, '@' ) === 0 ) {
72+
$bail_on_failure = false;
73+
$step = substr( $step, 1 );
74+
}
75+
$io->section( "> <fg=cyan>{$step}</>" );
76+
system( $step, $result );
77+
$io->newLine();
78+
79+
if ( $result ) {
80+
$io->writeln( "[FAIL] Workflow step failed: {$step}" );
81+
82+
if ( $bail_on_failure ) {
83+
$io->writeln( "<fg=red>Exiting...</>" );
84+
return $result;
85+
}
86+
}
87+
88+
if ( $root ) {
89+
chdir( $config->getWorkingDir() );
90+
}
91+
92+
$io->writeln( '<info>Workflow complete.</info>' );
93+
}
94+
95+
return 0;
96+
}
97+
}

src/Config.php

+35
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,37 @@ public function __construct() {
6060
$this->puprc_file_path = $this->working_dir . '.puprc';
6161

6262
$this->mergeConfigWithDefaults();
63+
$this->buildWorkflows();
6364
$this->parseCheckConfig();
6465
$this->parseVersionFiles();
6566
$this->validateConfig();
6667
}
6768

69+
/**
70+
* Builds the workflows from the config.
71+
*
72+
* @return void
73+
*/
74+
public function buildWorkflows() {
75+
$collection = new Workflow\Collection();
76+
77+
if ( empty( $this->config->workflows->build ) && ! empty( $this->config->build ) ) {
78+
$collection->add( new Workflow\Workflow( 'build', $this->config->build ) );
79+
}
80+
81+
if ( empty( $this->config->workflows->build_dev ) && ! empty( $this->config->build_dev ) ) {
82+
$collection->add( new Workflow\Workflow( 'build_dev', $this->config->build_dev ) );
83+
}
84+
85+
if ( ! empty( $this->config->workflows ) ) {
86+
foreach ( $this->config->workflows as $slug => $commands ) {
87+
$collection->add( new Workflow\Workflow( $slug, $commands ) );
88+
}
89+
}
90+
91+
$this->config->workflows = $collection;
92+
}
93+
6894
/**
6995
* Merges the local .puprc (if it exists) with the default .puprc-defaults.
7096
*
@@ -478,6 +504,15 @@ public function getVersionFiles() : array {
478504
return $this->config->paths['versions'];
479505
}
480506

507+
/**
508+
* Get the workflows from the config.
509+
*
510+
* @return Workflow\Collection
511+
*/
512+
public function getWorkflows(): Workflow\Collection {
513+
return $this->config->workflows;
514+
}
515+
481516
/**
482517
* @return string
483518
*/

src/VersionFile.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ public function getRegex(): string {
4949
/**
5050
* @inheritdoc
5151
*/
52+
#[\ReturnTypeWillChange]
5253
public function jsonSerialize() {
5354
return [
5455
'file' => $this->getPath(),
5556
'regex' => $this->getRegex(),
5657
];
5758
}
58-
}
59+
}

0 commit comments

Comments
 (0)