Skip to content

Commit eb2a6d4

Browse files
committed
Add github workflow to verify docs
1 parent ecf5677 commit eb2a6d4

File tree

7 files changed

+254
-1
lines changed

7 files changed

+254
-1
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ APP_SECRET=5dd8ffca252d95e8b4fb5b2d15310e92
2121

2222
SYMFONY_DOCS_SECRET=''
2323
SYMFONY_SECRET=''
24-
24+
BOT_USERNAME='carsonbot'
2525
###> knplabs/github-api ###
2626
#GITHUB_TOKEN=XXX
2727
###< knplabs/github-api ###

.env.test

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ SYMFONY_DEPRECATIONS_HELPER=999999
55
PANTHER_APP_ENV=panther
66
SYMFONY_DOCS_SECRET=''
77
SYMFONY_SECRET=''
8+
9+
BOT_USERNAME='carsonbot-test'
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Verify docs
2+
3+
on:
4+
schedule:
5+
- cron: '58 6 * * *'
6+
# This is just for test
7+
pull_request: ~
8+
push:
9+
branches:
10+
- master
11+
12+
jobs:
13+
use:
14+
name: Invalid use statements
15+
runs-on: ubuntu-latest
16+
strategy:
17+
fail-fast: false
18+
19+
steps:
20+
- name: Set up PHP
21+
uses: shivammathur/[email protected]
22+
with:
23+
php-version: 7.4
24+
coverage: none
25+
26+
- name: Checkout code
27+
uses: actions/checkout@v2
28+
29+
- name: Checkout Symfony repo
30+
run: git clone https://github.com/symfony/symfony .github/workflows/docs-invalid-use/symfony
31+
32+
- name: Checkout Symfony Docs repo
33+
run: git clone https://github.com/symfony/symfony-docs .github/workflows/docs-invalid-use/docs
34+
35+
- name: Get composer cache directory
36+
id: composer-cache
37+
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
38+
39+
- name: Cache dependencies
40+
uses: actions/cache@v2
41+
with:
42+
path: ${{ steps.composer-cache.outputs.dir }}
43+
key: composer-${{ runner.os }}-7.4-${{ hashFiles('composer.*') }}
44+
restore-keys: |
45+
composer-${{ runner.os }}-7.4-
46+
composer-${{ runner.os }}-
47+
composer-
48+
49+
- name: Download dependencies
50+
run: |
51+
composer install --no-interaction --optimize-autoloader
52+
cd .github/workflows/docs-invalid-use
53+
composer update --prefer-stable --no-interaction --optimize-autoloader
54+
cd symfony
55+
composer update --prefer-stable --no-interaction --optimize-autoloader
56+
57+
- name: Verify docs
58+
run: |
59+
cd .github/workflows/docs-invalid-use
60+
./run.php `pwd`/docs `pwd`/symfony > output.txt
61+
cat output.txt
62+
63+
- name: Open issue
64+
env:
65+
GITHUB_TOKEN: ${{ secrets.CARSONPROD_GITHUB_TOKEN }}
66+
run: |
67+
if [ ! -s .github/workflows/docs-invalid-use/output.txt ]; then
68+
echo "No issues to report"
69+
exit 0
70+
fi
71+
72+
echo -e "I've found some pages that have invalid class references. This is a list of use statements that I couldn't find the correct class to: \n\n\`\`\`\n" > issue.txt
73+
cat .github/workflows/docs-invalid-use/output.txt >> issue.txt
74+
echo -e "\n\`\`\`\nCould someone please verify these?" >> issue.txt
75+
bin/console app:issue:open symfony/symfony-docs "Invalid use statements" `pwd`/issue.txt
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "tobias/docs-checker",
3+
"type": "project",
4+
"authors": [
5+
{
6+
"name": "Nyholm",
7+
"email": "[email protected]"
8+
}
9+
],
10+
"require": {
11+
"symfony/filesystem": "^5.1",
12+
"symfony/finder": "^5.1",
13+
"symfony/phpunit-bridge": "^5.1",
14+
"phpunit/phpunit": "^9.4",
15+
"defuse/php-encryption": "^2.2",
16+
"sensiolabs/ansi-to-html": "^1.2",
17+
"twig/twig": "^3.0",
18+
"symfony/mercure": "^0.4.0",
19+
"lcobucci/jwt": "^3.3",
20+
"symfony/psr-http-message-bridge": "^2.0",
21+
"ramsey/uuid": "^4.1",
22+
"twig/cssinliner-extra": "^3.0"
23+
}
24+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
if ($argc !== 3) {
5+
echo "./docs-invalid-use.php path-to-docs path-to-symfony\n";
6+
exit(1);
7+
}
8+
9+
// Input
10+
$docs = $argv[1];
11+
$symfony = $argv[2];
12+
13+
$autoload = [
14+
__DIR__.'/vendor/autoload.php',
15+
$symfony.'/vendor/autoload.php',
16+
];
17+
18+
foreach ($autoload as $autoloadPHP) {
19+
if (!file_exists($autoloadPHP)) {
20+
echo "File $autoloadPHP does not exist.\nMake sure to run 'composer update'\n";
21+
exit(1);
22+
}
23+
require $autoloadPHP;
24+
}
25+
26+
use Symfony\Component\Finder\Finder;
27+
$finder = new Finder();
28+
$finder->in($docs)->name('*.rst');
29+
30+
$blocklist = getBlocklist();
31+
$count = 0;
32+
foreach ($finder as $file) {
33+
$contents = $file->getContents();
34+
$matches = [];
35+
if (preg_match_all('|^ +use (.*\\\.*); *?$|im', $contents, $matches)) {
36+
foreach ($matches[1] as $class) {
37+
if (substr($class, 0, 3) === 'App' || substr($class, 0, 4) === 'Acme') {
38+
continue;
39+
}
40+
41+
if (false !== $pos = strpos($class, ' as ')) {
42+
$class = substr($class, 0, $pos);
43+
}
44+
45+
if (false !== $pos = strpos($class, 'function ')) {
46+
continue;
47+
}
48+
49+
if (in_array($class, $blocklist)) {
50+
continue;
51+
}
52+
53+
$explode = explode('\\', $class);
54+
if (count($explode) === 3 && $explode[0] === 'Symfony' && $explode[1] === 'Component') {
55+
continue;
56+
}
57+
58+
if (!class_exists($class) && !interface_exists($class) && !trait_exists($class)) {
59+
$count++;
60+
echo $file->getRelativePath().'/'.$file->getFilename(). ' - '.$class. PHP_EOL;
61+
}
62+
}
63+
}
64+
}
65+
66+
if ($count === 0) {
67+
error_log("We found nothing\n");
68+
}
69+
70+
echo "foo".PHP_EOL;
71+
echo "bar".PHP_EOL;
72+
73+
exit(0);
74+
75+
function getBlocklist(): array
76+
{
77+
return [
78+
'Doctrine\ORM\Mapping',
79+
'Symfony\Component\Validator\Constraints',
80+
'Simplex\StringResponseListener',
81+
'Calendar\Model\LeapYear',
82+
'Symfony\Component\Security\Core\Validator\Constraints',
83+
'Simplex\Framework',
84+
'Calendar\Controller\LeapYearController',
85+
'ApiPlatform\Core\Annotation\ApiResource',
86+
'Other\Qux',
87+
'Doctrine\Bundle\FixturesBundle\Fixture',
88+
'Vendor\DependencyClass',
89+
'Example\Namespace\YourAwesomeCoolClass',
90+
'Your\Transport\YourTransportFactory',
91+
];
92+
}

config/services.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ services:
4242
autowire: true
4343
autoconfigure: true
4444

45+
bind:
46+
string $botUsername: '%env(BOT_USERNAME)%'
47+
4548
App\:
4649
resource: '../src/*'
4750
exclude: '../src/{DependencyInjection,Subscriber,Kernel.php,GitHubEvents.php}'

src/Command/OpenIssueCommand.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Command;
6+
7+
use Symfony\Component\Console\Command\Command;
8+
use Symfony\Component\Console\Input\InputArgument;
9+
use Symfony\Component\Console\Input\InputInterface;
10+
use Symfony\Component\Console\Output\OutputInterface;
11+
12+
/**
13+
* Open or update issues.
14+
*
15+
* @author Tobias Nyholm <[email protected]>
16+
*/
17+
class OpenIssueCommand extends Command
18+
{
19+
protected static $defaultName = 'app:issue:open';
20+
21+
public function __construct()
22+
{
23+
parent::__construct();
24+
}
25+
26+
protected function configure()
27+
{
28+
$this->addArgument('repository', InputArgument::REQUIRED, 'The full name to the repository, eg symfony/symfony-docs');
29+
$this->addArgument('title', InputArgument::REQUIRED, 'The title of the issue');
30+
$this->addArgument('file', InputArgument::REQUIRED, 'The path to the issue body text file');
31+
}
32+
33+
protected function execute(InputInterface $input, OutputInterface $output)
34+
{
35+
/** @var string $repositoryName */
36+
$repositoryName = $input->getArgument('repository');
37+
/** @var string $title */
38+
$title = $input->getArgument('title');
39+
/** @var string $filePath */
40+
$filePath = $input->getArgument('file');
41+
$body = file_get_contents($filePath);
42+
if (false === $body) {
43+
return 1;
44+
}
45+
46+
// These outputs are just debug code
47+
$output->writeln('Will create an issue on '.$repositoryName.' with the following:');
48+
$output->writeln('------');
49+
$output->writeln($title);
50+
$output->writeln($body);
51+
$output->writeln('------');
52+
53+
// TODO actually open the issue
54+
55+
return 0;
56+
}
57+
}

0 commit comments

Comments
 (0)