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

[DR-3282] Add Pact provider support for integration with WDS consumer #1528

Merged
merged 36 commits into from
Nov 15, 2023

Conversation

okotsopoulos
Copy link
Contributor

@okotsopoulos okotsopoulos commented Oct 24, 2023

https://broadworkbench.atlassian.net/browse/DR-3282

This PR does two things:

  1. Establishes datarepo as a Pact provider, and sets up infrastructure for verifying contracts published against it.
  2. Mocks SnapshotsApiController dependencies when setting up Pact Provider states used in Workspace Data Service's published contracts against datarepo. Companion PR: AJ-1188 Add wds consumer tests against datarepo provider terra-workspace-data-service#378

1. General Pact set up

PRs to develop branch will now verify that datarepo adheres to the contracts published by its consumers, and will then publish the results to the central Pact broker.

I've added instructions for running Pact verification locally, still fetching its Pacts from the central Pact broker but not publishing its results.

It's possible to run this verification on a purely local setup, with a local Pact broker. It was a bit cumbersome and I didn't get much extra value from it versus verifying Pacts from the broker, so I elected to leave it out of our checked-in documentation. However, if folks want it codified, I can add it in: https://broadworkbench.atlassian.net/wiki/spaces/IRT/pages/2829680649/Contract+Test+Local+Development

2. Provider states used in WDS contracts

This work was driven by the need to test the protected data journey across service boundaries.

WDS is only calling our snapshot retrieval API as part of this journey, so I've spun up a new SnapshotsApiControllerTest Pact provider. It pairs with WDS' published Pacts: https://pact-broker.dsp-eng-tools.broadinstitute.org/pacts/provider/datarepo/consumer/wds/version/0def2c7d6f55390ce00fc8b02e41fe7844ebfa1f

This is presently set up as a pure unit test of SnapshotsApiController, so that it can be run quickly with very few prerequisites. The controller's dependencies are all mocked / stubbed.

Suggestions for the Pact-curious

  1. Check out this branch and try to get Pact verification working locally for you. If anything doesn't work or isn't clear, I'd be happy to make changes.
  2. Look at the logs associated with new GHA "Verify Consumer Pacts".
  3. Explore the Pact broker to see which other services are registered.
  4. Join #dsp-contract-testing and read through the Getting Started with Pact Contract Testing guide.

Follow-on work

We've discussed concerns that mocking business logic in our Provider states adds maintenance burden, and increases the possibility that mocks could drift from actual app behavior. We want to experiment with sharing mocks between our non-Pact unit tests and Pact Provider states.

Alternatively, some other teams here treat their Provider states as functional tests rather than unit tests -- mocking out external calls and awkward actors but otherwise leaving business logic untouched. These tests run fast and should not be flaky, but can make it hard to pinpoint where a failure happens.

@okotsopoulos okotsopoulos changed the base branch from aj-1233-provider-contract to develop October 24, 2023 22:22
This follows existing convention in SnapshotsApiControllerTest:
by only loading in the required SnapshotsApiController into the context and mocking all of its inputs,
I want to see what's actually required when setting up the application context before introducing additional env variables.
While here, also broke out the reused UUID into a variable.
And enabled standard logging for easier debugging (default is JSON).
Pact tests were failing with:
au.com.dius.pact.provider.junitsupport.loader.NoPactsFoundException: No Pact files were found to verify
Provider: tdr
Source: Pact Broker http://https://pact-broker.dsp-eng-tools.broadinstitute.org
Otherwise, when we've configured our mocks to throw, our controller will not be able to properly handle the exceptions.
We've run into this for other MVC unit tests before: see SnapshotsApiControllerTest.java.
This will allow for our deployments to be recorded.
This also lays the groundwork to use the same name for both TDR as a consumer and provider, which allows for clearer construction of Pact Broker's network graph.
We needed to make a Terraform change so that the Pact broker credentials could be managed by Atlantis and exposed as GHA env variables.
Was seeing 'Cannot invoke getPreferredVersion because versionConstraint is null'
This reduces ongoing maintenance burden and better reflects the expectations that WDS has of TDR.
Upgraded to latest compatible pact plugins.
Moved away from deprecated host and scheme system properties in favor of setting pactbroker.url.
Since this is getting set in a test profile, we should no longer need to pass it as an environmentn variable in GHA verify_consumer_pacts.
This allowed us to remove a hardcoded dummy snapshot UUID which needed to match the one that WDS was using.
WDS contract tests will need to change to supply this ID.
These names now match the states referenced by our sole consumer, WDS
Only a very small amount of pre-configuration is required to verify Pact contracts: I want a dev to be able to verify contracts without getting bogged down in extraneous set-up.
This makes it so that Pact provider verification will pick up on the expected consumer Pacts from the broker.
Included documentation on how to expand the selector if you wish to pick up Pacts from a consumer's feature branch.
In coordination with WDS consumer, expanded 'user has access to snapshot with given id' provider state to include a table:
this consumer expects that a snapshot retrieved with tables will have at least one table with a name.
We want to set boundaries for how we define our Provider states: if future Consumers end up calling other non-snapshot endpoints, we should set up new corresponding Provider state classes.
Note that this name matches existing MockMvc unit test SnapshotsApiControllerTest: I'll seek PR feedback on whether the matching name helps or hurts us.
Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

No Coverage information No Coverage information
0.0% 0.0% Duplication

@okotsopoulos okotsopoulos marked this pull request as ready for review November 13, 2023 23:18
@okotsopoulos okotsopoulos requested a review from jladieu November 13, 2023 23:18
@@ -357,6 +357,10 @@ export AZURE_SYNAPSE_SQLADMINUSER=$(cat /tmp/jade-dev-synapse-admin-user.key)
export AZURE_SYNAPSE_SQLADMINPASSWORD=$(cat /tmp/jade-dev-synapse-admin-password.key)
export AZURE_SYNAPSE_ENCRIPTIONKEY=$(cat /tmp/jade-dev-synapse-encryption-key.key)
export AZURE_SYNAPSE_INITIALIZE=false

# Pact contract test settings
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for TDR devs --

These are two new environment variables needed to verify Pacts locally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for TDR devs --

I elected to break out this small bit of configuration rendering into its own file. I know that a pain point for new devs onboarding is not being sure which subset of configurations are actually needed to run unit tests, for example. Interested in your thoughts!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My inclination would be to keep it all in a single file, rather than dividing things up by tests types. A comment in the script can tell a reader which tests require which environment variables.

@MockBean private AssetModelValidator assetModelValidator;

@PactBrokerConsumerVersionSelectors
public static SelectorBuilder consumerVersionSelectors() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice...I'm totally going to copy this.

Do you know what happens when you don't specify this? Is what's defined here also the default?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All credit to @ichengchang who put up a draft PR to model this selection! I asked that same question in a comment:

#1534 (comment)

My most pressing issue at the time was that since TDR had no Pacts published to it from a consumer's default branch, TDR Pact verification was reporting no Pacts found. I could see Pacts published by WDS against TDR, but they weren't being picked up because they were being published by a WDS feature branch.

Copy link

@jladieu jladieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work. Also: super thoughtful additions to the readme & shell scripts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for TDR Devs --

You may be thinking, "Don't we already have a SnapshotsApiControllerTest?"

We do! It is a unit test of our SnapshotsApiController. I weirdly liked that these two had the same name (different root directories), it implies a link between the two. But I am absolutely open to renaming this if preferred.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine to me, to use the package name to disambiguate tests

jladieu added a commit to DataBiosphere/terra-workspace-manager that referenced this pull request Nov 14, 2023
Inspired by DataBiosphere/jade-data-repo#1528,
this is intended to improve the documentation and first time experience
for running pact tests locally.
jladieu added a commit to DataBiosphere/terra-workspace-manager that referenced this pull request Nov 14, 2023
Inspired by DataBiosphere/jade-data-repo#1528,
this is intended to improve the documentation and first time experience
for running pact tests locally.
@samanehsan
Copy link
Contributor

Will there be any pact tests in TDR for TPS?

@okotsopoulos
Copy link
Contributor Author

Will there be any pact tests in TDR for TPS?

@samanehsan yes! That work is ticketed separately: https://broadworkbench.atlassian.net/browse/DR-3357

It requires TDR to be set up as a Pact consumer (first time we're doing that) and publish its Pacts against TPS, and for TPS itself to be set up as a Pact provider. TPS is not yet involved in any Pact testing.

jladieu added a commit to DataBiosphere/terra-workspace-manager that referenced this pull request Nov 15, 2023
Inspired by DataBiosphere/jade-data-repo#1528,
this is intended to improve the documentation and first time experience
for running pact tests locally.
Copy link
Contributor

@samanehsan samanehsan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! :octocat:

@okotsopoulos okotsopoulos merged commit 85bd169 into develop Nov 15, 2023
11 checks passed
@okotsopoulos okotsopoulos deleted the okotsopo/AJ-1233-provider-contract branch November 15, 2023 19:10
Copy link
Member

@pshapiro4broad pshapiro4broad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see it's already merged, although I have a few minor comments from earlier that I hadn't pushed up yet.

To verify that TDR adheres to the contracts published by its consumers, run:
```
./src/test/render-pact-configs.sh
# Reload your environment variables, e.g. src ~/.zshrc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this assumes that the user has added export PACT_BROKER_USERNAME etc to their .zshrc? I guess overall this doc doesn't really talk about how the rendered configs are exported to the app via environment variables.


Running Pact tests can be achieved by rendering a small set of Pact-specific configurations first:
```
./src/test/render-pact-configs.sh
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the value in having this script exist separate from render-configs.sh. Is the idea that most of the time we don't run pact tests locally so it's typically not needed?

Comment on lines +16 to +17
# They are managed by Atlantis and were added to Terraform here:
# https://github.com/broadinstitute/terraform-ap-deployments/pull/1255
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up to you but I wouldn't leave this in, in case we change how secrets are populated in the future in GitHub. There's nothing specific to the workflow about this as all secrets in GitHub are populated the same way.

Comment on lines +24 to +25
paths-ignore:
- 'README.md'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's nothing wrong with using paths-ignore but we don't do it elsewhere in TDR and if you wanted to really do this, there are many other .md files which could be listed here.

- develop
paths-ignore:
- 'README.md'
push:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this run on push? That means it will run after a PR is merged to develop, in addition to running before the PR is merged. Under what conditions would this detect an error that would otherwise be missed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultimately, the verify_cosumer_pacts.yaml workflow needs to report the bumper tag to Pact Broker as the new pact version. The only way to do this will be to publish the verification results once again using the new tag.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine to me, to use the package name to disambiguate tests

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My inclination would be to keep it all in a single file, rather than dividing things up by tests types. A comment in the script can tell a reader which tests require which environment variables.

jladieu added a commit to DataBiosphere/terra-workspace-manager that referenced this pull request Nov 16, 2023
Inspired by DataBiosphere/jade-data-repo#1528,
this is intended to improve the documentation and first time experience
for running pact tests locally.
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

Successfully merging this pull request may close these issues.

6 participants