diff --git a/.github/workflows/post_release.yaml b/.github/workflows/post_release.yaml new file mode 100644 index 0000000000..f85407e6eb --- /dev/null +++ b/.github/workflows/post_release.yaml @@ -0,0 +1,65 @@ +name: Post Release Automation + +on: + release: + types: [published] + +permissions: + contents: write + pull-requests: write + +jobs: + update-version: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Configure git user for actions + run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" + + - name: Set environment variables + run: | + echo "NEW_VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_ENV + echo "NEW_BRANCH=release-${{ github.event.release.tag_name }}" >> $GITHUB_ENV + echo "COMMIT_MSG=feat(docs|fw): post ${{ github.event.release.tag_name }} release changes" >> $GITHUB_ENV + + - name: Bump version in setup configuration + run: | + sed -i "s/^version = .*/version = $NEW_VERSION/" setup.cfg + git add setup.cfg + + - name: Update changelog with release details + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_DATE: $(date +'%Y-%m-%d') + run: | + # Replace unreleased link with the new release information + RELEASE_DATE=$(date +'%Y-%m-%d') + ESCAPED_LINK="https:\/\/github.com\/ethereum\/execution-spec-tests\/releases\/tag\/${NEW_VERSION}" + RELEASE_NAME=$(gh release view ${NEW_VERSION} --json body -q '.body' | grep '^#' | head -n 1 | sed 's/^# //') + sed -i "s/^## ๐Ÿ”œ \[Unreleased\].*/## [${NEW_VERSION}](${ESCAPED_LINK}) - ${RELEASE_DATE}: ${RELEASE_NAME}/" docs/CHANGELOG.md + + # Append changelog template for the new unreleased section + { echo ""; tail -n +5 docs/changelog_section_template.md; } > temp_template.md + sed -i '/\*\*Key:\*\*/ r temp_template.md' docs/CHANGELOG.md + rm temp_template.md + + git add docs/CHANGELOG.md + + - name: Create pull request with relevant changes + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: ${{ env.NEW_BRANCH }} + commit-message: ${{ env.COMMIT_MSG }} + title: ${{ env.COMMIT_MSG }} + body: | + ## ๐Ÿ—’๏ธ Description + Post ${{ env.NEW_VERSION }} release changes: + - Bump version within `setup.cfg`. + - Update `CHANGELOG.md` and copy in `changelog_section_template.md`. + base: main \ No newline at end of file diff --git a/docs/changelog_section_template.md b/docs/changelog_section_template.md index 8cbaf9326c..e7bd6f0afb 100644 --- a/docs/changelog_section_template.md +++ b/docs/changelog_section_template.md @@ -2,7 +2,7 @@ The following can be copy-pasted into the `CHANGELOG.md` file for a new release. -## ๐Ÿ”œ [Unreleased] +## ๐Ÿ”œ [Unreleased](https://github.com/ethereum/execution-spec-tests/releases/tag/version) - 2024-xx-xx ### ๐Ÿงช Test Cases diff --git a/setup.cfg b/setup.cfg index 24d82ed00d..7c38735ccc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,9 @@ [metadata] -name = test-filler +name = execution-spec-tests description = Ethereum execution client test authoring framework long_description = file: README.md long_description_content_type = text/markdown -version = 1.0.0 +version = v2.1.0 url = https://github.com/ethereum/execution-spec-tests license_files = LICENSE @@ -67,6 +67,7 @@ lint = flake8>=6.1.0,<7 pep8-naming==0.13.3 fname8>=0.0.3 + GitPython>=3.1 docs = cairosvg>=2.7.0,<3 # required for social plugin (material) diff --git a/src/ethereum_test_tools/__init__.py b/src/ethereum_test_tools/__init__.py index 7d6d144f74..63be02a60b 100644 --- a/src/ethereum_test_tools/__init__.py +++ b/src/ethereum_test_tools/__init__.py @@ -55,6 +55,7 @@ TestInfo, ) from .spec.blockchain.types import Block, Header +from .utility.helpers import get_framework_version from .vm import Opcode, OpcodeCallArg, Opcodes __all__ = ( @@ -112,5 +113,6 @@ "cost_memory_bytes", "eip_2028_transaction_data_cost", "eip_2028_transaction_data_cost", + "get_framework_version", "transaction_list_root", ) diff --git a/src/ethereum_test_tools/spec/__init__.py b/src/ethereum_test_tools/spec/__init__.py index 9f32e30838..81b0fd9a86 100644 --- a/src/ethereum_test_tools/spec/__init__.py +++ b/src/ethereum_test_tools/spec/__init__.py @@ -1,6 +1,7 @@ """ Test spec definitions and utilities. """ + from typing import List, Type from .base.base_test import BaseFixture, BaseTest, TestSpec, verify_post_alloc diff --git a/src/ethereum_test_tools/spec/base/base_test.py b/src/ethereum_test_tools/spec/base/base_test.py index cd436de46c..f07169f568 100644 --- a/src/ethereum_test_tools/spec/base/base_test.py +++ b/src/ethereum_test_tools/spec/base/base_test.py @@ -1,6 +1,7 @@ """ Base test class and helper functions for Ethereum state and blockchain tests. """ + from abc import abstractmethod from dataclasses import dataclass, field from itertools import count @@ -16,6 +17,7 @@ from ...common.json import JSONEncoder from ...common.json import field as json_field from ...reference_spec.reference_spec import ReferenceSpec +from ...utility.helpers import get_framework_version def verify_transactions(txs: List[Transaction] | None, result) -> List[int]: @@ -100,6 +102,7 @@ def fill_info( self.info["filling-transition-tool"] = t8n.version() if ref_spec is not None: ref_spec.write_info(self.info) + self.info["framework-version"] = get_framework_version() @abstractmethod def to_json(self) -> Dict[str, Any]: diff --git a/src/ethereum_test_tools/utility/__init__.py b/src/ethereum_test_tools/utility/__init__.py new file mode 100644 index 0000000000..a454413a26 --- /dev/null +++ b/src/ethereum_test_tools/utility/__init__.py @@ -0,0 +1,7 @@ +""" +Utility functions used within the EEST framework. +""" + +from .helpers import get_framework_version + +__all__ = ("get_framework_version",) diff --git a/src/ethereum_test_tools/utility/helpers.py b/src/ethereum_test_tools/utility/helpers.py new file mode 100644 index 0000000000..1d4929b0d4 --- /dev/null +++ b/src/ethereum_test_tools/utility/helpers.py @@ -0,0 +1,18 @@ +""" +Utility functions for the EEST framework. +""" + +from importlib.metadata import version + +from git import InvalidGitRepositoryError, Repo + + +def get_framework_version() -> str: + """ + Returns the current version of the EEST framework. + """ + try: + local_commit_hash = Repo(search_parent_directories=True).head.commit.hexsha[:7] + except InvalidGitRepositoryError: # required for some framework tests + local_commit_hash = "unknown" + return f"execution-spec-tests v{version('execution-spec-tests')}-{local_commit_hash}" diff --git a/src/pytest_plugins/test_filler/test_filler.py b/src/pytest_plugins/test_filler/test_filler.py index a468d495c2..8d4041225a 100644 --- a/src/pytest_plugins/test_filler/test_filler.py +++ b/src/pytest_plugins/test_filler/test_filler.py @@ -19,7 +19,14 @@ get_closest_fork_with_solc_support, get_forks_with_solc_support, ) -from ethereum_test_tools import SPEC_TYPES, BaseTest, FixtureCollector, TestInfo, Yul +from ethereum_test_tools import ( + SPEC_TYPES, + BaseTest, + FixtureCollector, + TestInfo, + Yul, + get_framework_version, +) from evm_transition_tool import FixtureFormats, TransitionTool from pytest_plugins.spec_version_checker.spec_version_checker import EIPSpecTestItem @@ -126,6 +133,14 @@ def pytest_addoption(parser): help="Path to dump the transition tool debug output.", ) + version_group = parser.getgroup("version_info", "Versioning of the EEST framework") + version_group.addoption( + "--version-info", + action="store_true", + default=False, + help="Displays the versioning information of the framework.", + ) + @pytest.hookimpl(tryfirst=True) def pytest_configure(config): @@ -175,6 +190,10 @@ def pytest_configure(config): f"{Frontier.solc_min_version()}", returncode=pytest.ExitCode.USAGE_ERROR, ) + if config.getoption("version_info"): + pytest.exit( + f"'Displaying framework version information'\n" f"> {get_framework_version()}\n" + ) @pytest.hookimpl(trylast=True) diff --git a/stubs/git/__init__.pyi b/stubs/git/__init__.pyi new file mode 100644 index 0000000000..38517c8694 --- /dev/null +++ b/stubs/git/__init__.pyi @@ -0,0 +1,9 @@ +from typing import Any + +class Repo: + def __init__(self, path: str = ..., search_parent_directories: bool = ...) -> None: ... + @property + def head(self) -> Any: ... + +class InvalidGitRepositoryError(Exception): + pass