diff --git a/.github/workflows/e2e-external-phase-2.yml b/.github/workflows/e2e-external-phase-2.yml index 9f73a38e..7b68e862 100644 --- a/.github/workflows/e2e-external-phase-2.yml +++ b/.github/workflows/e2e-external-phase-2.yml @@ -101,7 +101,7 @@ jobs: key: ${{ hashFiles('uv.lock') }} - name: Install deps - run: uv install --all-groups + run: uv sync --all-groups - name: Run end-to-end tests run: pytest tests/end_to_end diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1a5cd8f4..7f2fd13e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,28 +21,58 @@ jobs: attestations: write id-token: write steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ewjoachim password: ${{ secrets.DOCKER_PASSWORD }} - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3.6.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3.10.0 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3.3.0 with: registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ github.actor }} + password: ${{ github.token }} + + - id: docker_meta + uses: docker/metadata-action@v5.7.0 + with: + images: ghcr.io/${{ github.repository }} + tags: type=sha,format=long - name: Build and push Docker image uses: docker/build-push-action@v6 with: - # See Dockerfile.build for instructions on bumping this. + context: . + file: Dockerfile.build + platforms: linux/amd64,linux/arm64 + labels: | + project='python-coverage-comment-action-base' + org='py-cov-action' + commit-sha='${{ github.sha }}' + org.opencontainers.image.source='https://github.com/${{ github.repository }}' + org.opencontainers.image.description='Publish coverage report as PR comment, and create a coverage badge & dashboard to display on the Readme for Python projects, all inside GitHub without third party servers' + org.opencontainers.image.licenses='MIT' tags: | ewjoachim/python-coverage-comment-action-base:v6 ghcr.io/py-cov-action/python-coverage-comment-action-base:v6 + ${{ steps.docker_meta.outputs.tags }} + ghcr.io/${{ github.repository }}:${{ github.sha }} + ghcr.io/${{ github.repository }}:latest + cache-from: | + ghcr.io/${{ github.repository }}:${{ github.sha }} + ghcr.io/${{ github.repository }}:latest + cache-to: type=inline push: true - file: Dockerfile.build compute-tags: name: Re-tag action with new version diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 20ceb6aa..7c6b93aa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: - id: check-added-large-files - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.9.9 + rev: v0.11.8 hooks: - id: ruff args: [--fix] diff --git a/Dockerfile b/Dockerfile index 8cef855d..7c45db63 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # See Dockerfile.build for instructions on bumping this. -FROM ewjoachim/python-coverage-comment-action-base:v6 +FROM ghcr.io/py-cov-action/python-coverage-comment-action-base:v6 COPY coverage_comment ./coverage_comment RUN md5sum -c pyproject.toml.md5 || pip install -e . diff --git a/Dockerfile.build b/Dockerfile.build index aff94169..bb3dce68 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -14,7 +14,7 @@ RUN git config --system --add safe.directory '*' WORKDIR /workdir -COPY pyproject.toml ./ +COPY pyproject.toml LICENSE ./ RUN md5sum pyproject.toml > pyproject.toml.md5 COPY coverage_comment ./coverage_comment diff --git a/README.md b/README.md index 2fcbfc43..31ea33b9 100644 --- a/README.md +++ b/README.md @@ -258,10 +258,10 @@ jobs: run: make test # This is the part where you put your own test command env: COVERAGE_FILE: ".coverage.${{ matrix.python_version }}" - # Alternatively you can run coverage with the --parallel flag or add - # `parallel = True` in the coverage config file. - # If using pytest-cov, you can also add the `--cov-append` flag - # directly or through PYTEST_ADD_OPTS. + # The file name prefix must be ".coverage." for "coverage combine" + # enabled by "MERGE_COVERAGE_FILES: true" to work. A "subprocess" + # error with the message "No data to combine" will be triggered if + # this prefix is not used. - name: Store coverage file uses: actions/upload-artifact@v4 @@ -269,8 +269,10 @@ jobs: name: coverage-${{ matrix.python_version }} path: .coverage.${{ matrix.python_version }} # By default hidden files/folders (i.e. starting with .) are ignored. - # You may prefer (for security reason) not setting this and instead - # set COVERAGE_FILE above to not start with a `.` + # You may prefer (for security reasons) not setting this and instead + # set COVERAGE_FILE above to not start with a `.`, but you cannot + # use "MERGE_COVERAGE_FILES: true" later on and need to manually + # combine the coverage file using "pipx run coverage combine" include-hidden-files: true coverage: diff --git a/action.yml b/action.yml index 9a6c2c70..a6fa986f 100644 --- a/action.yml +++ b/action.yml @@ -118,6 +118,7 @@ runs: using: docker image: Dockerfile env: + GITHUB_BASE_URL: ${{ inputs.GITHUB_BASE_URL }} GITHUB_TOKEN: ${{ inputs.GITHUB_TOKEN }} GITHUB_PR_RUN_ID: ${{ inputs.GITHUB_PR_RUN_ID }} COMMENT_TEMPLATE: ${{ inputs.COMMENT_TEMPLATE }} diff --git a/coverage_comment/main.py b/coverage_comment/main.py index 8da1c792..20f46468 100644 --- a/coverage_comment/main.py +++ b/coverage_comment/main.py @@ -33,20 +33,22 @@ def main(): log.info("Starting action") config = settings.Config.from_environ(environ=os.environ) - github_session = httpx.Client( - base_url=config.GITHUB_BASE_URL, - follow_redirects=True, - headers={"Authorization": f"token {config.GITHUB_TOKEN}"}, - ) - http_session = httpx.Client() git = subprocess.Git() - exit_code = action( - config=config, - github_session=github_session, - http_session=http_session, - git=git, - ) + with ( + httpx.Client( + base_url=config.GITHUB_BASE_URL, + follow_redirects=True, + headers={"Authorization": f"token {config.GITHUB_TOKEN}"}, + ) as github_session, + httpx.Client() as http_session, + ): + exit_code = action( + config=config, + github_session=github_session, + http_session=http_session, + git=git, + ) log.info("Ending action") sys.exit(exit_code) diff --git a/scripts/sync-pre-commit.py b/scripts/sync-pre-commit.py index 3cea8d95..67c20429 100755 --- a/scripts/sync-pre-commit.py +++ b/scripts/sync-pre-commit.py @@ -42,6 +42,7 @@ def export_from_uv_lock(group_args): "--no-header", "--no-emit-project", "--no-emit-workspace", + "--no-annotate", ] packages = ( subprocess.check_output( diff --git a/tests/end_to_end/conftest.py b/tests/end_to_end/conftest.py index 1bafa6a1..ac4a84b4 100644 --- a/tests/end_to_end/conftest.py +++ b/tests/end_to_end/conftest.py @@ -11,6 +11,7 @@ import subprocess import time +import httpx import pytest import tenacity @@ -387,3 +388,9 @@ def f(line): git("commit", "-m", "improve coverage") return f + + +@pytest.fixture +def http_client(): + with httpx.Client() as client: + yield client diff --git a/tests/end_to_end/repo/.github/workflows/ci.yml b/tests/end_to_end/repo/.github/workflows/ci.yml index 1388a17e..b07325ab 100644 --- a/tests/end_to_end/repo/.github/workflows/ci.yml +++ b/tests/end_to_end/repo/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.12" + python-version: "3.13" - run: pip install -e . working-directory: __ACTION_COVERAGE_PATH__ diff --git a/tests/end_to_end/test_all.py b/tests/end_to_end/test_all.py index 5ca63c2f..2501e55c 100644 --- a/tests/end_to_end/test_all.py +++ b/tests/end_to_end/test_all.py @@ -2,7 +2,6 @@ import base64 -import httpx import pytest @@ -24,6 +23,7 @@ def test_public_repo( token_other, gh_create_fork, gh_other_username, + http_client, ): # Create a GitHub repo, make it public gh_create_repo("--public") @@ -60,14 +60,12 @@ def test_public_repo( # - coverage branch readme url assert len(links) == 5 - client = httpx.Client() - # Check that all 5 links are valid and lead to a 200 # It's made this way to avoid hardcoding links in the test, because I assume # they'll be evolving. number_of_svgs = 0 for link in links: - response = client.get(link) + response = http_client.get(link) response.raise_for_status() number_of_svgs += int(response.text.startswith("