Skip to content

Commit 032dc63

Browse files
committed
First commit!
Signed-off-by: Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
0 parents  commit 032dc63

40 files changed

Lines changed: 3344 additions & 0 deletions

.docheader

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* This file is part of fast-forward/dev-tools.
3+
*
4+
* This source file is subject to the license bundled
5+
* with this source code in the file LICENSE.
6+
*
7+
* @copyright Copyright (c) 2026 Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
8+
* @license https://opensource.org/licenses/MIT MIT License
9+
*
10+
* @see https://github.com/php-fast-forward/dev-tools
11+
* @see https://github.com/php-fast-forward
12+
* @see https://datatracker.ietf.org/doc/html/rfc2119
13+
*/

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 4
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.gitattributes

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
* text=auto
2+
/.github/ export-ignore
3+
/docs/ export-ignore
4+
/tests/ export-ignore
5+
/.editorconfig export-ignore
6+
/.gitattributes export-ignore
7+
/.gitignore export-ignore
8+
/.gitmodules export-ignore

.github/workflows/reports.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Generate Reports and Deploy to GitHub Pages
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches: [ "main" ]
8+
9+
permissions:
10+
contents: write
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: "pages"
16+
cancel-in-progress: false
17+
18+
jobs:
19+
reports:
20+
name: Generate Reports
21+
runs-on: ubuntu-latest
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
submodules: recursive
26+
ref: ${{ github.head_ref || github.ref_name }}
27+
28+
- name: Get Composer Cache Directory
29+
id: composer-cache
30+
run: |
31+
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
32+
33+
- name: Cache Composer dependencies
34+
uses: actions/cache@v4
35+
with:
36+
path: ${{ steps.composer-cache.outputs.dir }}
37+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
38+
restore-keys: |
39+
${{ runner.os }}-composer-
40+
41+
- name: Install dependencies
42+
uses: php-actions/composer@v6
43+
env:
44+
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ github.token }}"} }'
45+
with:
46+
php_version: '8.3'
47+
48+
- name: Generate phpDocumentor API Docs
49+
uses: php-actions/composer@v6
50+
with:
51+
php_version: '8.3'
52+
php_extensions: pcov
53+
command: 'dev-tools'
54+
args: 'reports'
55+
56+
- name: Upload artifact
57+
if: github.ref == 'refs/heads/main'
58+
uses: actions/upload-pages-artifact@v3
59+
with:
60+
path: public/
61+
62+
deploy:
63+
if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
64+
65+
name: Deploy to GitHub Pages
66+
needs: reports
67+
68+
permissions:
69+
pages: write
70+
id-token: write
71+
72+
environment:
73+
name: github-pages
74+
url: ${{ steps.deployment.outputs.page_url }}
75+
76+
runs-on: ubuntu-latest
77+
steps:
78+
- name: Deploy to GitHub Pages
79+
id: deployment
80+
uses: actions/deploy-pages@v4

.github/workflows/tests.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Run PHPUnit Tests
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches: [ "main" ]
8+
9+
permissions:
10+
contents: write
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: "pages"
16+
cancel-in-progress: false
17+
18+
jobs:
19+
tests:
20+
name: Run Tests
21+
runs-on: ubuntu-latest
22+
strategy:
23+
matrix:
24+
php-version: [ '8.3', '8.4', '8.5' ]
25+
steps:
26+
- uses: actions/checkout@v4
27+
with:
28+
submodules: recursive
29+
ref: ${{ github.head_ref || github.ref_name }}
30+
31+
- name: Get Composer Cache Directory
32+
id: composer-cache
33+
run: |
34+
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
35+
36+
- name: Cache Composer dependencies
37+
uses: actions/cache@v4
38+
with:
39+
path: ${{ steps.composer-cache.outputs.dir }}
40+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
41+
restore-keys: |
42+
${{ runner.os }}-composer-
43+
44+
- name: Install dependencies
45+
uses: php-actions/composer@v6
46+
env:
47+
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ github.token }}"} }'
48+
with:
49+
php_version: ${{ matrix.php-version }}
50+
51+
- name: Run PHPUnit tests
52+
uses: php-actions/composer@v6
53+
with:
54+
php_version: ${{ matrix.php-version }}
55+
php_extensions: pcov
56+
command: 'dev-tools'
57+
args: 'tests --coverage=public/coverage'
58+
59+
- name: Ensure minimum code coverage
60+
env:
61+
MINIMUM_COVERAGE: 80
62+
run: |
63+
COVERAGE=$(php -r '
64+
$xml = new SimpleXMLElement(file_get_contents("public/coverage/clover.xml"));
65+
$m = $xml->project->metrics;
66+
$pct = (int) round(((int) $m["coveredstatements"]) * 100 / (int) $m["statements"]);
67+
echo $pct;
68+
')
69+
echo "Coverage: ${COVERAGE}%"
70+
if [ "${COVERAGE}" -lt ${{ env.MINIMUM_COVERAGE }} ]; then
71+
echo "Code coverage below ${{ env.MINIMUM_COVERAGE }}% threshold."
72+
exit 1
73+
fi

.github/workflows/wiki.yml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Update Wiki
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: ["main"]
7+
8+
permissions:
9+
contents: write
10+
11+
concurrency:
12+
group: update-wiki-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
wiki:
17+
name: Update Wiki
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
with:
24+
token: ${{ github.token }}
25+
submodules: recursive
26+
fetch-depth: 0
27+
28+
- name: Get Composer Cache Directory
29+
id: composer-cache
30+
run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
31+
32+
- name: Cache Composer dependencies
33+
uses: actions/cache@v4
34+
with:
35+
path: ${{ steps.composer-cache.outputs.dir }}
36+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
37+
restore-keys: |
38+
${{ runner.os }}-composer-
39+
40+
- name: Install dependencies
41+
uses: php-actions/composer@v6
42+
env:
43+
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ github.token }}"} }'
44+
with:
45+
php_version: '8.3'
46+
47+
- name: Create Docs Markdown
48+
uses: php-actions/composer@v6
49+
with:
50+
php_version: '8.3'
51+
command: 'dev-tools'
52+
args: 'docs'
53+
54+
- name: Prepare wiki submodule branch
55+
working-directory: docs/wiki
56+
run: |
57+
wiki_branch="main"
58+
git fetch origin "$wiki_branch"
59+
git checkout -B "$wiki_branch" "origin/$wiki_branch"
60+
61+
- name: Commit & push wiki submodule
62+
id: wiki_commit
63+
uses: EndBug/add-and-commit@v10
64+
with:
65+
cwd: docs/wiki
66+
add: .
67+
message: "Update wiki docs"
68+
default_author: github_actions
69+
pull: "--rebase"
70+
push: true
71+
72+
- name: Commit parent repo submodule pointer
73+
if: steps.wiki_commit.outputs.committed == 'true'
74+
id: parent_commit
75+
uses: EndBug/add-and-commit@v10
76+
with:
77+
add: docs/wiki
78+
message: "Update wiki submodule pointer"
79+
default_author: github_actions
80+
pull: "--rebase"
81+
push: true

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.idea/
2+
public/
3+
tmp/
4+
vendor/
5+
composer.lock
6+
*.cache
7+
TODO.md

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "docs/wiki"]
2+
path = docs/wiki
3+
url = https://github.com/php-fast-forward/dev-tools.wiki.git

.php-cs-fixer.dist.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
$rules = [
6+
'phpdoc_indent' => true,
7+
'phpdoc_order' => true,
8+
'phpdoc_separation' => true,
9+
'phpdoc_trim' => true,
10+
'phpdoc_trim_consecutive_blank_line_separation' => true,
11+
'phpdoc_scalar' => true,
12+
'phpdoc_types' => true,
13+
'phpdoc_to_comment' => false,
14+
'phpdoc_add_missing_param_annotation' => true,
15+
];
16+
17+
$docheader = getcwd() . '/.docheader';
18+
19+
if (file_exists($docheader)) {
20+
$header = file_get_contents($docheader);
21+
22+
$header = preg_replace(
23+
['!^/\*\*\n!', '! \*/!', '! \* ?!', '!%year%!', '!' . date('Y-Y') . '!'],
24+
[null, null, null, date('Y'), date('Y')],
25+
$header
26+
);
27+
28+
$header = trim($header);
29+
30+
$rules['header_comment'] = [
31+
'header' => $header,
32+
'comment_type' => 'PHPDoc',
33+
'location' => 'after_declare_strict',
34+
'separate' => 'both',
35+
];
36+
}
37+
38+
$finder = PhpCsFixer\Finder::create()
39+
->in([getcwd()])
40+
->exclude('public')
41+
->exclude('resources')
42+
->exclude('vendor')
43+
->exclude('tmp')
44+
;
45+
46+
return (new PhpCsFixer\Config())
47+
->setRiskyAllowed(false)
48+
->setFinder($finder)
49+
->setRules($rules);

LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2026 Felipe Sayão Lobato Abreu
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

0 commit comments

Comments
 (0)