From 591be9446a5cee1ce559c87e496fa4d7dab92924 Mon Sep 17 00:00:00 2001 From: Giuliano Mega Date: Mon, 5 Feb 2024 08:36:28 -0300 Subject: [PATCH 1/2] remove call to `waitFor` from clock.now and make it async (#691) --- codex/clock.nim | 3 +-- codex/contracts/clock.nim | 6 +++--- codex/purchasing.nim | 2 +- codex/rest/api.nim | 6 ++++-- codex/sales/salesagent.nim | 7 ++++--- codex/sales/states/proving.nim | 2 +- codex/stores/maintenance.nim | 2 +- codex/stores/repostore.nim | 6 +++--- codex/systemclock.nim | 4 ++-- codex/validation.nim | 10 +++++----- tests/codex/helpers/mockclock.nim | 4 ++-- tests/codex/node/testcontracts.nim | 2 +- tests/codex/sales/testsales.nim | 2 +- tests/codex/testpurchasing.nim | 8 ++++---- tests/codex/testsystemclock.nim | 7 ++++--- tests/codex/testvalidation.nim | 4 ++-- tests/contracts/testClock.nim | 8 ++++---- 17 files changed, 43 insertions(+), 40 deletions(-) diff --git a/codex/clock.nim b/codex/clock.nim index f680ddec..cd9603f9 100644 --- a/codex/clock.nim +++ b/codex/clock.nim @@ -1,6 +1,5 @@ import pkg/chronos import pkg/stew/endians2 -import pkg/upraises import pkg/stint type @@ -8,7 +7,7 @@ type SecondsSince1970* = int64 Timeout* = object of CatchableError -method now*(clock: Clock): SecondsSince1970 {.base, upraises: [].} = +method now*(clock: Clock): Future[SecondsSince1970] {.base, async.} = raiseAssert "not implemented" method waitUntil*(clock: Clock, time: SecondsSince1970) {.base, async.} = diff --git a/codex/contracts/clock.nim b/codex/contracts/clock.nim index 9102e5c2..fb329e6b 100644 --- a/codex/contracts/clock.nim +++ b/codex/contracts/clock.nim @@ -46,12 +46,12 @@ method stop*(clock: OnChainClock) {.async.} = await clock.subscription.unsubscribe() clock.started = false -method now*(clock: OnChainClock): SecondsSince1970 = +method now*(clock: OnChainClock): Future[SecondsSince1970] {.async.} = when codex_use_hardhat: # hardhat's latest block.timestamp is usually 1s behind the block timestamp # in the newHeads event. When testing, always return the latest block. try: - if queriedBlock =? (waitFor clock.provider.getBlock(BlockTag.latest)): + if queriedBlock =? (await clock.provider.getBlock(BlockTag.latest)): trace "using last block timestamp for clock.now", lastBlockTimestamp = queriedBlock.timestamp.truncate(int64), cachedBlockTimestamp = clock.lastBlockTime.truncate(int64) @@ -65,6 +65,6 @@ method now*(clock: OnChainClock): SecondsSince1970 = return toUnix(getTime() + clock.offset) method waitUntil*(clock: OnChainClock, time: SecondsSince1970) {.async.} = - while (let difference = time - clock.now(); difference > 0): + while (let difference = time - (await clock.now()); difference > 0): clock.newBlock.clear() discard await clock.newBlock.wait().withTimeout(chronos.seconds(difference)) diff --git a/codex/purchasing.nim b/codex/purchasing.nim index a53a5150..4ef575b3 100644 --- a/codex/purchasing.nim +++ b/codex/purchasing.nim @@ -53,7 +53,7 @@ proc populate*(purchasing: Purchasing, if result.ask.proofProbability == 0.u256: result.ask.proofProbability = purchasing.proofProbability if result.expiry == 0.u256: - result.expiry = (purchasing.clock.now().u256 + purchasing.requestExpiryInterval) + result.expiry = (await purchasing.clock.now()).u256 + purchasing.requestExpiryInterval if result.nonce == Nonce.default: var id = result.nonce.toArray doAssert randomBytes(id) == 32 diff --git a/codex/rest/api.nim b/codex/rest/api.nim index ccb213ab..58430704 100644 --- a/codex/rest/api.nim +++ b/codex/rest/api.nim @@ -328,10 +328,12 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = if node.clock.isNil: return RestApiResponse.error(Http500) - if expiry <= node.clock.now.u256: + let now = (await node.clock.now).u256 + + if expiry <= now: return RestApiResponse.error(Http400, "Expiry needs to be in future") - if expiry > node.clock.now.u256 + params.duration: + if expiry > now + params.duration: return RestApiResponse.error(Http400, "Expiry has to be before the request's end (now + duration)") without purchaseId =? await node.requestStorage( diff --git a/codex/sales/salesagent.nim b/codex/sales/salesagent.nim index 21475426..fb64245e 100644 --- a/codex/sales/salesagent.nim +++ b/codex/sales/salesagent.nim @@ -73,8 +73,9 @@ proc subscribeCancellation(agent: SalesAgent) {.async.} = return while true: - let deadline = max(clock.now, request.expiry.truncate(int64)) + 1 - trace "Waiting for request to be cancelled", now=clock.now, expiry=deadline + let now = await clock.now + let deadline = max(now, request.expiry.truncate(int64)) + 1 + trace "Waiting for request to be cancelled", now=now, expiry=deadline await clock.waitUntil(deadline) without state =? await agent.retrieveRequestState(): @@ -85,7 +86,7 @@ proc subscribeCancellation(agent: SalesAgent) {.async.} = agent.schedule(cancelledEvent(request)) break - debug "The request is not yet canceled, even though it should be. Waiting for some more time.", currentState = state, now=clock.now + debug "The request is not yet canceled, even though it should be. Waiting for some more time.", currentState = state, now=now data.cancelled = onCancelled() diff --git a/codex/sales/states/proving.nim b/codex/sales/states/proving.nim index 4593fd19..047e5f4a 100644 --- a/codex/sales/states/proving.nim +++ b/codex/sales/states/proving.nim @@ -57,7 +57,7 @@ proc proveLoop( proc getCurrentPeriod(): Future[Period] {.async.} = let periodicity = await market.periodicity() - return periodicity.periodOf(clock.now().u256) + return periodicity.periodOf((await clock.now()).u256) proc waitUntilPeriod(period: Period) {.async.} = let periodicity = await market.periodicity() diff --git a/codex/stores/maintenance.nim b/codex/stores/maintenance.nim index 343fed8f..0e953b3a 100644 --- a/codex/stores/maintenance.nim +++ b/codex/stores/maintenance.nim @@ -59,7 +59,7 @@ proc deleteExpiredBlock(self: BlockMaintainer, cid: Cid): Future[void] {.async.} trace "Unable to delete block from repoStore" proc processBlockExpiration(self: BlockMaintainer, be: BlockExpiration): Future[void] {.async} = - if be.expiration < self.clock.now: + if be.expiration < (await self.clock.now): await self.deleteExpiredBlock(be.cid) else: inc self.offset diff --git a/codex/stores/repostore.nim b/codex/stores/repostore.nim index dc63f4cd..ef9d322c 100644 --- a/codex/stores/repostore.nim +++ b/codex/stores/repostore.nim @@ -229,12 +229,12 @@ proc getBlockExpirationEntry( proc getBlockExpirationEntry( self: RepoStore, cid: Cid, - ttl: ?Duration): ?!BatchEntry = + ttl: ?Duration): Future[?!BatchEntry] {.async.} = ## Get an expiration entry for a batch for duration since "now" ## let duration = ttl |? self.blockTtl - self.getBlockExpirationEntry(cid, self.clock.now() + duration.seconds) + self.getBlockExpirationEntry(cid, (await self.clock.now()) + duration.seconds) method ensureExpiry*( self: RepoStore, @@ -340,7 +340,7 @@ method putBlock*( trace "Updating quota", used batch.add((QuotaUsedKey, @(used.uint64.toBytesBE))) - without blockExpEntry =? self.getBlockExpirationEntry(blk.cid, ttl), err: + without blockExpEntry =? (await self.getBlockExpirationEntry(blk.cid, ttl)), err: trace "Unable to create block expiration metadata key", err = err.msg return failure(err) batch.add(blockExpEntry) diff --git a/codex/systemclock.nim b/codex/systemclock.nim index 25ac4216..b43c5189 100644 --- a/codex/systemclock.nim +++ b/codex/systemclock.nim @@ -1,10 +1,10 @@ import std/times -import pkg/upraises +import pkg/chronos import ./clock type SystemClock* = ref object of Clock -method now*(clock: SystemClock): SecondsSince1970 {.upraises: [].} = +method now*(clock: SystemClock): Future[SecondsSince1970] {.async.} = let now = times.now().utc now.toTime().toUnix() diff --git a/codex/validation.nim b/codex/validation.nim index b549997e..a64d9318 100644 --- a/codex/validation.nim +++ b/codex/validation.nim @@ -34,11 +34,11 @@ proc new*( proc slots*(validation: Validation): seq[SlotId] = validation.slots.toSeq -proc getCurrentPeriod(validation: Validation): UInt256 = - return validation.periodicity.periodOf(validation.clock.now().u256) +proc getCurrentPeriod(validation: Validation): Future[UInt256] {.async.} = + return validation.periodicity.periodOf((await validation.clock.now()).u256) proc waitUntilNextPeriod(validation: Validation) {.async.} = - let period = validation.getCurrentPeriod() + let period = await validation.getCurrentPeriod() let periodEnd = validation.periodicity.periodEnd(period) trace "Waiting until next period", currentPeriod = period await validation.clock.waitUntil(periodEnd.truncate(int64) + 1) @@ -66,7 +66,7 @@ proc markProofAsMissing(validation: Validation, slotId: SlotId, period: Period) {.async.} = logScope: - currentPeriod = validation.getCurrentPeriod() + currentPeriod = (await validation.getCurrentPeriod()) try: if await validation.market.canProofBeMarkedAsMissing(slotId, period): @@ -82,7 +82,7 @@ proc markProofAsMissing(validation: Validation, proc markProofsAsMissing(validation: Validation) {.async.} = for slotId in validation.slots: - let previousPeriod = validation.getCurrentPeriod() - 1 + let previousPeriod = (await validation.getCurrentPeriod()) - 1 await validation.markProofAsMissing(slotId, previousPeriod) proc run(validation: Validation) {.async.} = diff --git a/tests/codex/helpers/mockclock.nim b/tests/codex/helpers/mockclock.nim index ada449f9..22ba8298 100644 --- a/tests/codex/helpers/mockclock.nim +++ b/tests/codex/helpers/mockclock.nim @@ -32,11 +32,11 @@ proc set*(clock: MockClock, time: SecondsSince1970) = proc advance*(clock: MockClock, seconds: int64) = clock.set(clock.time + seconds) -method now*(clock: MockClock): SecondsSince1970 = +method now*(clock: MockClock): Future[SecondsSince1970] {.async.} = clock.time method waitUntil*(clock: MockClock, time: SecondsSince1970) {.async.} = - if time > clock.now(): + if time > (await clock.now()): let future = newFuture[void]() clock.waiting.add(Waiting(until: time, future: future)) await future diff --git a/tests/codex/node/testcontracts.nim b/tests/codex/node/testcontracts.nim index eea35e28..8eb235c9 100644 --- a/tests/codex/node/testcontracts.nim +++ b/tests/codex/node/testcontracts.nim @@ -98,7 +98,7 @@ asyncchecksuite "Test Node - Host contracts": test "onExpiryUpdate callback": let # The blocks have set default TTL, so in order to update it we have to have larger TTL - expectedExpiry: SecondsSince1970 = clock.now + DefaultBlockTtl.seconds + 11123 + expectedExpiry: SecondsSince1970 = (await clock.now) + DefaultBlockTtl.seconds + 11123 expiryUpdateCallback = !sales.onExpiryUpdate (await expiryUpdateCallback(manifestCidStr, expectedExpiry)).tryGet() diff --git a/tests/codex/sales/testsales.nim b/tests/codex/sales/testsales.nim index 6241073b..5af97538 100644 --- a/tests/codex/sales/testsales.nim +++ b/tests/codex/sales/testsales.nim @@ -67,7 +67,7 @@ asyncchecksuite "Sales - start": sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[?!seq[byte]] {.async.} = return success(proof) itemsProcessed = @[] - request.expiry = (clock.now() + 42).u256 + request.expiry = ((await clock.now()) + 42).u256 teardown: await sales.stop() diff --git a/tests/codex/testpurchasing.nim b/tests/codex/testpurchasing.nim index 1660cb6a..0e6a2615 100644 --- a/tests/codex/testpurchasing.nim +++ b/tests/codex/testpurchasing.nim @@ -161,7 +161,7 @@ checksuite "Purchasing state machine": market.requestState[request5.id] = RequestState.Failed # ensure the started state doesn't error, giving a false positive test result - market.requestEnds[request2.id] = clock.now() - 1 + market.requestEnds[request2.id] = (await clock.now()) - 1 await purchasing.load() check eventually purchasing.getPurchase(PurchaseId(request1.id)).?finished == false.some @@ -182,7 +182,7 @@ checksuite "Purchasing state machine": test "moves to PurchaseStarted when request state is Started": let request = StorageRequest.example let purchase = Purchase.new(request, market, clock) - market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64) + market.requestEnds[request.id] = (await clock.now()) + request.ask.duration.truncate(int64) market.requested = @[request] market.requestState[request.id] = RequestState.Started let next = await PurchaseUnknown().run(purchase) @@ -215,7 +215,7 @@ checksuite "Purchasing state machine": test "moves to PurchaseFailed state once RequestFailed emitted": let request = StorageRequest.example let purchase = Purchase.new(request, market, clock) - market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64) + market.requestEnds[request.id] = (await clock.now()) + request.ask.duration.truncate(int64) let future = PurchaseStarted().run(purchase) market.emitRequestFailed(request.id) @@ -226,7 +226,7 @@ checksuite "Purchasing state machine": test "moves to PurchaseFinished state once request finishes": let request = StorageRequest.example let purchase = Purchase.new(request, market, clock) - market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64) + market.requestEnds[request.id] = (await clock.now()) + request.ask.duration.truncate(int64) let future = PurchaseStarted().run(purchase) clock.advance(request.ask.duration.truncate(int64)) diff --git a/tests/codex/testsystemclock.nim b/tests/codex/testsystemclock.nim index 6f743283..b4e74d0d 100644 --- a/tests/codex/testsystemclock.nim +++ b/tests/codex/testsystemclock.nim @@ -1,14 +1,15 @@ import std/times -import std/unittest import codex/systemclock + +import ../asynctest import ./helpers -checksuite "SystemClock": +asyncchecksuite "SystemClock": test "Should get now": let clock = SystemClock.new() let expectedNow = times.now().utc - let now = clock.now() + let now = (await clock.now()) check now == expectedNow.toTime().toUnix() diff --git a/tests/codex/testvalidation.nim b/tests/codex/testvalidation.nim index 9e4a2dcf..6786ecb0 100644 --- a/tests/codex/testvalidation.nim +++ b/tests/codex/testvalidation.nim @@ -31,9 +31,9 @@ asyncchecksuite "validation": teardown: await validation.stop() - proc advanceToNextPeriod = + proc advanceToNextPeriod {.async.} = let periodicity = Periodicity(seconds: period.u256) - let period = periodicity.periodOf(clock.now().u256) + let period = periodicity.periodOf((await clock.now()).u256) let periodEnd = periodicity.periodEnd(period) clock.set((periodEnd + 1).truncate(int)) diff --git a/tests/contracts/testClock.nim b/tests/contracts/testClock.nim index d7b6ad34..4a309a9e 100644 --- a/tests/contracts/testClock.nim +++ b/tests/contracts/testClock.nim @@ -17,23 +17,23 @@ ethersuite "On-Chain Clock": test "returns the current time of the EVM": let latestBlock = (!await ethProvider.getBlock(BlockTag.latest)) let timestamp = latestBlock.timestamp.truncate(int64) - check clock.now() == timestamp + check (await clock.now()) == timestamp test "updates time with timestamp of new blocks": let future = (getTime() + 42.years).toUnix discard await ethProvider.send("evm_setNextBlockTimestamp", @[%future]) discard await ethProvider.send("evm_mine") - check clock.now() == future + check (await clock.now()) == future test "can wait until a certain time is reached by the chain": - let future = clock.now() + 42 # seconds + let future = (await clock.now()) + 42 # seconds let waiting = clock.waitUntil(future) discard await ethProvider.send("evm_setNextBlockTimestamp", @[%future]) discard await ethProvider.send("evm_mine") check await waiting.withTimeout(chronos.milliseconds(100)) test "can wait until a certain time is reached by the wall-clock": - let future = clock.now() + 1 # seconds + let future = (await clock.now()) + 1 # seconds let waiting = clock.waitUntil(future) check await waiting.withTimeout(chronos.seconds(2)) From 403b9baf9f26d354457c08cf7972f968700b6efc Mon Sep 17 00:00:00 2001 From: Slava <20563034+veaceslavdoina@users.noreply.github.com> Date: Tue, 6 Feb 2024 12:56:27 +0200 Subject: [PATCH 2/2] Add Nim-matrix workflow to run on merge queue (#693) * Add Nim-matrix workflow to run on merge queue * Use reusable workflows for CI and Nim-matrix --- .github/workflows/ci-reusable.yml | 79 +++++++++++++++++++ .github/workflows/ci.yml | 106 +++++++------------------- .github/workflows/docker-reusable.yml | 2 +- .github/workflows/nim-matrix.yml | 30 ++++++++ 4 files changed, 139 insertions(+), 78 deletions(-) create mode 100644 .github/workflows/ci-reusable.yml create mode 100644 .github/workflows/nim-matrix.yml diff --git a/.github/workflows/ci-reusable.yml b/.github/workflows/ci-reusable.yml new file mode 100644 index 00000000..401ef161 --- /dev/null +++ b/.github/workflows/ci-reusable.yml @@ -0,0 +1,79 @@ +name: Reusable - CI + +on: + workflow_call: + inputs: + matrix: + type: string + cache_nonce: + default: '0' + description: Allows for easily busting actions/cache caches + required: false + type: string + +env: + cache_nonce: ${{ inputs.cache_nonce }} + +jobs: + build: + strategy: + matrix: + include: ${{ fromJson(inputs.matrix) }} + + defaults: + run: + shell: ${{ matrix.shell }} {0} + + name: '${{ matrix.os }}-${{ matrix.cpu }}-${{ matrix.nim_version }}-${{ matrix.tests }}' + runs-on: ${{ matrix.builder }} + timeout-minutes: 80 + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Nimbus Build System + uses: ./.github/actions/nimbus-build-system + with: + os: ${{ matrix.os }} + shell: ${{ matrix.shell }} + nim_version: ${{ matrix.nim_version }} + + ## Part 1 Tests ## + - name: Unit tests + if: matrix.tests == 'unittest' || matrix.tests == 'all' + run: make -j${ncpu} test + + # workaround for https://github.com/NomicFoundation/hardhat/issues/3877 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 18.15 + + - name: Start Ethereum node with Codex contracts + if: matrix.tests == 'contract' || matrix.tests == 'integration' || matrix.tests == 'all' + working-directory: vendor/codex-contracts-eth + env: + MSYS2_PATH_TYPE: inherit + run: | + npm install + npm start & + + ## Part 2 Tests ## + - name: Contract tests + if: matrix.tests == 'contract' || matrix.tests == 'all' + run: make -j${ncpu} testContracts + + ## Part 3 Tests ## + - name: Integration tests + if: matrix.tests == 'integration' || matrix.tests == 'all' + run: make -j${ncpu} testIntegration + + status: + if: always() + needs: [build] + runs-on: ubuntu-latest + steps: + - if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} + run: exit 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e09b9f9..905f6505 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,93 +1,45 @@ name: CI + on: push: branches: - master pull_request: workflow_dispatch: + env: cache_nonce: 0 # Allows for easily busting actions/cache caches nim_version: v1.6.14 + + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + jobs: - build: - strategy: - matrix: - include: - - os: linux - cpu: amd64 - builder: ubuntu-latest - shell: bash --noprofile --norc -e -o pipefail - tests: all - - os: macos - cpu: amd64 - builder: macos-latest - shell: bash --noprofile --norc -e -o pipefail - tests: all - - os: windows - cpu: amd64 - builder: windows-latest - shell: msys2 - tests: unittest - - os: windows - cpu: amd64 - builder: windows-latest - shell: msys2 - tests: contract - - os: windows - cpu: amd64 - builder: windows-latest - shell: msys2 - tests: integration - - defaults: - run: - shell: ${{ matrix.shell }} {0} - - name: '${{ matrix.os }}-${{ matrix.cpu }}-tests-${{ matrix.tests }}' - runs-on: ${{ matrix.builder }} - timeout-minutes: 80 + matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + cache_nonce: ${{ env.cache_nonce }} steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - submodules: recursive + - name: Compute matrix + id: matrix + uses: fabiocaccamo/create-matrix-action@v4 + with: + matrix: | + os {linux}, cpu {amd64}, builder {ubuntu-latest}, tests {all}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} + os {macos}, cpu {amd64}, builder {macos-latest}, tests {all}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} + os {windows}, cpu {amd64}, builder {windows-latest}, tests {unittest}, nim_version {${{ env.nim_version }}}, shell {msys2} + os {windows}, cpu {amd64}, builder {windows-latest}, tests {contract}, nim_version {${{ env.nim_version }}}, shell {msys2} + os {windows}, cpu {amd64}, builder {windows-latest}, tests {integration}, nim_version {${{ env.nim_version }}}, shell {msys2} - - name: Setup Nimbus Build System - uses: ./.github/actions/nimbus-build-system - with: - os: ${{ matrix.os }} - shell: ${{ matrix.shell }} - nim_version: ${{ env.nim_version }} - - ## Part 1 Tests ## - - name: Unit tests - if: matrix.tests == 'unittest' || matrix.tests == 'all' - run: make -j${ncpu} test - - # workaround for https://github.com/NomicFoundation/hardhat/issues/3877 - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 18.15 - - - name: Start Ethereum node with Codex contracts - if: matrix.tests == 'contract' || matrix.tests == 'integration' || matrix.tests == 'all' - working-directory: vendor/codex-contracts-eth - env: - MSYS2_PATH_TYPE: inherit - run: | - npm install - npm start & - - ## Part 2 Tests ## - - name: Contract tests - if: matrix.tests == 'contract' || matrix.tests == 'all' - run: make -j${ncpu} testContracts - - ## Part 3 Tests ## - - name: Integration tests - if: matrix.tests == 'integration' || matrix.tests == 'all' - run: make -j${ncpu} testIntegration + build: + needs: matrix + uses: ./.github/workflows/ci-reusable.yml + with: + matrix: ${{ needs.matrix.outputs.matrix }} + cache_nonce: ${{ needs.matrix.outputs.cache_nonce }} coverage: continue-on-error: true diff --git a/.github/workflows/docker-reusable.yml b/.github/workflows/docker-reusable.yml index 816b0791..ebd37ae8 100644 --- a/.github/workflows/docker-reusable.yml +++ b/.github/workflows/docker-reusable.yml @@ -1,4 +1,4 @@ -name: Docker - Reusable +name: Reusable - Docker on: diff --git a/.github/workflows/nim-matrix.yml b/.github/workflows/nim-matrix.yml new file mode 100644 index 00000000..87306ad8 --- /dev/null +++ b/.github/workflows/nim-matrix.yml @@ -0,0 +1,30 @@ +name: Nim matrix + +on: + merge_group: + workflow_dispatch: + +env: + cache_nonce: 0 # Allows for easily busting actions/cache caches + nim_version: v1.6.14, v1.6.16, v1.6.18, v2.0.0, v2.0.2 + +jobs: + matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.matrix.outputs.matrix }} + cache_nonce: ${{ env.cache_nonce }} + steps: + - name: Compute matrix + id: matrix + uses: fabiocaccamo/create-matrix-action@v4 + with: + matrix: | + os {linux}, cpu {amd64}, builder {ubuntu-latest}, tests {all}, nim_version {${{ env.nim_version }}}, shell {bash --noprofile --norc -e -o pipefail} + + build: + needs: matrix + uses: ./.github/workflows/ci-reusable.yml + with: + matrix: ${{ needs.matrix.outputs.matrix }} + cache_nonce: ${{ needs.matrix.outputs.cache_nonce }}