Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make CI/CD integration of Maven Plugin easier #1412

Closed
JapuDCret opened this issue Aug 9, 2021 · 6 comments
Closed

Make CI/CD integration of Maven Plugin easier #1412

JapuDCret opened this issue Aug 9, 2021 · 6 comments

Comments

@JapuDCret
Copy link
Contributor

JapuDCret commented Aug 9, 2021

Issue

The Pact Maven Plugin currently requires that the service, that the providers should be verified against, is available prior to starting the maven build/goal.
However, when you want to verify a new version on a build pipeline, you (usually) do not have an instance of that version which you can test against; it must be started right there and then.

This is hindered by the current implementation of the Maven Plugin, because

  1. the needed infrastructure (so the service itself and everything that it needs) cannot be started with just the Pact Maven Plugin
  2. the Pact Maven Plugin does not (easily) allow for setting the values for the host/port of a service provider dynamically

This issue is linked to this Slack Thread.

Expected behavior

The Pact Maven Plugins allows for easier integration of the necessary infrastructure (like the Gradle plugin).

Solutions

Possible solutions

IMO This issue can be fixed in three ways

  1. Add the ability to startup the necessary infrastructure to validate a provider (e.g. starting up testcontainers)
  2. Add the ability to dynamically set the provider host/port
  3. Do not fix; recommend the workaround (or something similar)

My current workaround

I'm starting the required infrastructure via the exec-maven-plugin as testcontainers and make the dynamic host/port available as system properties.
Then I add a requestFilter to each provider that uses the REQUEST_RESPONSE verification type (i.e. REST APIs), where the request uri is changed to the previously set values.
Both the infrastructure startup and the pact provider verification are done in the maven phase post-integration-test.

This here is the crucial part for the workaround:

<build>
    <plugins>
        <!-- Startup infrastructure for Pact REST provider tests -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>startup-pact-infrastructure</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>java</goal>
                    </goals>
                    <configuration>
                        <classpathScope>test</classpathScope>
                        <cleanupDaemonThreads>false</cleanupDaemonThreads>
                        <mainClass>com.example.pact.PrePactProviderVerificationSetup</mainClass>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>au.com.dius.pact.provider</groupId>
            <artifactId>maven</artifactId>
            <configuration>
                <!-- pact config -->
                <serviceProviders>
                    <serviceProvider>
                        <name>MyProvider</name>
                        <protocol>http</protocol>
                        <requestFilter>
                            def host = System.properties['test.service.host'] ?: 'localhost'
                            def port = System.properties['test.service.port'] ?: '8080'
                            def path = request.getURI().getPath()
                            def query = request.getURI().getQuery()
        
                            request.setURI(URI.create("http://$host:$port$path" + (query ? "?$query" : '')))
                        </requestFilter>
                    </serviceProvider>
                </serviceProviders>
            </configuration>
            <executions>
                <!-- Publish contracts after Unit tests -->
                <execution>
                    <id>publish-pact-contracts</id>
                    <phase>test</phase>
                    <goals>
                        <goal>publish</goal>
                    </goals>
                </execution>
                <!-- Verify providers after integration tests -->
                <execution>
                    <id>verify-pact-contracts</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
@uglyog
Copy link
Member

uglyog commented Aug 15, 2021

I have discovered with Maven that you can use system properties in your POM file: https://maven.apache.org/pom.html#properties

So you could use something like:

                        <name>MyProvider</name>
                        <protocol>http</protocol>
                        <host>${test.service.host}</host>
                        <port>${test.service.port}</port>
                    </serviceProvider>

@JapuDCret
Copy link
Contributor Author

Yes this does work, but only when the system properties are available during the evaluation of the POM. They are not evaluated, when the Plugin is executed and therefore you cannot use a system property, that was set in a previous plugin/phase.
(That's why I used the Groovy script)

@uglyog
Copy link
Member

uglyog commented Aug 21, 2021

Pact-JVM has the ability to parse expressions, so if we can pass in ${test.service.host} for the host, I can set it to resolve that when the plugin runs. But I don't know how to stop Maven from replacing the value when the POM is loaded.

@JapuDCret
Copy link
Contributor Author

JapuDCret commented Aug 23, 2021

Maybe your idea with expression parsing could be solved, with the fix for #1410 (changing the prefix and suffix of the expressions)

uglyog pushed a commit that referenced this issue Aug 29, 2021
uglyog pushed a commit that referenced this issue Aug 29, 2021
@uglyog
Copy link
Member

uglyog commented Aug 29, 2021

You can now use

    <host>{{pact.host}}</host>
    <port>{{pact.port}}</port>

and that will look for the JVM system properties pact.host and pact.port when the verify task is run

@uglyog
Copy link
Member

uglyog commented Sep 4, 2021

4.2.11 released

@uglyog uglyog closed this as completed Feb 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants