diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 13650c28..ec29f228 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -10,7 +10,7 @@ jobs: smoke: name: Testnet Smoke Tests runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 10 continue-on-error: true steps: @@ -41,3 +41,5 @@ jobs: - name: Run smoke tests run: npm run test:smoke + env: + CLI_SMOKE_TIMEOUT_MS: 240000 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e52bf0a0..5995aa80 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,19 +33,11 @@ Have ideas for new features or use cases? We're eager to hear them! But first: ## Branch model -This repo uses a branch-per-major release model. There is no `main`. - -- **`v0.39`** — current stable major (semver-zero, so 0.39 IS the major; 0.40 would be a major bump that gets its own branch). PRs for bug fixes / non-breaking features target this branch. -- **`v-dev`** — when next-major work is in progress, this branch is open for breaking changes. PRs introducing them target this branch. -- **Older majors** stay for back-ports. Default branch on github.com is whichever major is current stable. - -When you fork or clone, the default branch is `v0.39` today. If you have a `main` branch from a previous checkout, delete it locally: - -```sh -git checkout v0.39 -git branch -D main -git remote prune origin -``` +See [docs/BRANCHING.md](docs/BRANCHING.md) for the current release-train model. +In short: independently releasable work may target the stable branch directly; +multi-feature or cross-repo train work uses the active `*-dev` integration +branch and is promoted to the matching stable branch when ready. `main` is only +the default/static GitHub branch. The previous `staging` branch (beta channel) has been retired. Pre-releases now go through the same release script with an explicit version (`scripts/release.sh 0.39.2-beta.0`). @@ -138,4 +130,4 @@ Connect with the GenLayer community to discuss, collaborate, and share insights: - **[Discord Channel](https://discord.gg/8Jm4v89VAu)**: Our primary hub for discussions, support, and announcements. - **[Telegram Group](https://t.me/genlayer)**: For more informal chats and quick updates. -Your continuous feedback drives better product development. Please engage with us regularly to test, discuss, and improve the GenLayer CLI. \ No newline at end of file +Your continuous feedback drives better product development. Please engage with us regularly to test, discuss, and improve the GenLayer CLI. diff --git a/docs/BRANCHING.md b/docs/BRANCHING.md new file mode 100644 index 00000000..5b8d3d60 --- /dev/null +++ b/docs/BRANCHING.md @@ -0,0 +1,58 @@ +# Branching and Release Trains + +This repo follows the GenLayer release-train model. + +## Current Train + +- Current stable branch: `v0.39` +- Active integration branch: `v0.40-dev` +- Next stable target: `v0.40` +- `main`: default/static branch alias for the active integration branch + +## Stable Branches + +Stable branches are long-lived release lines. For semver-zero packages, each +minor line is treated as the release line, for example `v0.39` or `v0.40`. + +PRs may target a stable branch directly when the merged result should be +releasable immediately. This is appropriate for bug fixes, small non-breaking +features, isolated release fixes, or a breaking change that is intentionally +shipping as the next version by itself. + +Stable branches must remain releasable. PRs into stable branches are expected to +pass the required cross-repo `E2E Tests` gate before merge. + +## Integration Branches + +Integration branches are optional. Use one when multiple changes need to +accumulate before release, especially for cross-repo work, dependent features, +breaking changes that must ship together, or a train that needs advisory E2E +while still expected to be red. + +Integration branches are named after the target stable branch plus `-dev`, for +example `v0.40-dev`. Feature PRs for that train target the integration branch. + +PRs into integration branches may run `E2E Tests` as advisory checks. They are +not the release gate. + +## Promotion and Release + +When an integration train is ready, open a promotion PR from the integration +branch to the matching stable branch, for example `v0.40-dev` to `v0.40`. + +That promotion PR is the release-readiness gate and must pass required +cross-repo `E2E Tests`. The actual package release is cut from the stable branch +using a version tag after the stable branch is ready. + +## `main` + +`main` exists for GitHub UX and tools that require a stable default branch. It is +not a release branch and it is not the integration target. + +This repo keeps `main` forwarded to the active integration branch using +automation. PRs opened against `main` are automatically retargeted to the branch +listed in `support/ci/ACTIVE_DEV_BRANCH`. + +When changing the active integration branch, update +`support/ci/ACTIVE_DEV_BRANCH`, the repo docs, and the corresponding +`genlayer-e2e` release-train matrix in the same change set. diff --git a/tests/smoke.test.ts b/tests/smoke.test.ts index 56808871..7c34ed33 100644 --- a/tests/smoke.test.ts +++ b/tests/smoke.test.ts @@ -1,16 +1,19 @@ import {describe, it, expect, beforeAll} from "vitest"; -import {execSync} from "child_process"; +import {execFile} from "child_process"; +import {promisify} from "util"; import path from "path"; import {createClient, parseStakingAmount, formatStakingAmount} from "genlayer-js"; import {testnetAsimov, testnetBradbury} from "genlayer-js/chains"; import type {Address, GenLayerChain} from "genlayer-js/types"; const CLI = path.resolve(__dirname, "../dist/index.js"); +const execFileAsync = promisify(execFile); // Testnet validator-list fetches ALL validators + per-validator detail in -// batches; on bradbury/asimov that routinely passes 30s. 90s gives headroom -// without hiding real hangs. +// batches; on bradbury/asimov that routinely passes 30s. Keep RPC calls capped +// at 90s, but give the full CLI smoke path extra room for live testnet slowness. const TIMEOUT = 90_000; +const CLI_TIMEOUT = Number(process.env.CLI_SMOKE_TIMEOUT_MS ?? 180_000); const testnets: {name: string; chain: GenLayerChain}[] = [ {name: "Asimov", chain: testnetAsimov}, @@ -127,14 +130,16 @@ describe(`Testnet ${name} - CLI Staking Smoke Tests`, () => { } }, TIMEOUT); - it("CLI: genlayer staking validators lists validators", () => { - const output = execSync( - `node ${CLI} staking validators --network ${name === "Asimov" ? "testnet-asimov" : "testnet-bradbury"}`, - {encoding: "utf-8", timeout: TIMEOUT}, + it("CLI: genlayer staking validators lists validators", async () => { + const {stdout, stderr} = await execFileAsync( + "node", + [CLI, "staking", "validators", "--network", name === "Asimov" ? "testnet-asimov" : "testnet-bradbury"], + {encoding: "utf-8", timeout: CLI_TIMEOUT}, ); + const output = `${stdout}${stderr}`; expect(output).toContain("active"); expect(output).toMatch(/Total: \d+ validators/); - }, TIMEOUT); + }, CLI_TIMEOUT + 10_000); it("parseStakingAmount and formatStakingAmount round-trip", () => { const parsed = parseStakingAmount("1.5gen");