Skip to content

Commit 57d5fc4

Browse files
committed
wip
1 parent fd6088d commit 57d5fc4

File tree

6 files changed

+479
-3
lines changed

6 files changed

+479
-3
lines changed

warehouse/accounts/views.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,14 @@
7777
from warehouse.events.tags import EventTag
7878
from warehouse.metrics.interfaces import IMetricsService
7979
from warehouse.oidc.forms import DeletePublisherForm
80+
from warehouse.oidc.forms.buildkite import PendingBuildkitePublisherForm
8081
from warehouse.oidc.forms.github import PendingGitHubPublisherForm
8182
from warehouse.oidc.interfaces import TooManyOIDCRegistrations
82-
from warehouse.oidc.models import PendingGitHubPublisher, PendingOIDCPublisher
83+
from warehouse.oidc.models import (
84+
PendingBuildkitePublisher,
85+
PendingGitHubPublisher,
86+
PendingOIDCPublisher,
87+
)
8388
from warehouse.organizations.interfaces import IOrganizationService
8489
from warehouse.organizations.models import OrganizationRole, OrganizationRoleType
8590
from warehouse.packaging.models import (
@@ -1488,6 +1493,13 @@ def _check_ratelimits(self):
14881493
)
14891494
)
14901495

1496+
@property
1497+
def pending_buildkite_publisher_form(self):
1498+
return PendingBuildkitePublisherForm(
1499+
self.request.POST,
1500+
project_factory=self.project_factory
1501+
)
1502+
14911503
@property
14921504
def pending_github_publisher_form(self):
14931505
return PendingGitHubPublisherForm(
@@ -1499,6 +1511,7 @@ def pending_github_publisher_form(self):
14991511
@property
15001512
def default_response(self):
15011513
return {
1514+
"pending_buildkite_publisher_form": self.pending_buildkite_publisher_form,
15021515
"pending_github_publisher_form": self.pending_github_publisher_form,
15031516
}
15041517

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License");
2+
# you may not use this file except in compliance with the License.
3+
# You may obtain a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS,
9+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# See the License for the specific language governing permissions and
11+
# limitations under the License.
12+
"""
13+
Add Buildkite OIDC models
14+
15+
Revision ID: 8c83f0a1d70e
16+
Revises: 186f076eb60b
17+
Create Date: 2023-10-27 09:20:18.030874
18+
"""
19+
20+
import sqlalchemy as sa
21+
22+
from alembic import op
23+
24+
revision = "8c83f0a1d70e"
25+
down_revision = "186f076eb60b"
26+
27+
# Note: It is VERY important to ensure that a migration does not lock for a
28+
# long period of time and to ensure that each individual migration does
29+
# not break compatibility with the *previous* version of the code base.
30+
# This is because the migrations will be ran automatically as part of the
31+
# deployment process, but while the previous version of the code is still
32+
# up and running. Thus backwards incompatible changes must be broken up
33+
# over multiple migrations inside of multiple pull requests in order to
34+
# phase them in over multiple deploys.
35+
#
36+
# By default, migrations cannot wait more than 4s on acquiring a lock
37+
# and each individual statement cannot take more than 5s. This helps
38+
# prevent situations where a slow migration takes the entire site down.
39+
#
40+
# If you need to increase this timeout for a migration, you can do so
41+
# by adding:
42+
#
43+
# op.execute("SET statement_timeout = 5000")
44+
# op.execute("SET lock_timeout = 4000")
45+
#
46+
# To whatever values are reasonable for this migration as part of your
47+
# migration.
48+
49+
50+
def upgrade():
51+
# ### commands auto generated by Alembic - please adjust! ###
52+
op.create_table(
53+
"buildkite_oidc_publishers",
54+
sa.Column("id", sa.UUID(), nullable=False),
55+
sa.Column("organization_slug", sa.String(), nullable=False),
56+
sa.Column("pipeline_slug", sa.String(), nullable=False),
57+
sa.Column("build_branch", sa.String(), nullable=False),
58+
sa.Column("build_tag", sa.String(), nullable=False),
59+
sa.Column("step_key", sa.String(), nullable=False),
60+
sa.ForeignKeyConstraint(
61+
["id"],
62+
["oidc_publishers.id"],
63+
),
64+
sa.PrimaryKeyConstraint("id"),
65+
sa.UniqueConstraint(
66+
"organization_slug", "pipeline_slug", name="_buildkite_oidc_publisher_uc"
67+
),
68+
)
69+
op.create_table(
70+
"pending_buildkite_oidc_publishers",
71+
sa.Column("id", sa.UUID(), nullable=False),
72+
sa.Column("organization_slug", sa.String(), nullable=False),
73+
sa.Column("pipeline_slug", sa.String(), nullable=False),
74+
sa.Column("build_branch", sa.String(), nullable=False),
75+
sa.Column("build_tag", sa.String(), nullable=False),
76+
sa.Column("step_key", sa.String(), nullable=False),
77+
sa.ForeignKeyConstraint(
78+
["id"],
79+
["pending_oidc_publishers.id"],
80+
),
81+
sa.PrimaryKeyConstraint("id"),
82+
sa.UniqueConstraint(
83+
"organization_slug",
84+
"pipeline_slug",
85+
name="_pending_buildkite_oidc_publisher_uc",
86+
),
87+
)
88+
# ### end Alembic commands ###
89+
90+
91+
def downgrade():
92+
# ### commands auto generated by Alembic - please adjust! ###
93+
op.drop_table("pending_buildkite_oidc_publishers")
94+
op.drop_table("buildkite_oidc_publishers")
95+
# ### end Alembic commands ###

warehouse/oidc/forms/buildkite.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License");
2+
# you may not use this file except in compliance with the License.
3+
# You may obtain a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS,
9+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# See the License for the specific language governing permissions and
11+
# limitations under the License.
12+
13+
import re
14+
15+
import requests
16+
import sentry_sdk
17+
import wtforms
18+
19+
from warehouse import forms
20+
from warehouse.i18n import localize as _
21+
from warehouse.utils.project import PROJECT_NAME_RE
22+
23+
_VALID_BUILDKITE_SLUG = re.compile(r"^[a-zA-Z0-9]+[a-zA-Z0-9\-]*$")
24+
25+
26+
class BuildkitePublisherBase(forms.Form):
27+
__params__ = [
28+
"organization_slug",
29+
"pipeline_slug",
30+
"build_branch",
31+
"build_tag",
32+
"step_key",
33+
]
34+
35+
organization_slug = wtforms.StringField(
36+
validators=[
37+
wtforms.validators.InputRequired(
38+
message=_("Specify Buildkite organization slug"),
39+
),
40+
wtforms.validators.Regexp(
41+
_VALID_BUILDKITE_SLUG, message=_("Invalid pipeline slug")
42+
),
43+
]
44+
)
45+
46+
repository = wtforms.StringField(
47+
validators=[
48+
wtforms.validators.InputRequired(
49+
message=_("Specify Buildkite pipeline slug"),
50+
),
51+
wtforms.validators.Regexp(
52+
_VALID_BUILDKITE_SLUG, message=_("Invalid pipeline slug")
53+
),
54+
]
55+
)
56+
57+
build_branch = wtforms.StringField(validators=[wtforms.validators.Optional()])
58+
build_tag = wtforms.StringField(validators=[wtforms.validators.Optional()])
59+
step_key = wtforms.StringField(validators=[wtforms.validators.Optional()])
60+
61+
62+
class PendingBuildkitePublisherForm(BuildkitePublisherBase):
63+
__params__ = BuildkitePublisherBase.__params__ + ["project_name"]
64+
65+
project_name = wtforms.StringField(
66+
validators=[
67+
wtforms.validators.InputRequired(message=_("Specify project name")),
68+
wtforms.validators.Regexp(
69+
PROJECT_NAME_RE, message=_("Invalid project name")
70+
),
71+
]
72+
)
73+
74+
def __init__(self, *args, project_factory, **kwargs):
75+
super().__init__(*args, **kwargs)
76+
self._project_factory = project_factory
77+
78+
def validate_project_name(self, field):
79+
project_name = field.data
80+
81+
if project_name in self._project_factory:
82+
raise wtforms.validators.ValidationError(
83+
_("This project name is already in use")
84+
)
85+
86+
87+
class BuildkitePublisherForm(BuildkitePublisherBase):
88+
pass

warehouse/oidc/models/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111
# limitations under the License.
1212

1313
from warehouse.oidc.models._core import OIDCPublisher, PendingOIDCPublisher
14+
from warehouse.oidc.models.buildkite import BuildkitePublisher, PendingBuildkitePublisher
1415
from warehouse.oidc.models.github import GitHubPublisher, PendingGitHubPublisher
1516
from warehouse.oidc.models.google import GooglePublisher, PendingGooglePublisher
1617

1718
__all__ = [
1819
"OIDCPublisher",
1920
"PendingOIDCPublisher",
21+
"PendingBuildkitePublisher",
2022
"PendingGitHubPublisher",
2123
"PendingGooglePublisher",
24+
"BuildkitePublisher",
2225
"GitHubPublisher",
2326
"GooglePublisher",
2427
]

0 commit comments

Comments
 (0)