Skip to content

Commit

Permalink
Merge pull request tempestphp#255 from tempestphp/add-console-subsplit
Browse files Browse the repository at this point in the history
Adds console subsplit.
  • Loading branch information
aidan-casey authored Jun 4, 2024
2 parents 8956eea + 73fffe3 commit a3cec1e
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 46 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Exclude build/test files from the release
.github/ export-ignore
bin/get-packages export-ignore
tests/ export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.php-cs-fixer.dist.php export-ignore
monorepo-builder.php export-ignore
phpstan.neon.dist export-ignore
phpstan-baseline.php export-ignore
phpunit.xml export-ignore
Expand Down
30 changes: 29 additions & 1 deletion .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,32 @@ __:white_check_mark: Good Example__
> Value should be a valid email address
__:x: Bad Example__
> Value should be a valid email address!
> Value should be a valid email address!
# Release Workflow

> [!NOTE]
> Tempest uses sub-splits to allow components to be installed as individual packages. The following outlines how this process works.
## Workflow Steps

1. **Trigger Event**
- When a pull request is merged, or a new tag is created, the `.github/workflows/subsplit-packages.yml` action is run.

2. **Package Information Retrieval**
- When the `subsplit-packages.yml` is run, it calls `bin/get-packages`.
- This PHP script uses a combination of Composer and the filesystem to return (in JSON) some information about every package. It returns the:
- **Directory**
- **Name**
- **Package**
- **Organization**
- **Repository**

3. **Action Matrix Creation**
- The result of the `get-packages` command is then used to create an action matrix.
- This ensures that the next steps are performed for _every_ package discovered.

4. **Monorepo Split Action**
- The `symplify/[email protected]` GitHub action is called for every package and provided the necessary information (destination repo, directory, etc.).
- This action takes any changes and pushes them to the sub-split repository determined by combining the "Organization" and "Repository" values returned in step 2.
- Depending on whether a tag is found or not, a tag is also supplied so the repository is tagged appropriately.
75 changes: 75 additions & 0 deletions .github/workflows/subsplit-packages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: 'Sub-split Packages'

on:
push:
branches: [ main ]
tags: [ '*' ]

env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}

jobs:
get_packages:
name: Get Packages
runs-on: ubuntu-latest
steps:
- name: Set Up PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
coverage: none

- uses: actions/checkout@v2

- name: Get Packages
id: get_json
run: echo "::set-output name=json::$(bin/get-packages)"

- name: Output Packages
run: echo "${{ steps.get_json.outputs.json }}"
outputs:
matrix: ${{ steps.get_json.outputs.json }}

packages_split:
name: Split Package ${{ matrix.package.name }}
needs: get_packages
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package: ${{ fromJson(needs.get_packages.outputs.matrix) }}
steps:
- uses: actions/checkout@v2
# no tag
-
if: "!startsWith(github.ref, 'refs/tags/')"
uses: "symplify/[email protected]"
with:
# ↓ split "src/Tempest/Console" directory
package_directory: '${{ matrix.package.directory }}'

# ↓ into https://github.com/tempestphp/tempest-console repository
repository_organization: '${{ matrix.package.organization }}'
repository_name: '${{ matrix.package.repository }}'

# ↓ the user signed under the split commit
user_name: "aidan-casey"
user_email: "[email protected]"

# with tag
-
if: "startsWith(github.ref, 'refs/tags/')"
uses: "symplify/[email protected]"
with:
tag: ${GITHUB_REF#refs/tags/}

# ↓ split "src/Tempest/Console" directory
package_directory: '${{ matrix.package.directory }}'

# ↓ into https://github.com/tempestphp/tempest-console repository
repository_organization: '${{ matrix.package.organization }}'
repository_name: '${{ matrix.package.repository }}'

# ↓ the user signed under the split commit
user_name: "aidan-casey"
user_email: "[email protected]"
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
.idea/
build/
sessions/
vendor/
src/Tempest/database.sqlite
tests/Fixtures/database.sqlite
tests/Unit/Console/test-console.log
.env
.php-cs-fixer.cache
.phpunit.result.cache
tests/fixtures/database.sqlite
composer.lock
*.cache.php
sessions/
debug.log
tempest.log
tests/Unit/Console/test-console.log
*.cache.php
67 changes: 67 additions & 0 deletions bin/get-packages
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/usr/bin/env php
<?php

/**
* The following is heavily borrowed from Ecotone.
*
* This script allows us to dynamically retrieve the package namespace
* and directory from our composer file. This is then used by our GitHub
* action to publish the packages to their appropriate repositories.
*
* @link https://github.com/ecotoneframework/ecotone-dev/blob/main/bin/get-packages
*/

const PACKAGES_DIRECTORY = __DIR__ . '/../src/Tempest/';

function getPackageNameFromComposerFile(string $composerFile)
{
$composer = json_decode(file_get_contents($composerFile), true);

$name = $composer['name'] ?? throw new UnexpectedValueException(
'The referenced package is invalid because it is missing a name: ' . $composerFile
);

return str_replace('tempest/', '', $name);
}

/**
* @return array<array-key, array{
* directory: string,
* name: string,
* package: string,
* organization: string,
* repository: string
* }>
*/
function getPackages(): array {
$packages = [];
$directoryIterator = new DirectoryIterator(realpath(PACKAGES_DIRECTORY));

/**
* @var DirectoryIterator $directory
*/
foreach ($directoryIterator as $directory) {
if ($directory->isDot()) {
continue;
}

$file = $directory->getRealPath() . DIRECTORY_SEPARATOR . 'composer.json';

if (! file_exists($file)) {
continue;
}

$name = getPackageNameFromComposerFile($file);
$packages[] = [
'directory' => $directory->getRealPath(),
'name' => $name,
'package' => 'tempest/' . $name,
'organization' => 'tempestphp',
'repository' => sprintf('tempest-%s', $name),
];
}

return $packages;
}

echo json_encode(getPackages());
50 changes: 30 additions & 20 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,49 @@
"name": "tempest/framework",
"description": "The PHP framework that gets out of your way.",
"require": {
"php": "^8.3",
"tempest/core": "dev-main",
"ext-pdo": "*",
"vlucas/phpdotenv": "^5.6",
"egulias/email-validator": "^4.0",
"ext-dom": "*",
"ext-mbstring": "*",
"ext-fileinfo": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
"ext-readline": "*",
"ext-simplexml": "*",
"giggsey/libphonenumber-for-php": "^8.13",
"egulias/email-validator": "^4.0",
"psr/http-message": "^2.0",
"psr/http-factory": "^1.0",
"psr/http-client": "^1.0",
"guzzlehttp/guzzle": "^7.8",
"laminas/laminas-diactoros": "^3.3",
"php": "^8.3",
"psr/clock": "^1.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^2.0",
"ramsey/uuid": "^4.7",
"ext-simplexml": "*",
"ext-libxml": "*"
"symfony/dependency-injection": "^6.0",
"symfony/http-kernel": "^6.0",
"tempest/core": "dev-main",
"tempest/highlight": "^2.0",
"vlucas/phpdotenv": "^5.6"
},
"require-dev": {
"phpunit/phpunit": "^10.2",
"larapack/dd": "^1.1",
"phpstan/phpstan": "^1.10.0",
"aidan-casey/mock-client": "dev-master",
"friendsofphp/php-cs-fixer": "^3.21",
"larapack/dd": "^1.1",
"nyholm/psr7": "^1.8",
"php-http/mock-client": "^1.6",
"phpat/phpat": "^0.10.14",
"phpstan/phpstan": "^1.10.0",
"phpunit/phpunit": "^10.2",
"spaze/phpstan-disallowed-calls": "^3.1",
"php-http/mock-client": "^1.6",
"aidan-casey/mock-client": "dev-master"
"symplify/monorepo-builder": "^11.2"
},
"autoload": {
"psr-4": {
"Tempest\\": "src/Tempest"
},
"files": [
"src/Tempest/functions.php"
]
],
"psr-4": {
"Tempest\\": "src/Tempest",
"Tempest\\Console\\": "src/Tempest/Console/"
}
},
"autoload-dev": {
"psr-4": {
Expand All @@ -61,5 +68,8 @@
"allow-plugins": {
"php-http/discovery": true
}
},
"replace": {
"tempest/console": "self.version"
}
}
9 changes: 9 additions & 0 deletions monorepo-builder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

use Symplify\MonorepoBuilder\Config\MBConfig;

return static function (MBConfig $mbConfig): void {
$mbConfig->packageDirectories([__DIR__ . '/src/Tempest']);
};
45 changes: 45 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
parameters:
ignoreErrors:
-
message: "#^Tempest\\\\Console\\\\Exceptions\\\\ConsoleException should be final$#"
count: 1
path: src/Tempest/Console/Exceptions/ConsoleException.php

-
message: "#^Calling exec\\(\\) is forbidden\\.$#"
count: 3
path: src/Tempest/Console/Terminal/Terminal.php

-
message: "#^Tempest\\\\Database\\\\Exceptions\\\\DatabaseException should be final$#"
count: 1
Expand Down Expand Up @@ -50,6 +60,41 @@ parameters:
count: 1
path: src/Tempest/HttpClient/Driver/Psr18Driver.php

-
message: "#^Access to an undefined property Tempest\\\\View\\\\View\\:\\:\\$path\\.$#"
count: 1
path: src/View/ViewRenderer.php

-
message: "#^Access to an undefined property Tempest\\\\View\\\\ViewRenderer\\:\\:\\$extendsParams\\.$#"
count: 1
path: src/View/ViewRenderer.php

-
message: "#^Access to an undefined property Tempest\\\\View\\\\ViewRenderer\\:\\:\\$extendsPath\\.$#"
count: 1
path: src/View/ViewRenderer.php

-
message: "#^Access to an undefined property Tempest\\\\View\\\\ViewRenderer\\:\\:\\$path\\.$#"
count: 3
path: src/View/ViewRenderer.php

-
message: "#^Access to an undefined property Tempest\\\\View\\\\ViewRenderer\\:\\:\\$rawParams\\.$#"
count: 1
path: src/View/ViewRenderer.php

-
message: "#^Call to an undefined method Tempest\\\\View\\\\ViewRenderer\\:\\:parseSlots\\(\\)\\.$#"
count: 1
path: src/View/ViewRenderer.php

-
message: "#^Method Tempest\\\\View\\\\ViewRenderer\\:\\:escape\\(\\) is unused\\.$#"
count: 1
path: src/View/ViewRenderer.php

-
message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#"
count: 2
Expand Down
5 changes: 5 additions & 0 deletions src/Tempest/Console/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Exclude build/test files from the release
.github/ export-ignore
.gitattributes export-ignore
.gitignore export-ignore
README.md export-ignore
21 changes: 0 additions & 21 deletions test

This file was deleted.

0 comments on commit a3cec1e

Please sign in to comment.