ðð»ââïž Gato GraphQL ãã¢ãã¬ããå¿ èŠãšããçç±ãšããã®æé©åæ¹æ³
æ°æ¥åãèšäº Hosting all your PHP packages together in a monorepo ãå ¬éããŸãããããã§ã¯ãPHP ã³ãŒãããŒã¹ã®ç®¡çã«ã¢ãã¬ãã䜿ãããçç±ãšãMonorepo Builder ã䜿ã£ãŠãã®å®çŸæ¹æ³ã説æããŸããã
ããã§ã¯ããã®èšäºãè£è¶³ãã圢ã§ãGatoGraphQL/GatoGraphQL ã³ãŒãããŒã¹ïŒGato GraphQLããã®åºç€ãšãªã GraphQL ãšã³ãžã³ãããã³ãã®äžã«æ§ç¯ãããã³ã³ããŒãã³ãã¢ãã«ã¢ãŒããã¯ãã£ããã¹ãããŠããŸãïŒãã¢ãã¬ãã§ãã¹ããããå¿
èŠãããçç±ãšãç§ãè¡ã£ãæé©åã«ã€ããŠãããå°ã詳ãã説æããããšæããŸãã
Gato GraphQL ãã¢ãã¬ããå¿ èŠãšããçç±
CMSéäŸåæ§ããµããŒãããããã«ãGato GraphQL ããã³é¢é£ãããžã§ã¯ãã®ã³ãŒãããŒã¹ã¯ãComposer ã§ç®¡çããã倿°ã®ããã±ãŒãžã«åå²ãããŸãããåèšã§100以äžã®ããã±ãŒãžãäœæãããŸããïŒïŒçŸåšã¯200以äžã«ãªã£ãŠããŸããïŒ
ããã±ãŒãžæ°ãå€ããŠããComposer ã§ãããããã¹ãŠãŸãšããéã«äœåãªè€éãã¯çããŸãããcomposer install ãå®è¡ããã ãã§ããã¹ãŠãåäœããŸããããããåããã±ãŒãžãç¬èªã®ãªããžããªã«ååšããå ŽåãããŒãžã§ã³ç®¡çã®åé¡ããéçºãå°é£ã«ãªããŸãã
åããã±ãŒãžã¯ããŒãžã§ã³ç®¡çãããå¿ èŠããããããããã±ãŒãžã®ãã¹ãŠã®ããŒãžã§ã³ã¯å¥ã®ããã±ãŒãžã®ããããŒãžã§ã³ã«äŸåããŸããããã»ã©å€ãã®ããã±ãŒãžããããšãPR äœææã«ãã¹ãŠã®ããŒãžã§ã³ãäºãã«ã©ãäŸåããŠããããèšå®ããããšã¯æªå€¢ã®ããã«ãªããã¹ãã²ããã£ã³ãŒãã®ç¿ã®ãããªç¶æ ã«ãªããŸãã麺ã®å 端ã¯èŠããã®ã«ãã©ãã§çµãããããããŸããã

å®éã®ãšãããé¢ä¿ãããã¹ãŠã®ãªããžããªã®è€æ°ãã©ã³ãã«ãŸãããããŒãžã§ã³ããã¹ãŠçŽä»ããããšãéåžžã«å°é£ã«ãªã£ãããããã®ããã»ã¹ãå®å
šã«ã¹ãããããŠãåãªããžããªã® master ãã©ã³ãã«ã³ãŒããçŽæ¥ããã·ã¥ããããããã§ dev-master ããŒãžã§ã³ã«äŸåããããã«ãªã£ãŠããŸããŸããã
ããã¯é©åã§ã¯ãããŸããã§ããããã¹ãŠã®ã³ãŒãã GatoGraphQL/GatoGraphQL ã«ãã¹ãããã¢ãã¬ãã¢ãã«ãžç§»è¡ããããšã§ããã®åé¡ã¯å¹æçã«è§£æ±ºãããŸããã
æè¿ãã¹ãå¯äœçšïŒã³ã³ããªãã¥ãŒã·ã§ã³ã®ããŒãã«ãäžãã
èšäºã§ãè¿°ã¹ãŸãããããããžã§ã¯ããããã±ãŒãžããšã«1ã€ã®ãªããžããªã䜿ã£ãŠããé ã1人ã®ã³ã³ããªãã¥ãŒã¿ãŒãéçºç°å¢ã®ã»ããã¢ãããã§ãããåå ããåã«ãããžã§ã¯ããé¢ããŠããŸããŸããã
ã¢ãã¬ãã«ç§»è¡ããåã¯ãéçºç°å¢ã®ã»ããã¢ããã¯éåžžã«å°é£ã§ãããç§ã¯äœè ã ã£ãã®ã§ããã¹ãŠã®ãªããžããªãã¯ããŒã³ããŠ1ã€ã® VSCode ã¯ãŒã¯ã¹ããŒã¹ã«ãŸãšããããšã§ããªããšãæ©èœãããããšãã§ããŸããã
æœåšçãªã³ã³ããªãã¥ãŒã¿ãŒãåãç°å¢ãã»ããã¢ããããããããããããã® bash ã¹ã¯ãªããã§è©Šã¿ãŸããããããæ£çŽãªãšãããããã¯æåããç¡çãªè©±ã§ã誰ããããžã§ã¯ããžã®è²¢ç®ãå§ããããšãã§ããŸããã§ããã
ã¢ãã¬ãã«ãã£ãŠããã誰ããåå ããããšæã£ãå Žåã«ãäžåçãªå®å䞻矩ã§ã³ã³ããªãã¥ãŒã¿ãŒãæåŠããªãããšã確信ããªãããå€ãã£ããç ããããã«ãªããŸããã
ã¢ãã¬ãã®æé©å
èšäºã§è¿°ã¹ãéããä»£æ¿ææ®µãšæ¯èŒã㊠Monorepo Builder ã©ã€ãã©ãªã䜿ãå©ç¹ã¯ãPHP ã§æ§ç¯ãããŠãããæ¡åŒµå¯èœã§ããããšã§ãã
äŸãã°ãmaster ãžã®ããã·ã¥æã«ã¢ãã¬ããåå²ããå ŽåãGitHub Action ã®ãããªãã¯ã¹ã¯éåžžãåããã±ãŒãžã«å¯ŸããŠ1ã€ã®ã©ã³ããŒã€ã³ã¹ã¿ã³ã¹ãèµ·åãããã®ã³ãŒããç¬èªã®ãªããžããªãšåæããŸãïŒPackagist çµç±ã®é
åžã®ããïŒã
GatoGraphQL/GatoGraphQL ã«ã¯200以äžã®ããã±ãŒãžãå«ãŸããŠããããã200以äžã®ã©ã³ããŒã€ã³ã¹ã¿ã³ã¹ãèµ·åãããŠããŸããã

ããã§ã®åé¡ã¯ãGitHub ã䞊åã§å®è¡ã§ãããžã§ãæ°ã20ã«å¶éããŠããããšã§ãããã¹ãŠã®ã¢ã¯ã·ã§ã³ã¯ãã¥ãŒã«å ¥ãããããããä»ã®ã¢ã¯ã·ã§ã³ãç¶è¡ããããã«å®äºãåŸ ã€å¿ èŠããããŸããã
ããã«ãGitHub ãã©ã³ããŒãããã«ããããžã§ãã³ã°ãããåŸã§åŸ ãããããšããããŸããïŒ

ããããã¹ãŠãåŸ æ©æéã«ã€ãªãããŸãã200以äžã®ããã±ãŒãžããããšã1ã€ã® PR ãããŒãžããã ãã§æå€§1æéãããããšããããŸããïŒããã¯è§£æ±ºãå¿ èŠãªåé¡ã§ããã
ã«ã¹ã¿ã ã³ãã³ãã§ã¢ãã¬ããæ¡åŒµããããšã§ããã®åé¡ã解決ã§ããŸãã
Monorepo Builder ãæ¡åŒµãã
éåžžãæ¬¡ã®ã³ãã³ããå®è¡ãããšããªããžããªå ã®ãã¹ãŠã®ããã±ãŒãžã®äžèЧãååŸã§ããŸãïŒ
vendor/bin/monorepo-builder packages-json
ããããããæããŸããïŒãã¹ãŠã®ããã±ãŒãžãåæããå¿ èŠã¯ãªããPR ã§å€æŽãããã³ãŒããå«ãããã±ãŒãžã ããåæããã°è¯ãã®ã§ã¯ãªãããšã
倿Žããããã¡ã€ã«ã®äžèЧãååŸã§ããã°ããããå«ã倿Žããã±ãŒãžãç¹å®ã§ããŸããã€ãŸãïŒgit diff ãå®è¡ãããã®çµæã packages-json ã³ãã³ãã« filter å
¥åãšããŠæž¡ããŸãããã®ããã«ïŒ
vendor/bin/monorepo-builder packages-json --filter=modified_file_1 --filter=modified_file_2 --filter=...ãšããããMonorepo Builder ã«ä»å±ããŠãã packages-json ã³ãã³ã㯠filter å
¥åãåãä»ããŸããããããã«ã¹ã¿ã ã³ãã³ãã§æ¡åŒµããªããã°ãªããªãéšåã§ãã
Monorepo Builder 㯠Symfony ã® DependencyInjection ã䜿çšããŠãããããã³ã³ããã«æ°ãããµãŒãã¹ã泚å
¥ããããšã§æ¡åŒµã§ããŸããå®éãèšå®ãã¡ã€ã« monorepo-builder.php ã¯ãã§ã«ãµãŒãã¹ã³ã³ãã£ã®ã¥ã¬ãŒã¿ãŒã«ãªã£ãŠããŸãã
ããã§ãfilter å
¥åããµããŒããã package-entries-json ãšããæ°ããã³ãã³ãã§ Monorepo Builder ãæ¡åŒµããŸããïŒ
final class PackageEntriesJsonCommand extends AbstractSymplifyCommand
{
private PackageEntriesJsonProvider $packageEntriesJsonProvider;
public function __construct(PackageEntriesJsonProvider $packageEntriesJsonProvider)
{
$this->packageEntriesJsonProvider = $packageEntriesJsonProvider;
parent::__construct();
}
protected function configure(): void
{
$this->setDescription('Provides package entries in json format. Useful for GitHub Actions Workflow');
$this->addOption(
Option::FILTER,
null,
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
'Filter the packages to those from the list of files. Useful to split monorepo on modified packages only',
[]
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
/** @var string[] $fileFilter */
$fileFilter = $input->getOption(Option::FILTER);
$packageEntries = $this->packageEntriesJsonProvider->providePackageEntries($fileFilter);
// must be without spaces, otherwise it breaks GitHub Actions json
$json = Json::encode($packageEntries);
$this->symfonyStyle->writeln($json);
return ShellCode::SUCCESS;
}
}ãµãŒãã¹ã³ã³ããã«ã¯ãã®ããã«æ³šå ¥ãããŸãïŒ
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->defaults()->autowire()->autoconfigure();
$services->set(PackageEntriesJsonCommand::class);
}ããã«ãããpackage-entries-json ãšããæ°ããã³ãã³ãã GitHub Action ã¯ãŒã¯ãããŒã§å©çšã§ããããã«ãªããŸãã
GitHub Action ã§å€æŽããããã¡ã€ã«ã®äžèЧãååŸãã
次ã«ãã¯ãŒã¯ãããŒãæŽæ°ããæ¹æ³ãèŠãŠãããŸãããã
ç§ã¯äŸ¿å©ãªã¢ã¯ã·ã§ã³ technote-space/get-diff-action ã䜿çšããŠããŸãããã®ã¢ã¯ã·ã§ã³ã¯ãPR ã§å€æŽããããã¹ãŠã®ãã¡ã€ã«ã® git diff ãæäŸããŸãïŒ
# git diff to generate matrix with modified packages only
- uses: technote-space/get-diff-action@v4
with:
PATTERNS: layers/*/*/*/**ãããã®çµæïŒ${{ env.GIT_DIFF }} ã«æ ŒçŽãããŠããŸãïŒãããã«ã¹ã¿ã ã³ãã³ã package-entries-json ãžã®åŒã³åºããçæããåºåãšããŠèšå®ããŸãïŒ
- id: output_data
name: Calculate matrix for packages
run: |
quote=\'
clean_diff="$(echo "${{ env.GIT_DIFF }}" | sed -e s/$quote//g)"
packages_in_diff="$(echo $clean_diff | grep -E -o 'layers/[A-Za-z0-9_\-]*/[A-Za-z0-9_\-]*/[A-Za-z0-9_\-]*/' | sort -u)"
echo "[Packages in diff] $(echo $packages_in_diff | tr '\n' ' ')"
filter_arg="--filter=$(echo $packages_in_diff | sed -e 's/ / --filter=/g')"
echo "::set-output name=matrix::$(vendor/bin/monorepo-builder package-entries-json $(echo $filter_arg))"çµæãšããŠåŸãããããã±ãŒãžã¯ããããªãã¯ã¹ã®äœæã«äœ¿çšãããŸãïŒ
outputs:
matrix: ${{ steps.output_data.outputs.matrix }}ããã¯éåžžã«ããŸãæ©èœããŸãïŒãã®äŸã§ã¯ã倿Žãããããã±ãŒãžã¯2ã€ã ãã ã£ãããããããªãã¯ã¹ã§èµ·åãããã€ã³ã¹ã¿ã³ã¹ã2ã€ã ãã§ããïŒ

ããã§ PR ã®ããŒãžã1æéãããããæ°åã«ççž®ãããåã³å¹žããªéçºè ã«ãªããŸããã
ãããªãæé©åãšèª²é¡
GitHub Action ã®æéãåæžã§ãããã1ã€ã®å Žé¢ããããŸãïŒPHPUnit ãã¹ãã®å®è¡æã§ãã
çŸåšã¯ãæ°ããã³ãŒããã¢ããããŒãããããã³ã«ããã¹ãŠã®ããã±ãŒãžã®å šãã¹ããå®è¡ãããŸãããããããããæé©åã§ããŸãã
ã¢ãã¬ãã« AãBãC ã®3ã€ã®ããã±ãŒãžããããB ã A ã«äŸåããC ã B ã«äŸåããŠãããšããŸãã
ãã®å Žåã1ã€ã®ããã±ãŒãžã®ã³ãŒãã倿Žãããšãå®è¡ãå¿ èŠãªãã¹ãã¯æ¬¡ã®ããã«å€ãããŸãïŒ
- A ã®ã³ãŒãã倿Žããå ŽåïŒAãBãC ããã¹ãããå¿ èŠããã
- B ã®ã³ãŒãã倿Žããå ŽåïŒB ãš C ããã¹ãããå¿ èŠããã
- C ã®ã³ãŒãã倿Žããå ŽåïŒC ããã¹ãããå¿ èŠããã
æé©åã¯ã倿Žãããããã±ãŒãžã®äžèЧïŒåã®æé©åãšåæ§ïŒãååŸããããããšäŸåãããã¹ãŠã®ããã±ãŒãžã®ãã¹ããå®è¡ããããšã«äŸåããŸãã
ãããçŸåšãã¢ãã¬ãå ã®åããã±ãŒãžãäºãã«ã©ã®ããã«äŸåããŠãããã®æ å ±ãæã£ãŠããŸããã
ã«ãŒãã® composer.json ã«ã¯ãã¹ãŠã®ããŒã«ã«ããã±ãŒãžãå«ãŸããŠããŸãããrequire ã§ã¯ãªã replace ã»ã¯ã·ã§ã³ã§å®çŸ©ãããŠãããããcomposer info ${ package_name } ãå®è¡ã㊠Composer çµç±ã§ãã®äŸåé¢ä¿ãååŸããããšãã§ããŸããã
代æ¿ãšããŠãåããã±ãŒãžã®ãµããã©ã«ãã«å
¥ããcomposer install ãå®è¡ããŠãã composer info ãè¡ãããšãèããããŸãããããã200åä»¥äž composer install ãå®è¡ããã®ã¯ãŸã£ããéçŸå®çã§ãã
ãã®ããããã®ã·ããªãªã¯ãŸã æé©åããŠããŸããããããŸã§ã«ã€ã·ã¥ãŒãäœæããŠããããã€ã解決çãèŠã€ããããšãé¡ã£ãŠããŸãã
ãŸãšã
Monorepo Builder ãçºèŠã§ããããšããéåžžã«å¬ããæã£ãŠããŸãããããªãã§ã¯ Gato GraphQL ã®ã³ãŒãããŒã¹ã管çã§ããªãã£ããšæããŸãã
ãã¹ãŠã®ãããžã§ã¯ããããã䜿ãã¹ãã ãšèšã£ãŠããããã§ã¯ãããŸãããããããç§ã®ããã«200以äžã®ããã±ãŒãžãããå Žåããããã¯20以äžã®ããã±ãŒãžãããå Žåã§ããééããªãçæŽ»ã楜ã«ãªããŸãã
ã¢ãã¬ãã®ç®¡çã«ã¯ã»ããã¢ãããšç¶æã«å°ãæéãšåŽåãå¿ èŠã§ãããæ¥ã ã®ç¶ç¶çãªéçºã ãã§ããã®æéãšåŽåãäœåã«ãåãæ»ããŠããŸãã