Commit 31845fd2 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

ci: Refactor dependencies to reduce runtime (#9335)

* ci: Refactor dependencies to reduce runtime

This PR makes the following changes in order to reduce CI runtime:

1. Move the long-running Cannon E2E tests into a scheduled job. This reduces E2E runtime by 8 minutes.
2. Updates the `devnet` task to leverage the contract artifacts and cannon pre-state created in order jobs. This job was also updated to use a Geth binary rather than compiling it from source. This reduces devnet runtime by 5 minutes.
3. Removes intermediate linting, allocs, and geth version check jobs by putting them all in `pnpm-monorepo`. `pnpm-monorepo` already builds the contracts, devnet allocs, and checks the Geth version in parallel so splitting these jobs out actually makes things slower due to CCI image download/environment spin-up overhead. The `pnpm-monorepo` job now plugs into a bunch of downstream jobs.
4. Refactors the action tests to take advantage of multiple test executors.
5. Swaps the `bedrock-go-tests` image to a simple CCI base image to reduce runtime (this job alone was taking ~1min due to spin up overhead).
6. Puts linting in `go-mod-download` to avoid spin-up overhead.

In sum, this PR reduces overall CI runtime from 22 minutes to ~13.

* Use develop as a trigger rather than schedule

* schedule fpp-verify
parent 5a2ac1b4
This diff is collapsed.
......@@ -29,6 +29,11 @@ test-http: pre-test
test-cannon: pre-test
OP_E2E_CANNON_ENABLED=true $(go_test) $(go_test_flags) ./faultproofs
.PHONY: test-cannon
test-fault-proofs: pre-test
$(go_test) $(go_test_flags) ./faultproofs
.PHONY: test-faultproofs
cannon-prestate:
make -C .. cannon-prestate
......
......@@ -2,26 +2,12 @@ package actions
import (
"context"
"os"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
)
var enableParallelTesting bool = true
func init() {
if os.Getenv("OP_E2E_DISABLE_PARALLEL") == "true" {
enableParallelTesting = false
}
}
func parallel(t e2eutils.TestingBase) {
t.Helper()
if enableParallelTesting {
t.Parallel()
}
}
// Testing is an interface to Go-like testing,
// extended with a context getter for the test runner to shut down individual actions without interrupting the test,
// and a signaling function for when an invalid action is hit.
......@@ -69,7 +55,8 @@ type StatefulTesting interface {
// NewDefaultTesting returns a new testing obj, and enables parallel test execution.
// Returns an interface, we're likely changing the behavior here as we build more action tests.
func NewDefaultTesting(tb e2eutils.TestingBase) StatefulTesting {
parallel(tb)
op_e2e.InitParallel(tb)
return &defaultTesting{
TestingBase: tb,
ctx: context.Background(),
......
......@@ -11,7 +11,7 @@ import (
)
func TestMultipleGameTypes(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(0))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, _ := startFaultDisputeSystem(t)
......
......@@ -14,7 +14,7 @@ import (
)
func TestOutputAlphabetGame_ChallengerWins(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
......@@ -71,7 +71,7 @@ func TestOutputAlphabetGame_ChallengerWins(t *testing.T) {
}
func TestOutputAlphabetGame_ValidOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
......@@ -102,7 +102,7 @@ func TestOutputAlphabetGame_ValidOutputRoot(t *testing.T) {
}
func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t)
testCase := func(t *testing.T, isRootCorrect bool) {
ctx := context.Background()
......@@ -159,11 +159,11 @@ func TestChallengerCompleteExhaustiveDisputeGame(t *testing.T) {
}
t.Run("RootCorrect", func(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t)
testCase(t, true)
})
t.Run("RootIncorrect", func(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t)
testCase(t, false)
})
}
......@@ -16,7 +16,7 @@ import (
)
func TestOutputCannonGame(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(0))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
......@@ -72,7 +72,7 @@ func TestOutputCannonGame(t *testing.T) {
func TestOutputCannon_ChallengeAllZeroClaim(t *testing.T) {
// The dishonest actor always posts claims with all zeros.
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
......@@ -109,7 +109,7 @@ func TestOutputCannon_PublishCannonRootClaim(t *testing.T) {
for _, test := range tests {
test := test
t.Run(fmt.Sprintf("Dispute_%v", test.disputeL2BlockNumber), func(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(2))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, _ := startFaultDisputeSystem(t)
......@@ -139,7 +139,7 @@ func TestOutputCannonDisputeGame(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(3))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -176,7 +176,7 @@ func TestOutputCannonDisputeGame(t *testing.T) {
}
func TestOutputCannonDefendStep(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(4))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -212,7 +212,7 @@ func TestOutputCannonDefendStep(t *testing.T) {
}
func TestOutputCannonStepWithLargePreimage(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(0))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, _ := startFaultDisputeSystem(t, withLargeBatches())
......@@ -258,7 +258,7 @@ func TestOutputCannonStepWithLargePreimage(t *testing.T) {
func TestOutputCannonStepWithPreimage(t *testing.T) {
testPreimageStep := func(t *testing.T, preloadPreimage bool) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(5))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -315,9 +315,6 @@ func TestOutputCannonProposedOutputRootValid(t *testing.T) {
// performStep is called once the maximum game depth is reached. It should perform a step to counter the
// claim at parentClaimIdx. Since the proposed output root is invalid, the step call should always revert.
performStep func(ctx context.Context, game *disputegame.OutputCannonGameHelper, correctTrace *disputegame.OutputHonestHelper, parentClaimIdx int64)
// executor to run the task on
executor uint64
}{
{
name: "AttackWithCorrectTrace",
......@@ -330,7 +327,6 @@ func TestOutputCannonProposedOutputRootValid(t *testing.T) {
return correctTrace.AttackClaim(ctx, claim)
},
performStep: honestStepsFail,
executor: 6,
},
{
name: "DefendWithCorrectTrace",
......@@ -349,14 +345,13 @@ func TestOutputCannonProposedOutputRootValid(t *testing.T) {
return correctTrace.DefendClaim(ctx, claim)
},
performStep: honestStepsFail,
executor: 7,
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(test.executor))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -390,7 +385,7 @@ func TestOutputCannonProposedOutputRootValid(t *testing.T) {
}
func TestOutputCannonPoisonedPostState(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(1))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -454,7 +449,7 @@ func TestOutputCannonPoisonedPostState(t *testing.T) {
}
func TestDisputeOutputRootBeyondProposedBlock_ValidOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(2))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -504,7 +499,7 @@ func TestDisputeOutputRootBeyondProposedBlock_ValidOutputRoot(t *testing.T) {
}
func TestDisputeOutputRootBeyondProposedBlock_InvalidOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(3))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......@@ -555,7 +550,7 @@ func TestDisputeOutputRootBeyondProposedBlock_InvalidOutputRoot(t *testing.T) {
}
func TestDisputeOutputRoot_ChangeClaimedOutputRoot(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon, op_e2e.UseExecutor(4))
op_e2e.InitParallel(t, op_e2e.UsesCannon)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
......
......@@ -4,7 +4,8 @@ import (
"crypto/md5"
"os"
"strconv"
"testing"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
)
var enableParallelTesting bool = os.Getenv("OP_E2E_DISABLE_PARALLEL") != "true"
......@@ -13,7 +14,7 @@ type testopts struct {
executor uint64
}
func InitParallel(t *testing.T, args ...func(t *testing.T, opts *testopts)) {
func InitParallel(t e2eutils.TestingBase, args ...func(t e2eutils.TestingBase, opts *testopts)) {
t.Helper()
if enableParallelTesting {
t.Parallel()
......@@ -32,7 +33,7 @@ func InitParallel(t *testing.T, args ...func(t *testing.T, opts *testopts)) {
checkExecutor(t, info, opts.executor)
}
func UsesCannon(t *testing.T, opts *testopts) {
func UsesCannon(t e2eutils.TestingBase, opts *testopts) {
if os.Getenv("OP_E2E_CANNON_ENABLED") == "false" {
t.Skip("Skipping cannon test")
}
......@@ -44,8 +45,8 @@ func UsesCannon(t *testing.T, opts *testopts) {
// InitParallel(t, UseExecutor(1))
// Any tests assigned to an executor greater than the number available automatically use the last executor.
// Executor indexes start from 0
func UseExecutor(assignedIdx uint64) func(t *testing.T, opts *testopts) {
return func(t *testing.T, opts *testopts) {
func UseExecutor(assignedIdx uint64) func(t e2eutils.TestingBase, opts *testopts) {
return func(t e2eutils.TestingBase, opts *testopts) {
opts.executor = assignedIdx
}
}
......@@ -56,7 +57,7 @@ type executorInfo struct {
splitInUse bool
}
func getExecutorInfo(t *testing.T) executorInfo {
func getExecutorInfo(t e2eutils.TestingBase) executorInfo {
var info executorInfo
envTotal := os.Getenv("CIRCLE_NODE_TOTAL")
envIdx := os.Getenv("CIRCLE_NODE_INDEX")
......@@ -81,7 +82,7 @@ func getExecutorInfo(t *testing.T) executorInfo {
return info
}
func checkExecutor(t *testing.T, info executorInfo, assignedIdx uint64) {
func checkExecutor(t e2eutils.TestingBase, info executorInfo, assignedIdx uint64) {
if !info.splitInUse {
t.Logf("Test splitting not in use.")
return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment