25 mars 2022
sourceAvant que vous paniquiez, je vais vous expliquer.
Je travaille actuellement dans une organisation qui dispose d'un compte GitHub entreprise, et donc de repositories privés. Dans ce cas, la réutilisation d'action est un peu moins simple et, dans tous les cas, nécessite la copie d'un fichier. Que ce fichier soit simple ou complexe n'est en quelque sorte pas si intéressant.
Comme cette organisation vient de mettre en place un Nexus, je me suis dit - après un moment d'hésitation - qu'il pourrait être intelligent de définir un pom d'entreprise (généralement je ne suis pas fan de l'idée, mais là, il y a tant à faire qu'un peut de standardisation ne fera pas de mal) et de lui associer une action qui serait le standard d'entreprise. Et par conséquent le fichier build.yml
serait aussi le standard d'entreprise.
Donc, avant tout, il faut être en mesure de livrer les différents workflows GitHub Actions. C'est un usage assez classique de maven-assembly-plugin. Mais, comme mon pom sera utilisé comme pom parent, je préfère créer cet assembly dans un profil finement configuré.
<profile> <id>Attach GitHub workflow file to project for other projects to use</id> <activation> <file> <exists>.github/workflows</exists> </file> </activation> <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <id>Include github scripts as artifacts</id> <inherited>false</inherited> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptors> <descriptor>src/assembly/github.xml</descriptor> </descriptors> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile>
Avec évidement un fichier assembly assez simple
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd"> <id>github</id> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>.github/workflows</directory> <includes> <include>*.yml</include> </includes> </fileSet> </fileSets> </assembly>
Evidement, dans les pom enfants, il faudra récupérer cette dépendance, ce qui sera facile grâce à cet autre profil
<profile> <!-- If no build workflow file exists, copy the one from java-parent project of the version used in this project --> <id>Ensure GitHub Actions exists in this project</id> <activation> <file> <missing>.github/workflows/build.yml</missing> </file> </activation> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>Copy parent build.yml file as our own build.yml</id> <phase>generate-resources</phase> <goals> <goal>unpack</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>my.org</groupId> <artifactId>parent</artifactId> <version>${version.parent}</version> <type>zip</type> <classifier>github</classifier> <overWrite>false</overWrite> <outputDirectory>${project.basedir}</outputDirectory> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile>
Et là, il y a une feinte : on veut le fichier de build correspondant à la version du parent (sinon ça risque d'être le bazar). Mais cette version risque de changer avec le temps, non ? On ne peut donc pas mettre une version fixe, mais une variable. Mais comment faire coller cette variable avec la version du parent sans effort ? On ne peut pas utiliser ${project.version}
, pas plus que ${project.parentversion}
(qui semble à peu près exister, mais pas vraiment). Eh bien, dans ce cas, comme souvent, un peu de groovy va aider :
<plugin> <groupId>org.codehaus.gmaven</groupId> <artifactId>groovy-maven-plugin</artifactId> <executions> <execution> <id>Obtain parent version</id> <!-- I seriously tried to put that code fragment in an external script, but it unfortunatly never worked --> <phase>validate</phase> <goals> <goal>execute</goal> </goals> <configuration> <source><![CDATA[ def findRecursively(project) { if(project.artifactId.equals("parent") && project.groupId.equals("my.org")) { return project.version } else { return findRecursively(project.parent) } } project.properties["version.parent"] = findRecursively(project) log.info "Setting java-parent version to "+project.properties["version.parent"] ]]></source> </configuration> </execution> </executions> </plugin>
Et avec ces trois éléments (grâce aussi à la flexibilité approximative des profils), il est possible de synchroniser "facilement" les workflows GitHub en utilisant Maven (et Nexus, évidement).