Commit 68fc3fed authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

ci: Use conditional builds (#2853)

- Updates CircleCI jobs to exit early if the git diff doesn't require them to run. This will dramatically reduce our CircleCI usage and speed up the pipeline for projects like Bedrock that don't touch legacy code. The entire pipeline will still run on `develop` and `master`. The conditional logic is aware of package dependencies, so changing an upstream package will correctly trigger a build on downstream dependencies.
- Creates a new `ci-builder` image to replace `js-builder` and `go-builder`. The `ci-builder` image contains everything we need to run builds on CircleCI.
- Fixes a bunch of misspellings that should have failed the linter, but didn't.
parent e523a7fb
This diff is collapsed.
...@@ -90,7 +90,7 @@ func GenSequencerBatchParams( ...@@ -90,7 +90,7 @@ func GenSequencerBatchParams(
) )
// Iterate over the batch elements, grouping the elements according to // Iterate over the batch elements, grouping the elements according to
// the following critera: // the following criteria:
// - All txs in the same group must have the same timestamp. // - All txs in the same group must have the same timestamp.
// - All sequencer txs in the same group must have the same block number. // - All sequencer txs in the same group must have the same block number.
// - If sequencer txs exist in a group, they must come before all // - If sequencer txs exist in a group, they must come before all
......
...@@ -179,7 +179,7 @@ type AppendSequencerBatchParams struct { ...@@ -179,7 +179,7 @@ type AppendSequencerBatchParams struct {
// Contexts aggregates redundant L1 block numbers and L1 timestamps for // Contexts aggregates redundant L1 block numbers and L1 timestamps for
// the txns encoded in the Tx slice. Further, they specify consecutive // the txns encoded in the Tx slice. Further, they specify consecutive
// tx windows in Txs and implicitly allow one to compute how many // tx windows in Txs and implicitly allow one to compute how many
// (ommitted) queued txs are in a given window. // (omitted) queued txs are in a given window.
Contexts []BatchContext Contexts []BatchContext
// Txs contains all sequencer txs that will be recorded in the L1 CTC // Txs contains all sequencer txs that will be recorded in the L1 CTC
...@@ -192,7 +192,7 @@ type AppendSequencerBatchParams struct { ...@@ -192,7 +192,7 @@ type AppendSequencerBatchParams struct {
// - total_elements_to_append: 3 bytes // - total_elements_to_append: 3 bytes
// - num_contexts: 3 bytes // - num_contexts: 3 bytes
// - num_contexts * batch_context: num_contexts * 16 bytes // - num_contexts * batch_context: num_contexts * 16 bytes
// - [num txs ommitted] // - [num txs omitted]
// - tx_len: 3 bytes // - tx_len: 3 bytes
// - tx_bytes: tx_len bytes // - tx_bytes: tx_len bytes
// //
...@@ -292,7 +292,7 @@ func (p *AppendSequencerBatchParams) Serialize( ...@@ -292,7 +292,7 @@ func (p *AppendSequencerBatchParams) Serialize(
// - total_elements_to_append: 3 bytes // - total_elements_to_append: 3 bytes
// - num_contexts: 3 bytes // - num_contexts: 3 bytes
// - num_contexts * batch_context: num_contexts * 16 bytes // - num_contexts * batch_context: num_contexts * 16 bytes
// - [num txs ommitted] // - [num txs omitted]
// - tx_len: 3 bytes // - tx_len: 3 bytes
// - tx_bytes: tx_len bytes // - tx_bytes: tx_len bytes
func (p *AppendSequencerBatchParams) Read(r io.Reader) error { func (p *AppendSequencerBatchParams) Read(r io.Reader) error {
...@@ -349,7 +349,7 @@ func (p *AppendSequencerBatchParams) Read(r io.Reader) error { ...@@ -349,7 +349,7 @@ func (p *AppendSequencerBatchParams) Read(r io.Reader) error {
r = bufio.NewReader(zr) r = bufio.NewReader(zr)
} }
// Deserialize any transactions. Since the number of txs is ommitted // Deserialize any transactions. Since the number of txs is omitted
// from the encoding, loop until the stream is consumed. // from the encoding, loop until the stream is consumed.
for { for {
var txLen uint64 var txLen uint64
......
...@@ -21,8 +21,8 @@ var ( ...@@ -21,8 +21,8 @@ var (
"or mnemonic+hdpath") "or mnemonic+hdpath")
) )
// ParseAddress parses an ETH addres from a hex string. This method will fail if // ParseAddress parses an ETH address from a hex string. This method will fail if
// the address is not a valid hexidecimal address. // the address is not a valid hexadecimal address.
func ParseAddress(address string) (common.Address, error) { func ParseAddress(address string) (common.Address, error) {
if common.IsHexAddress(address) { if common.IsHexAddress(address) {
return common.HexToAddress(address), nil return common.HexToAddress(address), nil
...@@ -101,7 +101,7 @@ func DerivePrivateKey(mnemonic, hdPath string) (*ecdsa.PrivateKey, error) { ...@@ -101,7 +101,7 @@ func DerivePrivateKey(mnemonic, hdPath string) (*ecdsa.PrivateKey, error) {
return crypto.ToECDSA(rawPrivKey) return crypto.ToECDSA(rawPrivKey)
} }
// ParsePrivateKeyStr parses a hexidecimal encoded private key, the encoding may // ParsePrivateKeyStr parses a hexadecimal encoded private key, the encoding may
// optionally have an "0x" prefix. // optionally have an "0x" prefix.
func ParsePrivateKeyStr(privKeyStr string) (*ecdsa.PrivateKey, error) { func ParsePrivateKeyStr(privKeyStr string) (*ecdsa.PrivateKey, error) {
hex := strings.TrimPrefix(privKeyStr, "0x") hex := strings.TrimPrefix(privKeyStr, "0x")
......
...@@ -45,7 +45,7 @@ var ( ...@@ -45,7 +45,7 @@ var (
) )
// TestParseAddress asserts that ParseAddress correctly parses 40-characater // TestParseAddress asserts that ParseAddress correctly parses 40-characater
// hexidecimal strings with optional 0x prefix into valid 20-byte addresses. // hexadecimal strings with optional 0x prefix into valid 20-byte addresses.
func TestParseAddress(t *testing.T) { func TestParseAddress(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
...@@ -157,7 +157,7 @@ func TestDerivePrivateKey(t *testing.T) { ...@@ -157,7 +157,7 @@ func TestDerivePrivateKey(t *testing.T) {
} }
// TestParsePrivateKeyStr asserts that ParsePrivateKey properly parses // TestParsePrivateKeyStr asserts that ParsePrivateKey properly parses
// 64-character hexidecimal strings with optional 0x prefix into valid ECDSA // 64-character hexadecimal strings with optional 0x prefix into valid ECDSA
// private keys. // private keys.
func TestParsePrivateKeyStr(t *testing.T) { func TestParsePrivateKeyStr(t *testing.T) {
tests := []struct { tests := []struct {
...@@ -210,9 +210,9 @@ func TestParsePrivateKeyStr(t *testing.T) { ...@@ -210,9 +210,9 @@ func TestParsePrivateKeyStr(t *testing.T) {
// TestGetConfiguredPrivateKey asserts that GetConfiguredPrivateKey either: // TestGetConfiguredPrivateKey asserts that GetConfiguredPrivateKey either:
// 1) Derives the correct private key assuming the BIP39 mnemonic and BIP32 // 1) Derives the correct private key assuming the BIP39 mnemonic and BIP32
// derivation path are both present and the private key string is ommitted. // derivation path are both present and the private key string is omitted.
// 2) Parses the correct private key assuming only the private key string is // 2) Parses the correct private key assuming only the private key string is
// present, but the BIP39 mnemonic and BIP32 derivation path are ommitted. // present, but the BIP39 mnemonic and BIP32 derivation path are omitted.
func TestGetConfiguredPrivateKey(t *testing.T) { func TestGetConfiguredPrivateKey(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
......
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
type Base struct { type Base struct {
// subsystemName stores the name that will prefix all metrics. This can be // subsystemName stores the name that will prefix all metrics. This can be
// used by drivers to futher extend the core metrics and ensure they use the // used by drivers to further extend the core metrics and ensure they use the
// same prefix. // same prefix.
subsystemName string subsystemName string
......
...@@ -11,7 +11,7 @@ import ( ...@@ -11,7 +11,7 @@ import (
// SendState tracks information about the publication state of a given txn. In // SendState tracks information about the publication state of a given txn. In
// this context, a txn may correspond to multiple different txn hashes due to // this context, a txn may correspond to multiple different txn hashes due to
// varying gas prices, though we treat them all as the same logical txn. This // varying gas prices, though we treat them all as the same logical txn. This
// struct is primarly used to determine whether or not the txmgr should abort a // struct is primarily used to determine whether or not the txmgr should abort a
// given txn and retry with a higher nonce. // given txn and retry with a higher nonce.
type SendState struct { type SendState struct {
minedTxs map[common.Hash]struct{} minedTxs map[common.Hash]struct{}
......
...@@ -80,7 +80,7 @@ func TestSendStateMiningTxCancelsAbort(t *testing.T) { ...@@ -80,7 +80,7 @@ func TestSendStateMiningTxCancelsAbort(t *testing.T) {
} }
// TestSendStateReorgingTxResetsAbort asserts that unmining a tx does not // TestSendStateReorgingTxResetsAbort asserts that unmining a tx does not
// consider ErrNonceTooLow's prior to being mined when determing whether to // consider ErrNonceTooLow's prior to being mined when determine whether to
// abort. // abort.
func TestSendStateReorgingTxResetsAbort(t *testing.T) { func TestSendStateReorgingTxResetsAbort(t *testing.T) {
sendState := newSendState() sendState := newSendState()
......
...@@ -204,16 +204,18 @@ func (m *SimpleTxManager) Send( ...@@ -204,16 +204,18 @@ func (m *SimpleTxManager) Send(
wg.Add(1) wg.Add(1)
go sendTxAsync() go sendTxAsync()
tick := time.NewTicker(m.cfg.ResubmissionTimeout)
for { for {
select { select {
// Whenever a resubmission timeout has elapsed, bump the gas // Whenever a resubmission timeout has elapsed, bump the gas
// price and publish a new transaction. // price and publish a new transaction.
case <-time.After(m.cfg.ResubmissionTimeout): case <-tick.C:
// Avoid republishing if we are waiting for confirmation on an // Avoid republishing if we are waiting for confirmation on an
// existing tx. This is primarily an optimization to reduce the // existing tx. This is primarily an optimization to reduce the
// number of API calls we make, but also reduces the chances of // number of API calls we make, but also reduces the chances of
// getting a false postive reading for ShouldAbortImmediately. // getting a false positive reading for ShouldAbortImmediately.
if sendState.IsWaitingForConfirmation() { if sendState.IsWaitingForConfirmation() {
continue continue
} }
......
...@@ -37,7 +37,7 @@ func newTestHarnessWithConfig(cfg txmgr.Config) *testHarness { ...@@ -37,7 +37,7 @@ func newTestHarnessWithConfig(cfg txmgr.Config) *testHarness {
} }
} }
// newTestHarness initializes a testHarness with a defualt configuration that is // newTestHarness initializes a testHarness with a default configuration that is
// suitable for most tests. // suitable for most tests.
func newTestHarness() *testHarness { func newTestHarness() *testHarness {
return newTestHarnessWithConfig(configWithNumConfs(1)) return newTestHarnessWithConfig(configWithNumConfs(1))
......
...@@ -17,7 +17,7 @@ func makeTestGasPricerAndUpdater(curPrice uint64) (*GasPricer, *GasPriceUpdater, ...@@ -17,7 +17,7 @@ func makeTestGasPricerAndUpdater(curPrice uint64) (*GasPricer, *GasPriceUpdater,
getGasTarget := func() float64 { return gpsTarget } getGasTarget := func() float64 { return gpsTarget }
epochLengthSeconds := uint64(10) epochLengthSeconds := uint64(10)
averageBlockGasLimit := uint64(11000000) averageBlockGasLimit := uint64(11000000)
// Based on our 10 second epoch, we are targetting 3 blocks per epoch. // Based on our 10 second epoch, we are targeting 3 blocks per epoch.
gasPricer, err := NewGasPricer(curPrice, 1, getGasTarget, 10) gasPricer, err := NewGasPricer(curPrice, 1, getGasTarget, 10)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
......
...@@ -7,8 +7,8 @@ import ( ...@@ -7,8 +7,8 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
// ParseL1Address parses a L1 ETH addres from a hex string. This method will // ParseL1Address parses a L1 ETH address from a hex string. This method will
// fail if the address is not a valid hexidecimal address. // fail if the address is not a valid hexadecimal address.
func ParseL1Address(address string) (common.Address, error) { func ParseL1Address(address string) (common.Address, error) {
if common.IsHexAddress(address) { if common.IsHexAddress(address) {
return common.HexToAddress(address), nil return common.HexToAddress(address), nil
...@@ -16,8 +16,8 @@ func ParseL1Address(address string) (common.Address, error) { ...@@ -16,8 +16,8 @@ func ParseL1Address(address string) (common.Address, error) {
return common.Address{}, fmt.Errorf("invalid address: %v", address) return common.Address{}, fmt.Errorf("invalid address: %v", address)
} }
// ParseL2Address parses a L2 ETH addres from a hex string. This method will // ParseL2Address parses a L2 ETH address from a hex string. This method will
// fail if the address is not a valid hexidecimal address. // fail if the address is not a valid hexadecimal address.
func ParseL2Address(address string) (l2common.Address, error) { func ParseL2Address(address string) (l2common.Address, error) {
if l2common.IsHexAddress(address) { if l2common.IsHexAddress(address) {
return l2common.HexToAddress(address), nil return l2common.HexToAddress(address), nil
......
...@@ -12,7 +12,7 @@ import ( ...@@ -12,7 +12,7 @@ import (
) )
// TestParseL1Address asserts that ParseL1Address correctly parses // TestParseL1Address asserts that ParseL1Address correctly parses
// 40-characater hexidecimal strings with optional 0x prefix into valid 20-byte // 40-characater hexadecimal strings with optional 0x prefix into valid 20-byte
// addresses for the L1 chain. // addresses for the L1 chain.
func TestParseL1Address(t *testing.T) { func TestParseL1Address(t *testing.T) {
tests := []struct { tests := []struct {
...@@ -57,7 +57,7 @@ func TestParseL1Address(t *testing.T) { ...@@ -57,7 +57,7 @@ func TestParseL1Address(t *testing.T) {
} }
// TestParseL2Address asserts that ParseL2Address correctly parses // TestParseL2Address asserts that ParseL2Address correctly parses
// 40-characater hexidecimal strings with optional 0x prefix into valid 20-byte // 40-characater hexadecimal strings with optional 0x prefix into valid 20-byte
// addresses for the L2 chain. // addresses for the L2 chain.
func TestParseL2Address(t *testing.T) { func TestParseL2Address(t *testing.T) {
tests := []struct { tests := []struct {
......
FROM ethereum/client-go:alltools-v1.10.17 as geth
FROM ghcr.io/foundry-rs/foundry:latest as foundry
FROM python:3.8.12-slim-buster
ENV GOPATH /go
ENV PATH /usr/local/go/bin:$GOPATH/bin:$PATH
COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge
COPY --from=foundry /usr/local/bin/cast /usr/local/bin/cast
COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen
COPY check-changed.sh /usr/local/bin/check-changed
RUN apt-get update && \
apt-get install -y curl openssh-client git build-essential ca-certificates jq musl && \
curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh && \
curl -sL https://go.dev/dl/go1.18.2.linux-amd64.tar.gz -o go1.18.2.linux-amd64.tar.gz && \
tar -C /usr/local/ -xzvf go1.18.2.linux-amd64.tar.gz && \
ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt && \
bash nodesource_setup.sh && \
apt-get install -y nodejs && \
npm i -g yarn && \
npm i -g depcheck && \
pip install slither-analyzer && \
go install gotest.tools/gotestsum@latest && \
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.45.2 && \
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | bash && \
chmod +x /usr/local/bin/check-changed
RUN echo "downloading solidity compilers" && \
curl -o solc-linux-amd64-v0.5.17+commit.d19bba13 -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.5.17+commit.d19bba13 && \
curl -o solc-linux-amd64-v0.8.9+commit.e5eed63a -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.8.9+commit.e5eed63a && \
curl -o solc-linux-amd64-v0.8.10+commit.fc410830 -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.8.10+commit.fc410830 && \
curl -o solc-linux-amd64-v0.8.12+commit.f00d7308 -sL https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v0.8.12+commit.f00d7308 && \
echo "verifying checksums" && \
(echo "c35ce7a4d3ffa5747c178b1e24c8541b2e5d8a82c1db3719eb4433a1f19e16f3 solc-linux-amd64-v0.5.17+commit.d19bba13" | sha256sum --check --status - || exit 1) && \
(echo "f851f11fad37496baabaf8d6cb5c057ca0d9754fddb7a351ab580d7fd728cb94 solc-linux-amd64-v0.8.9+commit.e5eed63a" | sha256sum --check --status - || exit 1) && \
(echo "c7effacf28b9d64495f81b75228fbf4266ac0ec87e8f1adc489ddd8a4dd06d89 solc-linux-amd64-v0.8.10+commit.fc410830" | sha256sum --check --status - || exit 1) && \
(echo "556c3ec44faf8ff6b67933fa8a8a403abe82c978d6e581dbfec4bd07360bfbf3 solc-linux-amd64-v0.8.12+commit.f00d7308" | sha256sum --check --status - || exit 1) && \
echo "caching compilers" && \
mkdir -p ~/.cache/hardhat-nodejs/compilers/linux-amd64 && \
cp solc-linux-amd64-v0.5.17+commit.d19bba13 ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
cp solc-linux-amd64-v0.8.9+commit.e5eed63a ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
cp solc-linux-amd64-v0.8.10+commit.fc410830 ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
cp solc-linux-amd64-v0.8.12+commit.f00d7308 ~/.cache/hardhat-nodejs/compilers/linux-amd64/ && \
mkdir -p ~/.svm/0.5.17 && \
cp solc-linux-amd64-v0.5.17+commit.d19bba13 ~/.svm/0.5.17/solc-0.5.17 && \
mkdir -p ~/.svm/0.8.9 && \
cp solc-linux-amd64-v0.8.9+commit.e5eed63a ~/.svm/0.8.9/solc-0.8.9 && \
mkdir -p ~/.svm/0.8.10 && \
cp solc-linux-amd64-v0.8.10+commit.fc410830 ~/.svm/0.8.10/solc-0.8.10 && \
mkdir -p ~/.svm/0.8.12 && \
cp solc-linux-amd64-v0.8.12+commit.f00d7308 ~/.svm/0.8.12/solc-0.8.12
#!/usr/bin/env bash
# Usage: check-changed.sh <diff-pattern>.
#
# This script compares the files changed in the <diff-pattern> to the git diff,
# and writes TRUE or FALSE to stdout if the diff matches/does not match. It is
# used by CircleCI jobs to determine if they need to run.
set -e
echoerr() { echo "$@" 1>&2; }
# Check if this is a CircleCI PR.
if [[ -n $CIRCLE_PULL_REQUEST ]]; then
PACKAGE=$1
# Craft the URL to the GitHub API. The access token is optional for the monorepo since it's an open-source repo.
GITHUB_API_URL=$(echo "https://api.github.com/repos/${CIRCLE_PULL_REQUEST}?access_token=$GITHUB_ACCESS_TOKEN" | sed "s/\/pull\//\/pulls\//")
# Grab the PR's base ref using the GitHub API.
REF=$(curl -s "$GITHUB_API_URL" | jq -r ".base.ref")
echoerr "Base Ref: $REF"
echoerr "Base Ref SHA: $(git show-branch --sha1-name "$REF")"
echoerr "Curr Ref: $(git rev-parse --short HEAD)"
# Compare HEAD to the PR's base ref, stripping out the change percentages that come with git diff --dirstat.
# Pass in the diff pattern to grep, and echo TRUE if there's a match. False otherwise.
(git diff --dirstat=files,0 "$REF...HEAD" | sed 's/^[ 0-9.]\+% //g' | grep -q -E "$PACKAGE" && echo "TRUE") || echo "FALSE"
else
# Non-PR builds always require a rebuild.
echoerr "Not a PR build, requiring a total rebuild."
echo "TRUE"
fi
{
"name": "@eth-optimism/ci-builder",
"version": "0.0.0",
"scripts": {},
"license": "MIT",
"dependencies": {}
}
...@@ -144,7 +144,7 @@ func (c Config) WithoutDB() string { ...@@ -144,7 +144,7 @@ func (c Config) WithoutDB() string {
) )
} }
// sslMode retuns "enabled" if EnableSSL is true, otherwise returns "disabled". // sslMode returns "enabled" if EnableSSL is true, otherwise returns "disabled".
func (c Config) sslMode() string { func (c Config) sslMode() string {
if c.EnableSSL { if c.EnableSSL {
return "require" return "require"
......
...@@ -407,7 +407,7 @@ func (d *Driver) processPendingTxs(ctx context.Context) error { ...@@ -407,7 +407,7 @@ func (d *Driver) processPendingTxs(ctx context.Context) error {
return errors.New("unable to find receipt for any pending tx") return errors.New("unable to find receipt for any pending tx")
} }
// Useing the block number, load the header so that we can get accurate // Using the block number, load the header so that we can get accurate
// timestamps for the disbursements. // timestamps for the disbursements.
header, err := d.cfg.L2Client.HeaderByNumber(ctx, receipt.BlockNumber) header, err := d.cfg.L2Client.HeaderByNumber(ctx, receipt.BlockNumber)
if err != nil { if err != nil {
......
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