#Running a CI Matrix in parallel
1 messages ยท Page 1 of 1 (latest)
@novel sequoia Is there a Dagger-specific solution to this? For any SDK?
Or would it need to be split into separate jobs via YAML workflows?
How would this be achieved locally?
Context
Adrien has this function:
#[DaggerFunction]
public function testsMatrix(): array
{
$result = [];
$result = [];
foreach (['8.2', '8.3', '8.4'] as $phpVersion) {
foreach (['6.4.*', '7.2.*', '7.3.*'] as $symfonyVersion) {
$result[] = $this->test($source, $phpVersion, $symfonyVersion)->all();
}
}
return array_merge(...$result);
}
Where $this->test(...)->all() runs CI for one version.
AT the moment I fixed it with YAML in github actions. With matrix jobs. But locally it can't run in paralell ATM.
๐ค so, you can parallelize it for sure
not sure how you do it in php, but for example, in go you'd use a go statement, or in typescript you'd use async/await
in terms of output as you-go ๐ค i think there needs to be some php otel support? i'm not sure if that's there
essentially this
I think some work for OTEL support was implemented for PHP.
https://github.com/dagger/dagger/issues/8088
But not enough to get as-you-go output (yet).
that's what i was looking for โค๏ธ
yeah, so, that's what's missing - there needs to be some live span support for there to be live output - otherwise, you just get the full output when a thing is completed
Right okay, I think I'll add running test matrices locally as a use-case in the issue.
thank you for your inputs. Natively there are several approaches to async in PHP. You have whole frameworks (like swoole / reactphp), process forking, etc etc. What would be the best way to handle this ? simply requiring it ?
Yeah, so you can use composer packages as normal. You just can't pass them back to Dagger.
What do you mean ?
So, Dagger cares about two things:
- The arguments
- The return value
#[DaggerFunction]
public function (
// dagger cares what goes in here
): Thing { // dagger cares what you return
// Dagger does not care
// Still doesn't care...
// Still not caring...
return $thing; // Dagger cares
}
So you can do this:
#[DaggerFunction]
public function(string $myArg): string
{
$coolClass = new CoolClassFromPackage();
$coolString = $coolClass->doCoolThing($myArg);
return $coolString;
}
So, you can do a composer install inside your module, like normal
You can use the package to do whatever you want inside the function body
But the package isn't exposed to Dagger. So Dagger can't pass it around.
#[DaggerFunction]
public function(CoolClassFromPackage $coolClass): string
{
// do cool things
}
That will fail because Dagger can't receive an object it doesn't know about
#[DaggerFunction]
public function(): CoolClassFromPackage
{
// do cool things
}
That will fail because Dagger can't return an object it doesn't know about
#[DaggerFunction]
public function(): string
{
$coolClass = new CoolClassFromPackage();
// do cool things
}
That will work because Dagger doesn't do anything with it, it's just normal PHP
yes Ok. Fully understand this part ๐ just curious to be sure I do not mistake things. How does dagger handle the multi-lingual support ? Is it AST converted to graphql ? Or is it running multiple language internally to make it work ?
cc @novel sequoia in case I'm mistaken. ๐
My understanding is Dagger deals in GQL.
Each SDK translates GQL into their respective language (and back).
Lets say you call dagger call test --php-version=8.3 --symfony-version=7.4
- Dagger sends the GQL query to the PHP SDK
- The PHP SDK will
a. Receive the call from Dagger as GQL
b. Translatephp-versionandsymfony-versioninto PHP
c. Execute the PHP code inside thetestfunction
d. Translate the return value back to GQL and send it back.
so inside step 2.c. there is no GQL, no other language is playing a part, it's just PHP
yeup that's ittt ๐
graphql is the layer that everything connects to the engine through
yes but how does it work with external modules ? Let's say I require a phpstan dagger module which is written in go. How does it work ? It would need to "invoke" the phpstan module in go itself am I wrong ?
You are correct, if you use a module written in Go. Then it will be executed in Go.
- You install a PHPStan module written in Go.
- This gets added in with the rest of Dagger's GraphQL schema
- The PHP SDK regenerates your
generateddirectory.
a. If you dig into it at this point, you'll find some generated PHP code for the phpstan module.
b. If you look at the code, it's all basically wrappers around GraphQL queries.
Then you run this function
#[DaggerFunction]
public function(Container $container): Container
{
return dag()->phpstan($container)->analyse();
}
When use dag() you are basically just making a fancy GraphQL query, that sends Dagger off to get the result from the Go module.
both of them speak graphql - the api is generated (to speak graphql on each side). you just call a function, and underneath the hood it's making graphql calls
the engine brokers everything
yup okay. So then it executes go code then. And if I write something in PHP and someone else requires it, then my PHP code will be executed. Nice. Because was'nt totally sure how it worked. Wondered if it was using AST to converti it fully to GQL which would have been a nightmare to create and limited functionnality I guess. But that's all good. Meaning we could offload the async / await to other languages.
You could yeah.
I can imagine a scenario where someone might have a PHP back-end with a JS front-end:
I've not tried it, but they might want a PHP module for the back-end, and a Typescript module for the front-end. Then run them using whichever supported language has the best support for coroutines
That example might be contrived or over-engineered ๐คท but it's entirely possible
yeah just trying to think through what is and is not possible.
Maybe something like this https://www.php.net/manual/en/language.fibers.php#127282 could work
not really... Fibers allows to suspend and resume whenever there is no activity in a callback for example. So it allows that when your code is waiting for something (http client, sql query, else...) instead of waiting it can give back control to execute something else and get back to it. But in the case of dagger it is always doing something... I think the best approach would be to use pcntl fork of prcess
For referebce maybe something more like this : https://stancl.substack.com/p/simple-concurrency-in-vanilla-php
but you would be waiting for something: the dagger GraphQL call to complete.
yes but the PHP engine itself will see it as "working" (I think) so not sure Fibers applies here. Sadly pcntl is not available on the PHP runtime. I'll try to submit a PR to update PHP to 8.4 (is there a polivy about such upgrades ?) and see if we can add pcntl (i'll try locally first of course)
I think; from the examples I've seen, the trick is to use a tick function to manage suspending and resuming the fibres
oh, seems that no longer works; was patched out in 8.3
Nothing written down. As long as the change can be justified with something better than "number go higher". ๐
So in this instance, if upgrading to PHP 8.4 allows for concurrency in your CI. That would be a pretty good reason. ๐
not really... but upgrading php to 8.4 is also a way to allow contributors to execute their code with the latest syntax. Shouldn't be a way to register each module to say on which version it should run in (all sdk concerned)