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

ci: First run at interchaintests. (backport #3205) #3243

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .github/workflows/docker-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
contents: write
packages: write

steps:
Expand Down Expand Up @@ -54,3 +54,14 @@ jobs:
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
if: ${{ env.NEW_COMMIT_COUNT > 0 }}

- name: Dispatch Interchain test
uses: peter-evans/repository-dispatch@v3
with:
event-type: image-pushed
client-payload: |
{
"tag_name": "${{ fromJson(steps.meta.outputs.json)['labels']['org.opencontainers.image.version'] }}",
"ref_name": "${{ fromJson(steps.meta.outputs.json)['labels']['org.opencontainers.image.revision'] }}"
}
if: ${{ env.NEW_COMMIT_COUNT > 0 }}
64 changes: 64 additions & 0 deletions .github/workflows/interchain-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Interchain Test
on:
repository_dispatch:
types: [image-pushed]
workflow_dispatch:

jobs:
prepare-matrix:
runs-on: ubuntu-latest
steps:
# We need to figure out a) a ref to clone based on a docker image, and b) which tag to test
# If the event is a registry_package, this comes from the pushed image; for a workflow_dispatch, it's the branch/tag that the user supplied
- name: Get metadata
id: get-metadata
run: |
if [[ "${{ github.event_name }}" == 'repository_dispatch' ]]; then
echo "ref_name=${{ github.event.client_payload.ref_name }}" | tee -a $GITHUB_OUTPUT
echo "tag_name=${{ github.event.client_payload.tag_name }}" | tee -a $GITHUB_OUTPUT
else
echo "ref_name=${{ github.ref_name }}" | tee -a $GITHUB_OUTPUT
echo "tag_name=${{ github.ref_name }}" | tee -a $GITHUB_OUTPUT
fi
- name: Check out repository code
uses: actions/checkout@v3
with:
ref: ${{ steps.get-metadata.outputs.ref_name }}
- name: Setup go
uses: actions/setup-go@v5
- name: Prepare matrix
id: generate-matrix
run: |
cd ./tests/interchain
echo "matrix=$(go run ./matrix_tool/main.go ${{ steps.get-metadata.outputs.tag_name }})" | tee -a $GITHUB_OUTPUT
outputs:
matrix: ${{ steps.generate-matrix.outputs.matrix }}
ref_name: ${{ steps.get-metadata.outputs.ref_name }}
test:
needs: prepare-matrix
runs-on: ubuntu-latest
name: "${{ matrix.previous_version }} -> ${{ matrix.test_version }} test ${{ matrix.test_name }}"
strategy:
matrix:
${{fromJson(needs.prepare-matrix.outputs.matrix)}}
fail-fast: false
max-parallel: 10
steps:
- name: Check out repository code
uses: actions/checkout@v3
with:
ref: ${{ needs.prepare-matrix.outputs.ref_name }}
- name: Setup go
uses: actions/setup-go@v5
- name: Run test
env:
TEST_DOCKER_REGISTRY: "ghcr.io/${{ github.repository_owner }}"
TEST_OLD_GAIA_IMAGE_VERSION: "${{ matrix.previous_version }}"
TEST_NEW_GAIA_IMAGE_VERSION: "${{ matrix.test_version }}"
TEST_UPGRADE_NAME: "${{ matrix.upgrade_name }}"
run: |
# This docker pull/tag is a quick hack only necessary for v19, since there were no official v18 images built.
# Once we're testing 19 -> 20 this can be removed
docker pull "ghcr.io/hyphacoop/gaia:v18.1.0" && docker tag "ghcr.io/hyphacoop/gaia:v18.1.0" "ghcr.io/${{ github.repository_owner }}/gaia:v18.1.0"
cd ./tests/interchain
go test -v ./... -failfast -p 1 -timeout 5h -run="^${{ matrix.test_name }}"
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
- name: test & coverage report creation
if: env.GIT_DIFF
run: |
go test -v -coverprofile=profile.out -covermode=atomic -coverpkg=./... $(go list ./... | grep -v -e '/tests/e2e')
go test -v -coverprofile=profile.out -covermode=atomic -coverpkg=./... $(go list ./... | grep -v -e '/tests/e2e' | grep -v -e '/tests/interchain')
- uses: actions/upload-artifact@v4
if: env.GIT_DIFF
with:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ RUN echo "Ensuring binary is statically linked ..." \
&& file /src/app/build/gaiad | grep "statically linked"

FROM alpine:$IMG_TAG
RUN apk add --no-cache build-base
RUN apk add --no-cache build-base jq
RUN addgroup -g 1025 nonroot
RUN adduser -D nonroot -u 1025 -G nonroot
ARG IMG_TAG
Expand Down
139 changes: 139 additions & 0 deletions tests/interchain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Interchain tests for gaia.


These tests use [interchaintest](https://github.com/strangelove-ventures/interchaintest/) to
create, upgrade, and test chains.

They dockerize the validators, so they depend on a `gaia` docker image being built.
You can build a docker image using the [docker-push](../../.github/workflows/docker-push.yml) workflow.
`docker-push` runs nightly on the `main` branch, and for all new releases, but you can also
[run it manually on any branch](https://github.com/cosmos/gaia/actions/workflows/docker-push.yml)

Once the `gaia` image is built, the `docker-push` action workflow automatically invoke the
[interchain-test](../../.github/workflows/interchain-test.yml) workflow.

Read on to learn how these tests work.

## Upgrade testing

The tests will make sure it's possible to upgrade from a previous version of
`gaia` to the current version being tested. It does so by starting a chain from genesis
on the previous version, then upgrading it to the current version.

## Version selection

The `interchain-test` workflow will start by selecting versions to test upgrading from.

The [`matrix_tool`](./matrix_tool/main.go) tool will take the tag of the image
being tested (e.g. `v18.0.0`, or `main`, or `some-feature-branch`), and figure
out a corresponding semver. If the tag is already a valid semver, that's the
version. Otherwise, it will take the major version from the module line in `go.mod`,
and append `.999.0`. Given that semver, it'll figure out:

* The previous rc (if the current version is itself an rc)
* The previous minor version (if applicable)
* The previous major version

For instance, for `v15.1.0-rc1`, we'll test upgrading from:
* `v15.1.0-rc0`
* `v15.0.0`
* `v14.2.0`

The workflow will then test upgrading from each of those three to the current
version. When it's a major upgrade, it will do so via governance proposal,
otherwise it'll simply stop the old image and start the new one.

## Test Suites

Each of the *_test.go files in this directory contains a test suite. These
share some common scaffolding (a `SetupSuite`) to create and upgrade a chain,
and then run a set of tests on that chain.

So, for instance, a transactions suite:

```go
type TxSuite struct {
*chainsuite.Suite
}
```

It extends `chainsuite.Suite,` so its SetupSuite will create and upgrade a
chain (more on this later). The individual `Test*` methods then run the gaia
version being tested:

```go
func (s *TxSuite) TestBankSend() {
balanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[1].Address, chainsuite.Uatom)
s.Require().NoError(err)

_, err = s.Chain.Validators[0].ExecTx(
s.GetContext(),
s.Chain.ValidatorWallets[0].Moniker,
"bank", "send",
s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[1].Address, txAmountUatom(),
)
s.Require().NoError(err)

balanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[1].Address, chainsuite.Uatom)
s.Require().NoError(err)
s.Require().Equal(balanceBefore.Add(sdkmath.NewInt(txAmount)), balanceAfter)
}
```

Because of how testify works, we have to instantiate each suite to run it.
This is also where we tell the suite to run an upgrade on Setup:

```go
func TestTransactions(t *testing.T) {
txSuite := TxSuite{chainsuite.NewSuite(chainsuite.SuiteConfig{UpgradeOnSetup: true})}
suite.Run(t, &txSuite)
}
```

Of course, we can also parameterize the test suites themselves. This enables us
to write tests once and run them a bunch of times on different configurations:

```go
type ConsumerLaunchSuite struct {
*chainsuite.Suite
OtherChain string
OtherChainVersion string
ShouldCopyProviderKey [chainsuite.ValidatorCount]bool
}

func TestICS40ChainLaunch(t *testing.T) {
s := &ConsumerLaunchSuite{
Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}),
OtherChain: "ics-consumer",
OtherChainVersion: "v4.0.0",
ShouldCopyProviderKey: noProviderKeysCopied(),
}
suite.Run(t, s)
}

func TestICS33ConsumerAllKeysChainLaunch(t *testing.T) {
s := &ConsumerLaunchSuite{
Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}),
OtherChain: "ics-consumer",
OtherChainVersion: "v3.3.0",
ShouldCopyProviderKey: allProviderKeysCopied(),
}
suite.Run(t, s)
}
```

Notice also how `UpgradeOnSetup` isn't set here: the ConsumerLaunchSuite needs
to be handed a pre-upgrade chain so it can make sure that a consumer chain that
launched before the upgrade keeps working after the upgrade.


## Writing new tests

All you need to start writing new tests is a test suite as described above.
The suite will have an `s.Chain` that you can test. Check out utilities in
[`chainsuite/chain.go`](./chainsuite/chain.go) and
[`chain_ics.go`](./chainsuite/chain_ics.go) for some convenience methods.

In addition, the s.Chain object extends the `interchaintest` chain object, so
check out [the docs](https://pkg.go.dev/github.com/strangelove-ventures/interchaintest/v7) to
see what else is available.
Loading
Loading