diff --git a/.github/release-please/config.json b/.github/release-please/config.json new file mode 100644 index 00000000..6da049fd --- /dev/null +++ b/.github/release-please/config.json @@ -0,0 +1,12 @@ +{ + "bootstrap-sha": "127e7bf7b9b487149c64e76a8f9f90c573e675a5", + "include-component-in-tag": false, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "packages": { + "node": { + "component": "era-consensus", + "release-type": "simple" + } + } +} diff --git a/.github/release-please/manifest.json b/.github/release-please/manifest.json new file mode 100644 index 00000000..facb287e --- /dev/null +++ b/.github/release-please/manifest.json @@ -0,0 +1,3 @@ +{ + "node": "0.1.0" +} diff --git a/.github/workflows/pr-title.yaml b/.github/workflows/pr-title.yaml new file mode 100644 index 00000000..92c2c9dc --- /dev/null +++ b/.github/workflows/pr-title.yaml @@ -0,0 +1,49 @@ +name: PR title +on: + pull_request: + types: + - opened + - reopened + - edited + - synchronize + +jobs: + lint: + runs-on: ubuntu-latest + permissions: + statuses: write + pull-requests: write + steps: + - uses: amannn/action-semantic-pull-request@v5 + id: lint_pr_title + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: marocchino/sticky-pull-request-comment@v2 + # When the previous steps fails, the workflow would stop. By adding this + # condition you can continue the execution with the populated error message. + if: always() && (steps.lint_pr_title.outputs.error_message != null) + with: + header: pr-title-lint-error + message: | + Hey there! 👋🏼 + + We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. + Examples of valid PR titles: + + - feat(boojum): Expose more public methods + - fix(franklin-crypto): Correctly handle edge case + - ci: Add new workflow for linting + + Details: + + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + + # Delete a previous comment when the issue has been resolved + - if: ${{ steps.lint_pr_title.outputs.error_message == null }} + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: pr-title-lint-error + delete: true diff --git a/.github/workflows/release-please-prepare-branch.yml b/.github/workflows/release-please-prepare-branch.yml new file mode 100644 index 00000000..43a5d897 --- /dev/null +++ b/.github/workflows/release-please-prepare-branch.yml @@ -0,0 +1,71 @@ +on: + push: + branches: + - release-please--branches--main--components--era-consensus + +env: + EXPECTED_COMMIT_MESSAGE: "Update version in Cargo.toml" + CARGO_TERM_COLOR: "always" + CARGO_INCREMENTAL: "0" + # Rust version to use. + # Should be aligned with the version used in core to prevent regressions on publish. + nightly: nightly-2024-08-01 + +name: release-please-update-versions +jobs: + check_state: + name: "release-please: Check if Cargo.toml is updated" + runs-on: [ubuntu-latest] + outputs: + already_committed: ${{ steps.condition.outputs.already_committed }} + + steps: + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4 + + - name: Check last commit + id: condition + run: | + COMMIT=$(git log -1 --pretty=%B) + if [[ "$COMMIT" == "$EXPECTED_COMMIT_MESSAGE" ]]; then + echo "Cargo.toml is already updated" + echo "already_committed=true" >> "$GITHUB_OUTPUT" + else + echo "Cargo.toml should be updated" + echo "already_committed=false" >> "$GITHUB_OUTPUT" + fi + + update_version: + runs-on: [ubuntu-latest] + name: "release-please: Update version in Cargo.toml" + needs: [check_state] + if: ${{ needs.check_state.outputs.already_committed != 'true' }} + steps: + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4 + with: + persist-credentials: false + + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ env.nightly }} + components: rustfmt, clippy + # Remove default `-D warnings`. This is a temporary measure. + rustflags: "" + + # cargo-workspaces fails to update versions in some cases. + - name: Install cargo-edit + run: cargo install cargo-edit + + - name: Bump version + run: | + NEW_VERSION=$(cat .github/release-please/manifest.json | jq -r '."."') + cargo-set-version set-version $NEW_VERSION --workspace --manifest-path node/Cargo.toml + + - name: Push changes + run: | + git config --global user.email "zksync-era-bot@users.noreply.github.com" + git config --global user.name "zksync-era-bot" + git remote set-url origin 'https://${{ secrets.RELEASE_TOKEN }}@github.com/matter-labs/era-consensus.git' + git add ./Cargo.toml + git commit -m "$EXPECTED_COMMIT_MESSAGE" + git push diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml new file mode 100644 index 00000000..ab543d15 --- /dev/null +++ b/.github/workflows/release-please.yaml @@ -0,0 +1,94 @@ +on: + push: + branches: + - main + workflow_dispatch: + +env: + CARGO_TERM_COLOR: "always" + CARGO_INCREMENTAL: "0" + RUSTC_WRAPPER: "sccache" + SCCACHE_GHA_ENABLED: "true" + # Rust version to use. + # Should be aligned with the version used in core to prevent regressions on publish. + nightly: nightly-2024-08-01 + +permissions: + contents: write + pull-requests: write + +name: release-please +jobs: + release-please: + runs-on: ubuntu-latest + outputs: + releases_created: ${{ steps.release.outputs.releases_created }} + release_please_output_json: ${{ toJSON(steps.release.outputs) }} + steps: + - name: Run release-please + id: release + uses: googleapis/release-please-action@7987652d64b4581673a76e33ad5e98e3dd56832f # v4.1.3 + with: + token: ${{ secrets.RELEASE_TOKEN }} + config-file: .github/release-please/config.json + manifest-file: .github/release-please/manifest.json + + - name: Show outputs + env: + OUTPUTS: ${{ toJSON(steps.release.outputs) }} + run: echo "$OUTPUTS" + + process-release: + runs-on: [ubuntu-22.04-github-hosted-32core] + needs: [release-please] + if: ${{ needs.release-please.outputs.releases_created == 'true' }} + steps: + - name: Checkout code + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4 + + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ env.nightly }} + # Remove default `-D warnings`. This is a temporary measure. + rustflags: "" + + - name: Install sccache + uses: mozilla-actions/sccache-action@v0.0.4 + + - name: Install cargo-workspaces + run: cargo install cargo-workspaces + + - name: Build each package separately + working-directory: ./node + run: cargo ws exec cargo build + + - name: Login to crates.io + run: cargo login ${{ secrets.CRATES_IO_TOKEN }} + + - name: Publish + working-directory: ./node + run: cargo ws publish --publish-as-is --allow-dirty + + - name: Set owners for new packages + working-directory: ./node + # `cargo owner --add` fails if the package is already owned by the same entity, + # so we have to check if the package is already owned by the organization. + run: | + ORG_OWNER=github:matter-labs:crates-io + for PKG in $(cargo ws list); do + cargo owner --list --quiet $PKG | grep $ORG_OWNER || cargo owner --add $ORG_OWNER $PKG + done + + - name: Send Release Info + uses: matter-labs/format-release-please-for-slack-action@69e6fe9e4ec531b7b5fb0d826f73c190db83cf42 # v2.1.0 + with: + release-please-output: ${{ needs.release-please.outputs.release_please_output_json }} + slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_RELEASES }} + + - name: Notify about failure + if: failure() + uses: matter-labs/format-release-please-for-slack-action@69e6fe9e4ec531b7b5fb0d826f73c190db83cf42 # v2.1.0 + with: + release-please-output: '{ "body": "⚠️ Failed to publish the release" }' + slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_RELEASES }} diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..b6a066a3 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,67 @@ +# Release process + +## Automatic releases + +We use [release-please](https://github.com/googleapis/release-please) to manage releases, as well +as a custom automation to publish releases on [crates.io](https://crates.io/). + +Any pull request name must follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) +specification, and then, based on the PR titles, a release pull request will be created, which +will take care of changelog generation. + +Important: only `fix` and `feat` labels will trigger a release PR creation. So, if a `chore` or `ci` +PR will be merged right after release, the PR will not be created (they _will_ be included into a release, +if a release PR exists, but they won't trigger PR creation or appear in the changelog). If you want to make +sure that the change will trigger a release PR, mark the PR as `fix` or `feat`. + +By default, a patch version will be bumped. If you want to bump a minor version, mark the PR as breaking with +an exclamation point, e.g. `feat!` or `fix!`. + +It is recommended that each PR has a component mentioned, e.g. `feat(component): Change added`. + +Once release PR is merged, it will be published to `crates.io`, and a notification will be sent to Slack. + +## Manual releases + +> [!WARNING] +> Manual releases are discouraged, and should only be used as a last resort measure. +> Discuss the manual release with the team beforehand and prepare a plan. +> It is very likely that manual release will interfere with `release-please` configuration, +> which will have to be fixed manually as well. +> +> Additionally, if the release was created, but wasn't published, you will only need a subset +> of the actions listed below (e.g. if the it failed due to a transient error, you just need to +> publish code without creating any tags; but if the release can't be published, it's better to +> remove it, fix the issue, and try releasing again via automation). + +> [!CAUTION] +> Never release code that does not correspond to any tag. + +If you want to release the packages on crates.io manually, follow this process: + +1. Install `cargo workspaces`: `cargo install cargo-workspaces` +2. Create a new branch to prepare a release. +3. Change versions in the `Cargo.toml`: + - `version` in `[workspace.package]` + - `version` in `[workspace.dependencies]` for all the relevant crates. +4. Run `cargo build`. It must succeed. +5. Commit changes. +6. Run `cargo ws publish --dry-run`. Check the output. It might fail, but it might be OK. + - `error: config value 'http.cainfo' is not set` can be ignored. + - There might be warnings, this is OK. + - There might be errors related to the version resolution, e.g. `failed to select a version` + (in particular, for `zkevm_test_harness`). It's due to a bug in cargo workspaces. + Check that the packages it complains about actually have the specified version, and if so, + it's safe to proceed. +7. Create a PR named `crates.io: Release `. Get a review and merge it. +8. From the main branch _after_ you merge it, run `cargo ws publish --publish-as-is --allow-dirty`. + - The `--publish-as-is` argument skips the versioning step, which you already did before. + - The `--allow-dirty` argument is required, because `cargo ws` temporarily removes dev-dependencies + during publishing. + - Important: if something fails and you have to do changes to the code, it's safe to run the same + command again. `cargo ws` will skip already published packages. +9. If something goes wrong, see recommendations below. +10. If everything is OK, create a tag: `git tag v`, e.g. `git tag v0.150.4` +11. `git push --tags` +12. Go to the Releases in the GitHUb, and create a release for published version. +13. Make sure that `release-please` works.