diff --git a/docs/user/trusted-publishers/adding-a-publisher.md b/docs/user/trusted-publishers/adding-a-publisher.md index 8f9643a0c24f..34498923df6c 100644 --- a/docs/user/trusted-publishers/adding-a-publisher.md +++ b/docs/user/trusted-publishers/adding-a-publisher.md @@ -117,6 +117,13 @@ each. **optionally** provide the name of a [GitLab CI/CD environment](https://docs.gitlab.com/ee/ci/environments/). + !!! note + + The repository's namepsace and name must be provided as lowercase. + For example, if your project is at `https://gitlab.com/NameSpace/SampleProject`, + you must enter `namespace` as the namespace and `sampleproject` as the + project name. + For example, if you have a project at `https://gitlab.com/namespace/sampleproject` with a top-level pipeline defined in `.gitlab-ci.yml` and a custom environment named `release`, then you'd do the following: diff --git a/tests/unit/oidc/forms/test_gitlab.py b/tests/unit/oidc/forms/test_gitlab.py index c6b494c06d11..f4c76179404a 100644 --- a/tests/unit/oidc/forms/test_gitlab.py +++ b/tests/unit/oidc/forms/test_gitlab.py @@ -152,6 +152,16 @@ def test_validate(self, data): }, {"project": "some", "namespace": "some", "workflow_filepath": None}, {"project": "some", "namespace": "some", "workflow_filepath": ""}, + { + "namespace": "some-owner", + "project": "CaseSensitive", + "workflow_filepath": "some-workflow.yml", + }, + { + "namespace": "CaseSensitive", + "project": "some-repo", + "workflow_filepath": "some-workflow.yml", + }, ], ) def test_validate_basic_invalid_fields(self, data): diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index e396b50bed4e..5530083fe7d1 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -394,7 +394,7 @@ msgid "Select project" msgstr "" #: warehouse/manage/forms.py:507 warehouse/oidc/forms/_core.py:36 -#: warehouse/oidc/forms/gitlab.py:47 +#: warehouse/oidc/forms/gitlab.py:60 msgid "Specify project name" msgstr "" @@ -677,7 +677,7 @@ msgid "Expired invitation for '${username}' deleted." msgstr "" #: warehouse/oidc/forms/_core.py:38 warehouse/oidc/forms/_core.py:49 -#: warehouse/oidc/forms/gitlab.py:50 warehouse/oidc/forms/gitlab.py:54 +#: warehouse/oidc/forms/gitlab.py:64 warehouse/oidc/forms/gitlab.py:68 msgid "Invalid project name" msgstr "" @@ -827,27 +827,31 @@ msgstr "" msgid "Name ends with .git or .atom" msgstr "" -#: warehouse/oidc/forms/gitlab.py:31 +#: warehouse/oidc/forms/gitlab.py:34 +msgid "Value must be lowercase" +msgstr "" + +#: warehouse/oidc/forms/gitlab.py:43 msgid "Specify GitLab namespace (username or group/subgroup)" msgstr "" -#: warehouse/oidc/forms/gitlab.py:36 warehouse/oidc/forms/gitlab.py:40 +#: warehouse/oidc/forms/gitlab.py:49 warehouse/oidc/forms/gitlab.py:53 msgid "Invalid GitLab username or group/subgroup name." msgstr "" -#: warehouse/oidc/forms/gitlab.py:62 +#: warehouse/oidc/forms/gitlab.py:76 msgid "Specify top-level pipeline file path" msgstr "" -#: warehouse/oidc/forms/gitlab.py:71 +#: warehouse/oidc/forms/gitlab.py:85 msgid "Invalid environment name" msgstr "" -#: warehouse/oidc/forms/gitlab.py:86 +#: warehouse/oidc/forms/gitlab.py:100 msgid "Top-level pipeline file path must end with .yml or .yaml" msgstr "" -#: warehouse/oidc/forms/gitlab.py:90 +#: warehouse/oidc/forms/gitlab.py:104 msgid "Top-level pipeline file path cannot start or end with /" msgstr "" diff --git a/warehouse/oidc/forms/gitlab.py b/warehouse/oidc/forms/gitlab.py index 00b100cf5a51..2667d75092e6 100644 --- a/warehouse/oidc/forms/gitlab.py +++ b/warehouse/oidc/forms/gitlab.py @@ -22,6 +22,18 @@ def ends_with_atom_or_git(form: wtforms.Form, field: wtforms.Field) -> None: raise wtforms.validators.ValidationError(_("Name ends with .git or .atom")) +def _lowercase_only(form: wtforms.Form, field: wtforms.Field) -> None: + """ + GitLab API is case-insensitive for namespaces and projects. + Instead of changing the regular expressions to remove uppercase letters, + we add this additional validator to ensure that users only enter lowercase + characters, and provide a clear error message if they do not. + """ + field_value = typing.cast(str, field.data) + if field_value != field_value.lower(): + raise wtforms.validators.ValidationError(_("Value must be lowercase")) + + class GitLabPublisherBase(wtforms.Form): __params__ = ["namespace", "project", "workflow_filepath", "environment"] @@ -31,6 +43,7 @@ class GitLabPublisherBase(wtforms.Form): message=_("Specify GitLab namespace (username or group/subgroup)"), ), ends_with_atom_or_git, + _lowercase_only, wtforms.validators.Regexp( _VALID_GITLAB_NAMESPACE, message=_("Invalid GitLab username or group/subgroup name."), @@ -46,6 +59,7 @@ class GitLabPublisherBase(wtforms.Form): validators=[ wtforms.validators.InputRequired(message=_("Specify project name")), ends_with_atom_or_git, + _lowercase_only, wtforms.validators.Regexp( _VALID_GITLAB_PROJECT, message=_("Invalid project name") ),