Search code examples
mavenjenkinsgoogle-chrome-extensionchromiummicrosoft-edge-extension

Is there an up-to-date (crx3) way to build a chromium extension (Edge+Chrome) using a CI jenkins pipeline (maven+nexus preferably)?


I am building a self-hosted chromium extension for Edge and Chrome. So far I got a nice working CI pipeline using maven with this plugin (https://github.com/bmatthews68/crx-maven-plugin) and I managed to automate the versioning, packaging and signing of the .crx file, and upload to Nexus repository without much hassle (our intent was to point the upload URL to Nexus releases using group policies to get the extension deployed to users).

But we have found that the plugin is a bit outdated and uses crx2 format for the extension packaging. Support for crx2 was dropped a while ago (chromium v75 or so), and current browser versions require crx3 or won't install the extension.

Seems like the only reliable way to package a crx3 extension right now is using the chrome executable itself, but it does not look like the best idea for a CI pipeline :-/

Any suggestion is welcome!


Solution

  • Finally I found a way, though indirect. There is a CRX3 NPM project that has been kept up to date for the CRX3 format at https://www.npmjs.com/package/crx3

    Using exec-maven-plugin to invoke NPM as detailed below, I've been able to package the crx file correctly (and this works in local windows workstations and ALM linux nodes):

                <!-- Build crx file using NPM -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                  <execution>
                    <phase>compile</phase>                  
                    <goals>
                      <goal>exec</goal>
                    </goals>
                  </execution>
                </executions>
                <configuration>
                  <executable>npm</executable>                
                  <workingDirectory>${project.build.directory}</workingDirectory>
                  <commandlineArgs>install</commandlineArgs>
                </configuration>                
            </plugin>
    

    I used a package.json file for NPM with placeholders for version so I could keep on managing the version in the pom:

    {
      "name": "${project.artifactId}",
      "version": "${project.version}",
      "private": true,
      "dependencies": {
        "crx3": "^1.1.3"
      },
      "scripts": {
        "install": "crx3 ${project.artifactId}-${project.version} --keyPath crx.pem --appVersion ${crx.version} --crxPath ${project.artifactId}-${project.version}.crx"
      }
    }
    

    For the filtering to work correctly I used maven-resources plugin in the pom as well:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <id>copy-extension-resources</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}</outputDirectory>
                        <resources>
                            <!-- Resource filtering to include version number in manifest.json and copy sources to a subfolder in /target -->
                            <resource>
                                <directory>src/main/chrome</directory>
                                <filtering>true</filtering>
                                <includes>
                                    <include>**/manifest.json</include>
                                </includes>
                            </resource>
                            <resource>
                                <directory>src/main/chrome</directory>
                                <filtering>false</filtering>
                                <excludes>
                                    <exclude>**/manifest.json</exclude>
                                </excludes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
                <execution>
                    <id>copy-external-resources</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}</outputDirectory>
                        <resources>
                            <!-- Resource filtering to include version number in update.xml and package.json and copy resources to /target folder -->
                            <resource>
                                <directory>src/main/resources</directory>
                                <filtering>true</filtering>
                                <includes>
                                    <include>update.xml</include>
                                    <include>package.json</include>
                                    <include>package-lock.json</include>    
                                </includes>
                            </resource>
                            <resource>
                                <filtering>false</filtering>
                                <directory>src/main/resources</directory>                   
                                <includes>
                                    <include>crx.pem</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
    
            </executions>
        </plugin>