Skip to content

Commit

Permalink
Merge pull request #17 from stellarwp/feature/workflows
Browse files Browse the repository at this point in the history
Implement pup workflows and add docs
  • Loading branch information
borkweb authored Apr 25, 2024
2 parents f868375 + 430116d commit f61d682
Show file tree
Hide file tree
Showing 30 changed files with 741 additions and 12 deletions.
1 change: 1 addition & 0 deletions .puprc-defaults
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"build": [],
"build_dev": [],
"workflows": {},
"checks": {
"tbd": {
"fail_method": "error",
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ This is a CLI utility built by [StellarWP](https://stellarwp.com) for running pr
* [`pup check:tbd`](/docs/commands.md#pup-checktbd)
* [`pup check:version-conflict`](/docs/commands.md#pup-checkversion-conflict)
* [`pup clean`](/docs/commands.md#pup-clean)
* [`pup do`](/docs/commands.md#pup-do)
* [`pup get-version`](/docs/commands.md#pup-get-version)
* [`pup help`](/docs/commands.md#pup-help)
* [`pup i18n`](/docs/commands.md#pup-i18n)
* [`pup info`](/docs/commands.md#pup-info)
* [`pup package`](/docs/commands.md#pup-package)
* [`pup workflow`](/docs/commands.md#pup-workflow)
* [`pup zip`](/docs/commands.md#pup-zip)
* [`pup zip-name`](/docs/commands.md#pup-zip-name)
* [Command flow for `pup zip`](/docs/flow.md)
Expand All @@ -35,5 +37,9 @@ This is a CLI utility built by [StellarWP](https://stellarwp.com) for running pr
* [Creating custom checks](#creating-custom-checks)
* [Simple checks](#simple-checks)
* [Class-based checks](#class-based-checks)
* [Workflows](/docs/workflows.md)
* [Defining workflows](/docs/workflows.md#defining-workflows)
* [Calling workflows](/docs/workflows.md#calling-workflows)
* [Pseudo-workflows](/docs/workflows.md#pseudo-workflows)
* Examples
* [GitHub Workflow: Zipping](/examples/workflows/zip.yml) - Breaks up the `pup zip` command into multiple steps so debugging is easy.
68 changes: 68 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
* [`pup check:tbd`](/docs/commands.md#pup-checktbd)
* [`pup check:version-conflict`](/docs/commands.md#pup-checkversion-conflict)
* [`pup clean`](/docs/commands.md#pup-clean)
* [`pup do`](/docs/commands.md#pup-do)
* [`pup get-version`](/docs/commands.md#pup-get-version)
* [`pup help`](/docs/commands.md#pup-help)
* [`pup i18n`](/docs/commands.md#pup-i18n)
* [`pup info`](/docs/commands.md#pup-info)
* [`pup package`](/docs/commands.md#pup-package)
* [`pup workflow`](/docs/commands.md#pup-workflow)
* [`pup zip`](/docs/commands.md#pup-zip)
* [`pup zip-name`](/docs/commands.md#pup-zip-name)

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


## `pup do`
Alias for `pup workflow`. See `pup help workflow` for more information.

### Usage
```bash
pup do <workflow>
# or
composer -- pup do <workflow>
```

### Arguments
| Argument | Description |
|----------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `workflow` | **Required.** The workflow you would like to run. |
| `--root` | **Optional.** Run the command from a different directory from the current. |


## `pup get-version`
Gets your project's version number.

Expand Down Expand Up @@ -250,6 +270,54 @@ composer -- pup package <version>
| `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. | |
| `--root` | **Optional.** Run the command from a different directory from the current. |


## `pup workflow`
Run a command workflow.

An example workflow might look like this:

```json
{
"workflow": {
"my-workflow": [
"npm ci",
"npm run build",
"@composer run some-script"
]
}
}
```

Executing this workflow would work like this:

```bash
pup workflow my-workflow
# OR
pup do my-workflow
# OR
composer -- pup workflow my-workflow
# OR
composer -- pup do my-workflow
```

### Usage
```bash
pup workflow <workflow>
# or
pup do <workflow>
# or
composer -- pup workflow <workflow>
# or
composer -- pup do <workflow>
```

### Arguments
| Argument | Description |
|----------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `workflow` | **Required.** The workflow you would like to run. |
| `--root` | **Optional.** Run the command from a different directory from the current. |


## `pup zip`
Runs the full `pup` set of commands to create a zip file.

Expand Down
21 changes: 11 additions & 10 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ root of the project. This file is a JSON file that contains the configuration op

## Top-level properties

| Property | Type | Description |
|-------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------|
| `build` | `array` | An array of CLI commands to execute for the build process of your project. |
| `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` |
| `checks` | `object` | An object of check configurations indexed by the check's slug. See the [docs for checks](/docs/checks.md) for more info. |
| `paths` | `object` | An object containing paths used by `pup`. [See below](#paths). |
| `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` |
| `zip_use_default_ignore` | `boolean` | Whether or not additionally ignore files based on the [`.distignore-defaults`](/.distignore-defaults) file. Defaults to `true`. |
| `zip_name` | `string` | The name of the zip file to be generated. Defaults to the name of the project as set in `composer.json`. |
| Property | Type | Description |
|-------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `build` | `array` | An array of CLI commands to execute for the build process of your project. |
| `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` |
| `checks` | `object` | An object of check configurations indexed by the check's slug. See the [docs for checks](/docs/checks.md) for more info. |
| `paths` | `object` | An object containing paths used by `pup`. [See below](#paths). |
| `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` |
| `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. |
| `zip_use_default_ignore` | `boolean` | Whether or not additionally ignore files based on the [`.distignore-defaults`](/.distignore-defaults) file. Defaults to `true`. |
| `zip_name` | `string` | The name of the zip file to be generated. Defaults to the name of the project as set in `composer.json`. |

## Paths

Expand Down Expand Up @@ -135,4 +136,4 @@ This is what you should add as a `paths.versions` entry:
]
}
}
```
```
46 changes: 46 additions & 0 deletions docs/workflows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Workflows

Workflows are a way to declare a series of commands that you want to run in a specific order. This allows you to specify
workflows that differ from the `build` and `build_dev` commands.

* [Defining workflows](#defining-workflows)
* [Calling workflows](#calling-workflows)
* [Pseudo-workflows](#pseudo-workflows)

## Defining workflows

Workflows are defined in the `workflows` property of your `.puprc` file.

```json
{
"workflows": {
"my-workflow": [
"npm ci",
"npm run build",
"@composer run some-script"
],
"my-other-workflow": [
"@composer run some-other-script",
"@composer run make-pot"
]
}
}
```

## Calling workflows

You can call a workflow by running the `workflow` command (or its alias `do`) with the name of the workflow as an argument.

```bash
pup workflow my-workflow
# OR
pup do my-workflow
```

## Pseudo-workflows

The `build` and `build_dev` properties within your `.puprc` file are also callable via the `workflow` command.

```bash
pup workflow build
```
2 changes: 1 addition & 1 deletion pup
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace StellarWP\Pup;

const PUP_VERSION = '1.2.5';
const PUP_VERSION = '1.3.0';
define( '__PUP_DIR__', __DIR__ );

if ( ! \Phar::running() ) {
Expand Down
1 change: 1 addition & 0 deletions src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public function __construct( string $version ) {
$this->add( new Commands\I18n() );
$this->add( new Commands\Info() );
$this->add( new Commands\Package() );
$this->add( new Commands\Workflow() );
$this->add( new Commands\Zip() );
$this->add( new Commands\ZipName() );

Expand Down
97 changes: 97 additions & 0 deletions src/Commands/Workflow.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace StellarWP\Pup\Commands;

use StellarWP\Pup\App;
use StellarWP\Pup\Exceptions\BaseException;
use StellarWP\Pup\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class Workflow extends Command {
/**
* @inheritDoc
*
* @return void
*/
protected function configure() {
$this->setName( 'workflow' )
->setAliases( [ 'do' ] )
->addArgument( 'workflow', InputArgument::REQUIRED, 'The workflow you would like to run.' )
->addOption( 'root', null, InputOption::VALUE_REQUIRED, 'Set the root directory for running commands.' )
->setDescription( 'Run a command workflow.' )
->setHelp( 'Run a command workflow.' );
}

/**
* @inheritDoc
*/
protected function execute( InputInterface $input, OutputInterface $output ) {
parent::execute( $input, $output );
$config = App::getConfig();
$root = $input->getOption( 'root' );
$workflow_slug = $input->getArgument( 'workflow' );
$io = $this->getIO();
$application = $this->getApplication();
if ( ! $application ) {
throw new BaseException( 'Could not run pup.' );
}

$collection = $config->getWorkflows();

if ( $collection->count() === 0 ) {
$io->writeln( '📣 The .puprc does not have any workflows configured.' );
$io->writeln( '💡 If you would like to use workflows, simply add a "<comment>workflows</comment>" property in <comment>.puprc</comment> similar to:' );
$io->writeln( '' );
$io->writeln( '"workflows": {' );
$io->writeln( ' "my-workflow": [' );
$io->writeln( ' "composer install",' );
$io->writeln( ' "npm run build"' );
$io->writeln( ' ]' );
$io->writeln( '}' );
$io->writeln( '' );
return 0;
}

$workflow = $collection->get( $workflow_slug );
if ( ! $workflow ) {
$io->writeln( "<error>The workflow '{$workflow_slug}' does not exist.</error>" );
return 1;
}

if ( $root ) {
chdir( $root );
}

$io->writeln( "<comment>Running {$workflow_slug} workflow steps...</comment>" );
foreach ( $workflow->getCommands() as $step ) {
$bail_on_failure = true;
if ( strpos( $step, '@' ) === 0 ) {
$bail_on_failure = false;
$step = substr( $step, 1 );
}
$io->section( "> <fg=cyan>{$step}</>" );
system( $step, $result );
$io->newLine();

if ( $result ) {
$io->writeln( "[FAIL] Workflow step failed: {$step}" );

if ( $bail_on_failure ) {
$io->writeln( "<fg=red>Exiting...</>" );
return $result;
}
}

if ( $root ) {
chdir( $config->getWorkingDir() );
}

$io->writeln( '<info>Workflow complete.</info>' );
}

return 0;
}
}
35 changes: 35 additions & 0 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,37 @@ public function __construct() {
$this->puprc_file_path = $this->working_dir . '.puprc';

$this->mergeConfigWithDefaults();
$this->buildWorkflows();
$this->parseCheckConfig();
$this->parseVersionFiles();
$this->validateConfig();
}

/**
* Builds the workflows from the config.
*
* @return void
*/
public function buildWorkflows() {
$collection = new Workflow\Collection();

if ( empty( $this->config->workflows->build ) && ! empty( $this->config->build ) ) {
$collection->add( new Workflow\Workflow( 'build', $this->config->build ) );
}

if ( empty( $this->config->workflows->build_dev ) && ! empty( $this->config->build_dev ) ) {
$collection->add( new Workflow\Workflow( 'build_dev', $this->config->build_dev ) );
}

if ( ! empty( $this->config->workflows ) ) {
foreach ( $this->config->workflows as $slug => $commands ) {
$collection->add( new Workflow\Workflow( $slug, $commands ) );
}
}

$this->config->workflows = $collection;
}

/**
* Merges the local .puprc (if it exists) with the default .puprc-defaults.
*
Expand Down Expand Up @@ -478,6 +504,15 @@ public function getVersionFiles() : array {
return $this->config->paths['versions'];
}

/**
* Get the workflows from the config.
*
* @return Workflow\Collection
*/
public function getWorkflows(): Workflow\Collection {
return $this->config->workflows;
}

/**
* @return string
*/
Expand Down
3 changes: 2 additions & 1 deletion src/VersionFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ public function getRegex(): string {
/**
* @inheritdoc
*/
#[\ReturnTypeWillChange]
public function jsonSerialize() {
return [
'file' => $this->getPath(),
'regex' => $this->getRegex(),
];
}
}
}
Loading

0 comments on commit f61d682

Please sign in to comment.