Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
83e0357
feat(oidc): add CircleCI publisher model and registry
meeech Jan 20, 2026
673379c
feat(oidc): add CircleCI admin flag and service registration
meeech Jan 20, 2026
f9a6b8a
feat(oidc): add CircleCI publisher forms
meeech Jan 20, 2026
9fe32e8
feat(oidc): add CircleCI project publisher management view
meeech Jan 20, 2026
5b61f06
feat(oidc): add CircleCI pending publisher views for accounts
meeech Jan 20, 2026
b9ec073
feat(oidc): add CircleCI pending publisher views for organizations
meeech Jan 20, 2026
9e8c143
feat(oidc): add CircleCI sections to publishing templates
meeech Jan 20, 2026
6b031e6
feat(oidc): add CircleCI OIDC publisher database migration
meeech Jan 20, 2026
5f1d067
test(oidc): add CircleCI publisher tests and factories
meeech Jan 20, 2026
02adb03
feat(oidc): add UUID validation to CircleCI form fields
meeech Jan 21, 2026
524923c
feat(oidc): add vcs_ref and vcs_origin optional claims for CircleCI
meeech Jan 22, 2026
753dee4
chore(migrations): add vcs_ref and vcs_origin to CircleCI migration
meeech Jan 22, 2026
f4a93f0
fix(tests): use valid UUIDs in CircleCI OIDC publisher view tests
meeech Jan 22, 2026
a9517d5
fix(tests): add missing CircleCI form fields in organization view tests
meeech Jan 22, 2026
94a9476
test(oidc): add tests for vcs_ref and vcs_origin form fields
meeech Jan 22, 2026
3125f73
test(oidc): add model tests for vcs_ref and vcs_origin claims
meeech Jan 22, 2026
db7de0b
feat(templates): add vcs_ref and vcs_origin fields to CircleCI forms
meeech Jan 27, 2026
a491c7b
fix(templates): reorder VCS fields - origin before ref
meeech Jan 27, 2026
50f15ed
fix(migrations): regenerate CircleCI OIDC publisher migration
meeech Jan 27, 2026
05322a3
make reformat
meeech Jan 27, 2026
99ccf2d
feat(oidc): add attestation_identity property to CircleCI publisher
meeech Jan 27, 2026
0f431cb
test(oidc): add missing CircleCI publisher model test coverage
meeech Jan 28, 2026
0501afc
test(oidc): add missing CircleCI publisher form test coverage
meeech Jan 28, 2026
acd717c
test(oidc): populate all optional fields in CircleCI prefill test
meeech Jan 28, 2026
4c25708
feat(oidc): display all CircleCI publisher fields in manage UI
meeech Feb 4, 2026
2719126
updatre migration to point to the latest for the down
meeech Feb 7, 2026
00cf61d
normalize the optional values on the form which everything else cons…
meeech Feb 23, 2026
d7a0226
update revises field
meeech Feb 23, 2026
8cfd208
update tests for use of normalized
meeech Feb 23, 2026
3d6dd06
update migration
meeech Feb 24, 2026
d820ef3
feat(oidc): fetch CircleCI project metadata during publisher validation
meeech Mar 2, 2026
c46dcf5
feat(oidc): persist CircleCI org/project names on publishers
meeech Mar 2, 2026
a02650e
feat(ui): display CircleCI org/project names in manage publisher details
meeech Mar 2, 2026
31e2f9f
update the revises/down revision
meeech Mar 2, 2026
1582d91
update CircleCI publisher URLs to return valid links
meeech Mar 3, 2026
de7dcf9
update translations
meeech Mar 12, 2026
bafa296
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Mar 18, 2026
749a665
update translation
meeech Mar 18, 2026
09720e7
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Mar 18, 2026
3a9c79c
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Mar 24, 2026
f3e7908
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Mar 26, 2026
aeee84c
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Mar 30, 2026
4e6c449
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Apr 5, 2026
81d5afe
Merge branch 'main' into add-cci-trusted-publisher-take-2
meeech Apr 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions tests/common/db/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

from warehouse.oidc.models import (
ActiveStatePublisher,
CircleCIPublisher,
GitHubPublisher,
GitLabPublisher,
GooglePublisher,
PendingActiveStatePublisher,
PendingCircleCIPublisher,
PendingGitHubPublisher,
PendingGitLabPublisher,
PendingGooglePublisher,
Expand Down Expand Up @@ -122,3 +124,35 @@ class Meta:
actor = factory.Faker("pystr", max_chars=12)
actor_id = factory.Faker("uuid4")
added_by = factory.SubFactory(UserFactory)


class CircleCIPublisherFactory(WarehouseFactory):
class Meta:
model = CircleCIPublisher

id = factory.Faker("uuid4", cast_to=None)
circleci_org_id = factory.Faker("uuid4")
circleci_project_id = factory.Faker("uuid4")
pipeline_definition_id = factory.Faker("uuid4")
context_id = ""
vcs_ref = ""
vcs_origin = ""
circleci_org_name = None
circleci_project_name = None


class PendingCircleCIPublisherFactory(WarehouseFactory):
class Meta:
model = PendingCircleCIPublisher

id = factory.Faker("uuid4", cast_to=None)
project_name = factory.Faker("pystr", max_chars=12)
circleci_org_id = factory.Faker("uuid4")
circleci_project_id = factory.Faker("uuid4")
pipeline_definition_id = factory.Faker("uuid4")
context_id = ""
vcs_ref = ""
vcs_origin = ""
circleci_org_name = None
circleci_project_name = None
added_by = factory.SubFactory(UserFactory)
83 changes: 83 additions & 0 deletions tests/unit/accounts/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3969,6 +3969,15 @@ def test_manage_publishing(self, metrics, monkeypatch):
"PendingActiveStatePublisherForm",
pending_activestate_publisher_form_cls,
)
pending_circleci_publisher_form_obj = pretend.stub()
pending_circleci_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_circleci_publisher_form_obj
)
monkeypatch.setattr(
views,
"PendingCircleCIPublisherForm",
pending_circleci_publisher_form_cls,
)

view = views.ManageAccountPublishingViews(request)

Expand All @@ -3978,11 +3987,13 @@ def test_manage_publishing(self, metrics, monkeypatch):
"GitLab": False,
"Google": False,
"ActiveState": False,
"CircleCI": False,
},
"pending_github_publisher_form": pending_github_publisher_form_obj,
"pending_gitlab_publisher_form": pending_gitlab_publisher_form_obj,
"pending_google_publisher_form": pending_google_publisher_form_obj,
"pending_activestate_publisher_form": pending_activestate_publisher_form_obj, # noqa: E501
"pending_circleci_publisher_form": pending_circleci_publisher_form_obj,
}

assert request.flags.disallow_oidc.calls == [
Expand All @@ -3991,6 +4002,7 @@ def test_manage_publishing(self, metrics, monkeypatch):
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
]
assert pending_github_publisher_form_cls.calls == [
pretend.call(
Expand Down Expand Up @@ -4057,6 +4069,15 @@ def test_manage_publishing_admin_disabled(self, monkeypatch, pyramid_request):
"PendingActiveStatePublisherForm",
pending_activestate_publisher_form_cls,
)
pending_circleci_publisher_form_obj = pretend.stub()
pending_circleci_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_circleci_publisher_form_obj
)
monkeypatch.setattr(
views,
"PendingCircleCIPublisherForm",
pending_circleci_publisher_form_cls,
)

view = views.ManageAccountPublishingViews(pyramid_request)

Expand All @@ -4066,11 +4087,13 @@ def test_manage_publishing_admin_disabled(self, monkeypatch, pyramid_request):
"GitLab": True,
"Google": True,
"ActiveState": True,
"CircleCI": True,
},
"pending_github_publisher_form": pending_github_publisher_form_obj,
"pending_gitlab_publisher_form": pending_gitlab_publisher_form_obj,
"pending_google_publisher_form": pending_google_publisher_form_obj,
"pending_activestate_publisher_form": pending_activestate_publisher_form_obj, # noqa: E501
"pending_circleci_publisher_form": pending_circleci_publisher_form_obj,
}

assert pyramid_request.flags.disallow_oidc.calls == [
Expand All @@ -4079,6 +4102,7 @@ def test_manage_publishing_admin_disabled(self, monkeypatch, pyramid_request):
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
]
assert pyramid_request.session.flash.calls == [
pretend.call(
Expand Down Expand Up @@ -4130,6 +4154,11 @@ def test_manage_publishing_admin_disabled(self, monkeypatch, pyramid_request):
AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC,
"ActiveState",
),
(
"add_pending_circleci_oidc_publisher",
AdminFlagValue.DISALLOW_CIRCLECI_OIDC,
"CircleCI",
),
],
)
def test_add_pending_oidc_publisher_admin_disabled(
Expand Down Expand Up @@ -4186,6 +4215,15 @@ def test_add_pending_oidc_publisher_admin_disabled(
monkeypatch.setattr(
views, "PendingGooglePublisherForm", pending_google_publisher_form_cls
)
pending_circleci_publisher_form_obj = pretend.stub()
pending_circleci_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_circleci_publisher_form_obj
)
monkeypatch.setattr(
views,
"PendingCircleCIPublisherForm",
pending_circleci_publisher_form_cls,
)

view = views.ManageAccountPublishingViews(pyramid_request)

Expand All @@ -4195,23 +4233,27 @@ def test_add_pending_oidc_publisher_admin_disabled(
"GitLab": True,
"Google": True,
"ActiveState": True,
"CircleCI": True,
},
"pending_github_publisher_form": pending_github_publisher_form_obj,
"pending_gitlab_publisher_form": pending_gitlab_publisher_form_obj,
"pending_google_publisher_form": pending_google_publisher_form_obj,
"pending_activestate_publisher_form": pending_activestate_publisher_form_obj, # noqa: E501
"pending_circleci_publisher_form": pending_circleci_publisher_form_obj,
}

assert pyramid_request.flags.disallow_oidc.calls == [
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
pretend.call(flag),
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
]
assert pyramid_request.session.flash.calls == [
pretend.call(
Expand Down Expand Up @@ -4264,6 +4306,11 @@ def test_add_pending_oidc_publisher_admin_disabled(
AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC,
"ActiveState",
),
(
"add_pending_circleci_oidc_publisher",
AdminFlagValue.DISALLOW_CIRCLECI_OIDC,
"CircleCI",
),
],
)
def test_add_pending_oidc_publisher_user_cannot_register(
Expand Down Expand Up @@ -4326,6 +4373,15 @@ def test_add_pending_oidc_publisher_user_cannot_register(
"PendingActiveStatePublisherForm",
pending_activestate_publisher_form_cls,
)
pending_circleci_publisher_form_obj = pretend.stub()
pending_circleci_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_circleci_publisher_form_obj
)
monkeypatch.setattr(
views,
"PendingCircleCIPublisherForm",
pending_circleci_publisher_form_cls,
)

view = views.ManageAccountPublishingViews(pyramid_request)

Expand All @@ -4335,23 +4391,27 @@ def test_add_pending_oidc_publisher_user_cannot_register(
"GitLab": False,
"Google": False,
"ActiveState": False,
"CircleCI": False,
},
"pending_github_publisher_form": pending_github_publisher_form_obj,
"pending_gitlab_publisher_form": pending_gitlab_publisher_form_obj,
"pending_google_publisher_form": pending_google_publisher_form_obj,
"pending_activestate_publisher_form": pending_activestate_publisher_form_obj, # noqa: E501
"pending_circleci_publisher_form": pending_circleci_publisher_form_obj,
}

assert pyramid_request.flags.disallow_oidc.calls == [
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
pretend.call(flag),
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
]
assert view.metrics.increment.calls == [
pretend.call(
Expand Down Expand Up @@ -4493,15 +4553,18 @@ def test_add_pending_github_oidc_publisher_too_many_already(
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
pretend.call(flag),
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITHUB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
]
assert view.metrics.increment.calls == [
pretend.call(
Expand Down Expand Up @@ -4536,6 +4599,10 @@ def test_add_pending_github_oidc_publisher_too_many_already(
"add_pending_activestate_oidc_publisher",
"ActiveState",
),
(
"add_pending_circleci_oidc_publisher",
"CircleCI",
),
],
)
def test_add_pending_oidc_publisher_ratelimited(
Expand Down Expand Up @@ -4610,6 +4677,10 @@ def test_add_pending_oidc_publisher_ratelimited(
"add_pending_activestate_oidc_publisher",
"ActiveState",
),
(
"add_pending_circleci_oidc_publisher",
"CircleCI",
),
],
)
def test_add_pending_oidc_publisher_invalid_form(
Expand Down Expand Up @@ -5102,6 +5173,15 @@ def test_delete_pending_oidc_publisher_admin_disabled(
"PendingActiveStatePublisherForm",
pending_activestate_publisher_form_cls,
)
pending_circleci_publisher_form_obj = pretend.stub()
pending_circleci_publisher_form_cls = pretend.call_recorder(
lambda *a, **kw: pending_circleci_publisher_form_obj
)
monkeypatch.setattr(
views,
"PendingCircleCIPublisherForm",
pending_circleci_publisher_form_cls,
)

view = views.ManageAccountPublishingViews(pyramid_request)

Expand All @@ -5111,11 +5191,13 @@ def test_delete_pending_oidc_publisher_admin_disabled(
"GitLab": True,
"Google": True,
"ActiveState": True,
"CircleCI": True,
},
"pending_github_publisher_form": pending_github_publisher_form_obj,
"pending_gitlab_publisher_form": pending_gitlab_publisher_form_obj,
"pending_google_publisher_form": pending_google_publisher_form_obj,
"pending_activestate_publisher_form": pending_activestate_publisher_form_obj, # noqa: E501
"pending_circleci_publisher_form": pending_circleci_publisher_form_obj,
}

assert pyramid_request.flags.disallow_oidc.calls == [
Expand All @@ -5124,6 +5206,7 @@ def test_delete_pending_oidc_publisher_admin_disabled(
pretend.call(AdminFlagValue.DISALLOW_GITLAB_OIDC),
pretend.call(AdminFlagValue.DISALLOW_GOOGLE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_ACTIVESTATE_OIDC),
pretend.call(AdminFlagValue.DISALLOW_CIRCLECI_OIDC),
]
assert pyramid_request.session.flash.calls == [
pretend.call(
Expand Down
Loading
Loading