From 9aa3d2e5ebbbb44ebed08db007e84e55d7dbfa4d Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 30 Apr 2024 18:50:53 +0000 Subject: [PATCH 1/8] adding verified column for releaseurl and filling it during upload Signed-off-by: Javan lacerda --- warehouse/forklift/legacy.py | 34 +++++++---- ...a2_create_verified_field_for_releaseurl.py | 59 +++++++++++++++++++ warehouse/packaging/models.py | 3 +- 3 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py index e925db39489c..ca2dfad645f9 100644 --- a/warehouse/forklift/legacy.py +++ b/warehouse/forklift/legacy.py @@ -676,6 +676,24 @@ def file_upload(request): ), ) from None + publisher_url = ( + request.oidc_publisher.publisher_url(request.oidc_claims) + if request.oidc_publisher + else None + ) + project_urls = {} + if meta.project_urls: + for name, url in meta.project_urls.items(): + url = url.rstrip("/") + "/" + + verified = url.lower() == publisher_url[:len(url)].lower() if publisher_url else False + + # Would it be a problem sava the modified url? + project_urls[name] = { + "url": url, + "verified": verified + } + try: canonical_version = packaging.utils.canonicalize_version(meta.version) release = ( @@ -730,7 +748,7 @@ def file_upload(request): html=rendered or "", rendered_by=readme.renderer_version(), ), - project_urls=meta.project_urls or {}, + project_urls=project_urls, # TODO: Fix this, we currently treat platform as if it is a single # use field, but in reality it is a multi-use field, which the # packaging.metadata library handles correctly. @@ -789,11 +807,7 @@ def file_upload(request): request.user.username if request.user else "OpenID created token" ), "canonical_version": release.canonical_version, - "publisher_url": ( - request.oidc_publisher.publisher_url(request.oidc_claims) - if request.oidc_publisher - else None - ), + "publisher_url": publisher_url, "uploaded_via_trusted_publisher": bool(request.oidc_publisher), }, ) @@ -1109,16 +1123,14 @@ def file_upload(request): request.user.username if request.user else "OpenID created token" ), "canonical_version": release.canonical_version, - "publisher_url": ( - request.oidc_publisher.publisher_url(request.oidc_claims) - if request.oidc_publisher - else None - ), + "publisher_url": publisher_url, "project_id": str(project.id), "uploaded_via_trusted_publisher": bool(request.oidc_publisher), }, ) + + # TODO: This should be handled by some sort of database trigger or a # SQLAlchemy hook or the like instead of doing it inline in this # view. diff --git a/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py b/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py new file mode 100644 index 000000000000..8f3549fecb24 --- /dev/null +++ b/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py @@ -0,0 +1,59 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +create verified field for ReleaseUrl + +Revision ID: 26455e3712a2 +Revises: 78ecf599841c +Create Date: 2024-04-30 18:40:17.149050 +""" + +import sqlalchemy as sa + +from alembic import op + +revision = "26455e3712a2" +down_revision = "78ecf599841c" + +# Note: It is VERY important to ensure that a migration does not lock for a +# long period of time and to ensure that each individual migration does +# not break compatibility with the *previous* version of the code base. +# This is because the migrations will be ran automatically as part of the +# deployment process, but while the previous version of the code is still +# up and running. Thus backwards incompatible changes must be broken up +# over multiple migrations inside of multiple pull requests in order to +# phase them in over multiple deploys. +# +# By default, migrations cannot wait more than 4s on acquiring a lock +# and each individual statement cannot take more than 5s. This helps +# prevent situations where a slow migration takes the entire site down. +# +# If you need to increase this timeout for a migration, you can do so +# by adding: +# +# op.execute("SET statement_timeout = 5000") +# op.execute("SET lock_timeout = 4000") +# +# To whatever values are reasonable for this migration as part of your +# migration. + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py index dd4ddca38c68..b10e9e18f34d 100644 --- a/warehouse/packaging/models.py +++ b/warehouse/packaging/models.py @@ -465,6 +465,7 @@ class ReleaseURL(db.Model): name: Mapped[str] = mapped_column(String(32)) url: Mapped[str] + verified: Mapped[bool] = False DynamicFieldsEnum = ENUM( @@ -567,7 +568,7 @@ def __table_args__(cls): # noqa project_urls = association_proxy( "_project_urls", "url", - creator=lambda k, v: ReleaseURL(name=k, url=v), + creator=lambda k, v: ReleaseURL(name=k, url=v["url"], verified=v["verified"]), ) files: Mapped[list[File]] = orm.relationship( From bad192e0e8b834934fba2ffa86a8339e5b1f5b31 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 30 Apr 2024 19:06:15 +0000 Subject: [PATCH 2/8] fill migration for verified column creation Signed-off-by: Javan lacerda --- ...5e3712a2_create_verified_field_for_releaseurl.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py b/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py index 8f3549fecb24..9ffeda8a7af8 100644 --- a/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py +++ b/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py @@ -48,12 +48,13 @@ def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - pass - # ### end Alembic commands ### + op.add_column( + "release_urls", + sa.Column( + "verified", sa.Boolean(), server_default=sa.text("false"), nullable=False + ), + ) def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - pass - # ### end Alembic commands ### + op.drop_column("release_urls", "verified") From 74997ae4ec4161c64d47cea72f19802f84228d3a Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Tue, 30 Apr 2024 22:44:51 +0000 Subject: [PATCH 3/8] conform lint Signed-off-by: Javan lacerda --- warehouse/forklift/legacy.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py index ca2dfad645f9..52bff50b8c0b 100644 --- a/warehouse/forklift/legacy.py +++ b/warehouse/forklift/legacy.py @@ -677,22 +677,23 @@ def file_upload(request): ) from None publisher_url = ( - request.oidc_publisher.publisher_url(request.oidc_claims) - if request.oidc_publisher - else None - ) + request.oidc_publisher.publisher_url(request.oidc_claims) + if request.oidc_publisher + else None + ) project_urls = {} if meta.project_urls: - for name, url in meta.project_urls.items(): + for name, url in meta.project_urls.items(): url = url.rstrip("/") + "/" - verified = url.lower() == publisher_url[:len(url)].lower() if publisher_url else False + verified = ( + url.lower() == publisher_url[: len(url)].lower() + if publisher_url + else False + ) # Would it be a problem sava the modified url? - project_urls[name] = { - "url": url, - "verified": verified - } + project_urls[name] = {"url": url, "verified": verified} try: canonical_version = packaging.utils.canonicalize_version(meta.version) @@ -1129,8 +1130,6 @@ def file_upload(request): }, ) - - # TODO: This should be handled by some sort of database trigger or a # SQLAlchemy hook or the like instead of doing it inline in this # view. From 2f13cc617df93d02da5804d724ca58387c1d0351 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Sat, 4 May 2024 21:27:24 +0000 Subject: [PATCH 4/8] conform mypy requirements Signed-off-by: Javan lacerda --- warehouse/packaging/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py index b10e9e18f34d..21717ab81def 100644 --- a/warehouse/packaging/models.py +++ b/warehouse/packaging/models.py @@ -465,7 +465,7 @@ class ReleaseURL(db.Model): name: Mapped[str] = mapped_column(String(32)) url: Mapped[str] - verified: Mapped[bool] = False + verified: Mapped[bool] = mapped_column(default=False) DynamicFieldsEnum = ENUM( From 303ed4597212d3dee2cd049248f3b72b9b61acc3 Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 6 May 2024 14:37:55 +0000 Subject: [PATCH 5/8] createing tests for release url verified Signed-off-by: Javan lacerda --- tests/unit/forklift/test_legacy.py | 70 ++++++++++++++++++++++++++++ warehouse/forklift/legacy.py | 10 ++-- warehouse/oidc/models/_core.py | 5 ++ warehouse/oidc/models/activestate.py | 6 ++- warehouse/oidc/models/github.py | 6 ++- warehouse/oidc/models/gitlab.py | 6 ++- warehouse/oidc/models/google.py | 4 ++ 7 files changed, 97 insertions(+), 10 deletions(-) diff --git a/tests/unit/forklift/test_legacy.py b/tests/unit/forklift/test_legacy.py index 0b6a61d7d629..4a362db36a1d 100644 --- a/tests/unit/forklift/test_legacy.py +++ b/tests/unit/forklift/test_legacy.py @@ -48,6 +48,7 @@ Project, ProjectMacaroonWarningAssociation, Release, + ReleaseURL, Role, ) from warehouse.packaging.tasks import sync_file_to_cache, update_bigquery_release_files @@ -3293,6 +3294,75 @@ def test_upload_succeeds_creates_release( ), ] + @pytest.mark.parametrize( + "url, expected", + [ + ("https://xpto.com", False), # Totally different + ("https://github.com/foo", False), # Missing parts + ("https://github.com/foo/bar/", True), # Exactly the same + ("https://github.com/foo/bar/readme.md", True), # Additonal parts + ("https://github.com/foo/bar", True), # Missing trailing slash + ], + ) + def test_release_url_verified( + self, monkeypatch, pyramid_config, db_request, metrics, url, expected + ): + project = ProjectFactory.create() + publisher = GitHubPublisherFactory.create(projects=[project]) + publisher.repository_owner = "foo" + publisher.repository_name = "bar" + claims = {"sha": "somesha"} + identity = PublisherTokenContext(publisher, SignedClaims(claims)) + db_request.oidc_publisher = identity.publisher + db_request.oidc_claims = identity.claims + + db_request.db.add(Classifier(classifier="Environment :: Other Environment")) + db_request.db.add(Classifier(classifier="Programming Language :: Python")) + + filename = "{}-{}.tar.gz".format(project.name, "1.0") + + pyramid_config.testing_securitypolicy(identity=identity) + db_request.user_agent = "warehouse-tests/6.6.6" + db_request.POST = MultiDict( + { + "metadata_version": "1.2", + "name": project.name, + "version": "1.0", + "summary": "This is my summary!", + "filetype": "sdist", + "md5_digest": _TAR_GZ_PKG_MD5, + "content": pretend.stub( + filename=filename, + file=io.BytesIO(_TAR_GZ_PKG_TESTDATA), + type="application/tar", + ), + } + ) + db_request.POST.extend( + [ + ("classifiers", "Environment :: Other Environment"), + ("classifiers", "Programming Language :: Python"), + ("requires_dist", "foo"), + ("requires_dist", "bar (>1.0)"), + ("project_urls", f"Test, {url}"), + ("requires_external", "Cheese (>1.0)"), + ("provides", "testing"), + ] + ) + + storage_service = pretend.stub(store=lambda path, filepath, meta: None) + db_request.find_service = lambda svc, name=None, context=None: { + IFileStorage: storage_service, + IMetricsService: metrics, + }.get(svc) + + legacy.file_upload(db_request) + release_url = ( + db_request.db.query(ReleaseURL).filter(Release.project == project).one() + ) + assert release_url is not None + assert release_url.verified == expected + @pytest.mark.parametrize( "version, expected_version", [ diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py index 52bff50b8c0b..acbec544063f 100644 --- a/warehouse/forklift/legacy.py +++ b/warehouse/forklift/legacy.py @@ -677,22 +677,18 @@ def file_upload(request): ) from None publisher_url = ( - request.oidc_publisher.publisher_url(request.oidc_claims) - if request.oidc_publisher - else None + request.oidc_publisher.publisher_base_url if request.oidc_publisher else None ) project_urls = {} if meta.project_urls: for name, url in meta.project_urls.items(): - url = url.rstrip("/") + "/" - + striped_url = url.rstrip("/") + "/" verified = ( - url.lower() == publisher_url[: len(url)].lower() + striped_url[: len(publisher_url)].lower() == publisher_url.lower() if publisher_url else False ) - # Would it be a problem sava the modified url? project_urls[name] = {"url": url, "verified": verified} try: diff --git a/warehouse/oidc/models/_core.py b/warehouse/oidc/models/_core.py index 336dddf130b9..1965e9e67269 100644 --- a/warehouse/oidc/models/_core.py +++ b/warehouse/oidc/models/_core.py @@ -235,6 +235,11 @@ def publisher_name(self) -> str: # pragma: no cover # Only concrete subclasses are constructed. raise NotImplementedError + @property + def publisher_base_url(self) -> str | None: # pragma: no cover + # Only concrete subclasses are constructed. + raise NotImplementedError + def publisher_url( self, claims: SignedClaims | None = None ) -> str | None: # pragma: no cover diff --git a/warehouse/oidc/models/activestate.py b/warehouse/oidc/models/activestate.py index b5939f3b4a82..f0be6460a339 100644 --- a/warehouse/oidc/models/activestate.py +++ b/warehouse/oidc/models/activestate.py @@ -118,11 +118,15 @@ def publisher_name(self) -> str: def project(self) -> str: return self.activestate_project_name - def publisher_url(self, claims: SignedClaims | None = None) -> str: + @property + def publisher_base_url(self) -> str: return urllib.parse.urljoin( _ACTIVESTATE_URL, f"{self.organization}/{self.activestate_project_name}" ) + def publisher_url(self, claims: SignedClaims | None = None) -> str: + return self.publisher_base_url + def stored_claims(self, claims=None): return {} diff --git a/warehouse/oidc/models/github.py b/warehouse/oidc/models/github.py index 840039355a8e..09efb3347217 100644 --- a/warehouse/oidc/models/github.py +++ b/warehouse/oidc/models/github.py @@ -227,8 +227,12 @@ def job_workflow_ref(self): def sub(self): return f"repo:{self.repository}" + @property + def publisher_base_url(self): + return f"https://github.com/{self.repository}" + def publisher_url(self, claims=None): - base = f"https://github.com/{self.repository}" + base = self.publisher_base_url sha = claims.get("sha") if claims else None if sha: diff --git a/warehouse/oidc/models/gitlab.py b/warehouse/oidc/models/gitlab.py index 33d2fc947260..cd78660397b8 100644 --- a/warehouse/oidc/models/gitlab.py +++ b/warehouse/oidc/models/gitlab.py @@ -221,8 +221,12 @@ def ci_config_ref_uri(self): def publisher_name(self): return "GitLab" + @property + def publisher_base_url(self): + return f"https://gitlab.com/{self.project_path}" + def publisher_url(self, claims=None): - base = f"https://gitlab.com/{self.project_path}" + base = self.publisher_base_url return f"{base}/commit/{claims['sha']}" if claims else base def stored_claims(self, claims=None): diff --git a/warehouse/oidc/models/google.py b/warehouse/oidc/models/google.py index acd660f7d355..a60e685798e7 100644 --- a/warehouse/oidc/models/google.py +++ b/warehouse/oidc/models/google.py @@ -81,6 +81,10 @@ def __lookup_no_sub__(klass, signed_claims: SignedClaims) -> Query | None: def publisher_name(self): return "Google" + @property + def publisher_base_url(self): + return None + def publisher_url(self, claims=None): return None From 69243da6e4b09d3a2ac975441fe08dbbf557777e Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 6 May 2024 14:54:14 +0000 Subject: [PATCH 6/8] adding tests for publisher_base_url Signed-off-by: Javan lacerda --- tests/unit/oidc/models/test_activestate.py | 12 ++++++++++++ tests/unit/oidc/models/test_github.py | 1 + tests/unit/oidc/models/test_gitlab.py | 1 + tests/unit/oidc/models/test_google.py | 5 +++++ 4 files changed, 19 insertions(+) diff --git a/tests/unit/oidc/models/test_activestate.py b/tests/unit/oidc/models/test_activestate.py index f03e23fdf20f..b5541db869e3 100644 --- a/tests/unit/oidc/models/test_activestate.py +++ b/tests/unit/oidc/models/test_activestate.py @@ -84,6 +84,18 @@ def test_publisher_name(self): assert publisher.publisher_name == "ActiveState" + def test_publisher_base_url(self): + org_name = "fakeorg" + project_name = "fakeproject" + publisher = ActiveStatePublisher( + organization=org_name, activestate_project_name=project_name + ) + + assert ( + publisher.publisher_base_url + == f"https://platform.activestate.com/{org_name}/{project_name}" + ) + def test_publisher_url(self): org_name = "fakeorg" project_name = "fakeproject" diff --git a/tests/unit/oidc/models/test_github.py b/tests/unit/oidc/models/test_github.py index a0bf7826dfec..2130309c4253 100644 --- a/tests/unit/oidc/models/test_github.py +++ b/tests/unit/oidc/models/test_github.py @@ -96,6 +96,7 @@ def test_github_publisher_computed_properties(self): assert getattr(publisher, claim_name) is not None assert str(publisher) == "fakeworkflow.yml" + assert publisher.publisher_base_url == "https://github.com/fakeowner/fakerepo" assert publisher.publisher_url() == "https://github.com/fakeowner/fakerepo" assert ( publisher.publisher_url({"sha": "somesha"}) diff --git a/tests/unit/oidc/models/test_gitlab.py b/tests/unit/oidc/models/test_gitlab.py index fa0ac48b3fc8..4e63392f472d 100644 --- a/tests/unit/oidc/models/test_gitlab.py +++ b/tests/unit/oidc/models/test_gitlab.py @@ -94,6 +94,7 @@ def test_gitlab_publisher_computed_properties(self): assert getattr(publisher, claim_name) is not None assert str(publisher) == "subfolder/fakeworkflow.yml" + assert publisher.publisher_base_url == "https://gitlab.com/fakeowner/fakerepo" assert publisher.publisher_url() == "https://gitlab.com/fakeowner/fakerepo" assert ( publisher.publisher_url({"sha": "somesha"}) diff --git a/tests/unit/oidc/models/test_google.py b/tests/unit/oidc/models/test_google.py index d0ce98e689d3..88935aca255a 100644 --- a/tests/unit/oidc/models/test_google.py +++ b/tests/unit/oidc/models/test_google.py @@ -33,6 +33,11 @@ def test_publisher_name(self): assert publisher.publisher_name == "Google" + def test_publisher_base_url(self): + publisher = google.GooglePublisher(email="fake@example.com") + + assert publisher.publisher_base_url is None + def test_publisher_url(self): publisher = google.GooglePublisher(email="fake@example.com") From e165eb64c534d11612dbe640b22454f515fd47ec Mon Sep 17 00:00:00 2001 From: Javan lacerda Date: Mon, 6 May 2024 20:46:17 +0000 Subject: [PATCH 7/8] fix legacy publisher url usage Signed-off-by: Javan lacerda --- warehouse/forklift/legacy.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py index acbec544063f..d77ebc5b0816 100644 --- a/warehouse/forklift/legacy.py +++ b/warehouse/forklift/legacy.py @@ -676,7 +676,7 @@ def file_upload(request): ), ) from None - publisher_url = ( + publisher_base_url = ( request.oidc_publisher.publisher_base_url if request.oidc_publisher else None ) project_urls = {} @@ -684,8 +684,9 @@ def file_upload(request): for name, url in meta.project_urls.items(): striped_url = url.rstrip("/") + "/" verified = ( - striped_url[: len(publisher_url)].lower() == publisher_url.lower() - if publisher_url + striped_url[: len(publisher_base_url)].lower() + == publisher_base_url.lower() + if publisher_base_url else False ) @@ -804,7 +805,11 @@ def file_upload(request): request.user.username if request.user else "OpenID created token" ), "canonical_version": release.canonical_version, - "publisher_url": publisher_url, + "publisher_url": ( + request.oidc_publisher.publisher_url(request.oidc_claims) + if request.oidc_publisher + else None + ), "uploaded_via_trusted_publisher": bool(request.oidc_publisher), }, ) @@ -1120,7 +1125,11 @@ def file_upload(request): request.user.username if request.user else "OpenID created token" ), "canonical_version": release.canonical_version, - "publisher_url": publisher_url, + "publisher_url": ( + request.oidc_publisher.publisher_url(request.oidc_claims) + if request.oidc_publisher + else None + ), "project_id": str(project.id), "uploaded_via_trusted_publisher": bool(request.oidc_publisher), }, From d6d6fa62f47a33285d2510e9deaf2b18f6b26230 Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Mon, 1 Jul 2024 16:50:59 -0400 Subject: [PATCH 8/8] Apply suggestions from code review --- warehouse/forklift/legacy.py | 26 +++++++++---------- ...a2_create_verified_field_for_releaseurl.py | 26 ++----------------- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py index d77ebc5b0816..b551af3a5675 100644 --- a/warehouse/forklift/legacy.py +++ b/warehouse/forklift/legacy.py @@ -676,22 +676,22 @@ def file_upload(request): ), ) from None + # Verify any verifiable URLs publisher_base_url = ( request.oidc_publisher.publisher_base_url if request.oidc_publisher else None ) - project_urls = {} - if meta.project_urls: - for name, url in meta.project_urls.items(): - striped_url = url.rstrip("/") + "/" - verified = ( - striped_url[: len(publisher_base_url)].lower() - == publisher_base_url.lower() - if publisher_base_url - else False - ) - - project_urls[name] = {"url": url, "verified": verified} - + project_urls = ( + {} + if not meta.project_urls + else { + name: { + "url": url, + "verified": publisher_base_url + and url.lower().startswith(publisher_base_url.lower()), + } + for name, url in meta.project_urls.items() + } + ) try: canonical_version = packaging.utils.canonicalize_version(meta.version) release = ( diff --git a/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py b/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py index 9ffeda8a7af8..8b8aeab4f8b0 100644 --- a/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py +++ b/warehouse/migrations/versions/26455e3712a2_create_verified_field_for_releaseurl.py @@ -13,7 +13,7 @@ create verified field for ReleaseUrl Revision ID: 26455e3712a2 -Revises: 78ecf599841c +Revises: b14df478c48f Create Date: 2024-04-30 18:40:17.149050 """ @@ -22,29 +22,7 @@ from alembic import op revision = "26455e3712a2" -down_revision = "78ecf599841c" - -# Note: It is VERY important to ensure that a migration does not lock for a -# long period of time and to ensure that each individual migration does -# not break compatibility with the *previous* version of the code base. -# This is because the migrations will be ran automatically as part of the -# deployment process, but while the previous version of the code is still -# up and running. Thus backwards incompatible changes must be broken up -# over multiple migrations inside of multiple pull requests in order to -# phase them in over multiple deploys. -# -# By default, migrations cannot wait more than 4s on acquiring a lock -# and each individual statement cannot take more than 5s. This helps -# prevent situations where a slow migration takes the entire site down. -# -# If you need to increase this timeout for a migration, you can do so -# by adding: -# -# op.execute("SET statement_timeout = 5000") -# op.execute("SET lock_timeout = 4000") -# -# To whatever values are reasonable for this migration as part of your -# migration. +down_revision = "b14df478c48f" def upgrade():