diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2a5d0a2bd..50015c775 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,20 +19,10 @@ updates: directory: "/" schedule: interval: "monthly" + ignore: + - dependency-name: "pydantic-core" groups: minor-and-patch: update-types: - "minor" - "patch" - exclude-patterns: - - "pydantic*" - - # pydantic is a known violator of version updates where they don't release the core backend - # with the API library at the same time which holds up other legitimate updates, so group - # pydantic deps together - pydantic: - update-types: - - "minor" - - "patch" - patterns: - - "pydantic*" diff --git a/.github/workflows/dependabot-pipcompile.yml b/.github/workflows/dependabot-pipcompile.yml new file mode 100644 index 000000000..282b2678e --- /dev/null +++ b/.github/workflows/dependabot-pipcompile.yml @@ -0,0 +1,76 @@ +name: Pip-compile + +on: + pull_request: + types: + - opened + - reopened + - synchronize + paths: + - requirements.txt + - requirements-extras.txt + workflow_dispatch: + inputs: {} + +# Need these permissions for the GITHUB_TOKEN to be able to post a comment to a PR +permissions: + issues: write + pull-requests: write + +jobs: + versions-check: + runs-on: ubuntu-24.04 + container: + image: python:3.9-alpine + + steps: + # Need to install git before running the checkout action in a container + - name: Install dependencies + run: apk update && apk add --no-cache git + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install pip-tools + run: | + pip install --upgrade pip + pip install --no-cache-dir pip-tools + + # This step uses multi-line string injection to GitHub environment [1] + # [1] https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#multiline-strings + - name: Run pip-compile to update requirements.txt + run: | + git config --global --add safe.directory "*" + pip-compile --generate-hashes --output-file=requirements.txt pyproject.toml + pip-compile \ + --all-extras \ + --allow-unsafe \ + --generate-hashes \ + --output-file=requirements-extras.txt \ + pyproject.toml + { + echo 'GIT_DIFF<> "$GITHUB_ENV" + + # Only comment on PRs when changes to requirements files are needed, based on: + # - https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/using-conditions-to-control-job-execution + # - https://github.com/actions/github-script?tab=readme-ov-file#comment-on-an-issue + # - https://github.com/actions/github-script/issues/247#issuecomment-1079839739 + # - https://github.com/actions/github-script/issues/220#issuecomment-1007633429 + - name: Comment on pull request + uses: actions/github-script@v7 + if: env.GIT_DIFF != '' + env: + DIFF: "Changes to requirements files are needed. If you're experiencing CI test failures, please apply the following patch and update the pull request:\n```diff\n${{ env.GIT_DIFF }}\n```" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: process.env.DIFF + }) diff --git a/cachi2/core/package_managers/generic/models.py b/cachi2/core/package_managers/generic/models.py index 232e4ff2e..88fdef4f7 100644 --- a/cachi2/core/package_managers/generic/models.py +++ b/cachi2/core/package_managers/generic/models.py @@ -7,8 +7,16 @@ from urllib.parse import urljoin, urlparse from packageurl import PackageURL -from pydantic import AnyUrl, BaseModel, ConfigDict, field_validator, model_validator +from pydantic import ( + AnyUrl, + BaseModel, + ConfigDict, + PlainSerializer, + field_validator, + model_validator, +) from pydantic_core.core_schema import ValidationInfo +from typing_extensions import Annotated from cachi2.core.checksum import ChecksumInfo from cachi2.core.errors import PackageManagerError @@ -88,7 +96,7 @@ class LockfileArtifactUrl(LockfileArtifactBase): :param download_url: The URL to download the artifact from. """ - download_url: AnyUrl + download_url: Annotated[AnyUrl, PlainSerializer(lambda url: str(url), return_type=str)] def resolve_filename(self) -> str: """Resolve the filename of the artifact.""" @@ -120,7 +128,7 @@ def get_sbom_component(self) -> Component: class LockfileArtifactMavenAttributes(BaseModel): """Attributes for a Maven artifact in the lockfile.""" - repository_url: AnyUrl + repository_url: Annotated[AnyUrl, PlainSerializer(lambda url: str(url), return_type=str)] group_id: str artifact_id: str version: str diff --git a/tests/unit/package_managers/test_generic.py b/tests/unit/package_managers/test_generic.py index 162b6b961..a20b47e0b 100644 --- a/tests/unit/package_managers/test_generic.py +++ b/tests/unit/package_managers/test_generic.py @@ -3,7 +3,6 @@ from unittest import mock import pytest -from pydantic_core import Url from cachi2.core.errors import Cachi2Error, PackageRejected from cachi2.core.models.input import GenericPackageInput @@ -335,15 +334,13 @@ def test_load_generic_lockfile_valid(rooted_tmp_path: RootedPath) -> None: "metadata": {"version": "1.0"}, "artifacts": [ { - "download_url": Url("https://example.com/artifact"), + "download_url": "https://example.com/artifact", "filename": str(rooted_tmp_path.join_within_root("archive.zip")), "checksum": "md5:3a18656e1cea70504b905836dee14db0", }, { "checksum": "md5:32112bed1914cfe3799600f962750b1d", - "download_url": Url( - "https://example.com/more/complex/path/file.tar.gz?foo=bar#fragment" - ), + "download_url": "https://example.com/more/complex/path/file.tar.gz?foo=bar#fragment", "filename": str(rooted_tmp_path.join_within_root("file.tar.gz")), }, ],