[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:bug-task-channel into launchpad:master

2022-12-15 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:bug-task-channel into launchpad:master.

Commit message:
WIP: Add `channel` field to `BugTask` and `SourcePackage`

This should also make a `SourcePackage` with a channel a valid target for a 
`BugTask`, and some work has been done in that direction, but it may not be 
100% complete.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/434693

Currently, it is confirmed to pass all tests in `lp.{bugs,soyuz,registry}` 
(other packages hasn't been checked)
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:bug-task-channel into launchpad:master.
diff --git a/lib/lp/bugs/configure.zcml b/lib/lp/bugs/configure.zcml
index 6eaa58c..12bfdd7 100644
--- a/lib/lp/bugs/configure.zcml
+++ b/lib/lp/bugs/configure.zcml
@@ -211,6 +211,8 @@
 distribution
 distroseries
 milestone
+_channel
+channel
 _status
 status
 status_explanation
diff --git a/lib/lp/bugs/interfaces/bugsummary.py b/lib/lp/bugs/interfaces/bugsummary.py
index 7cb55ef..be83775 100644
--- a/lib/lp/bugs/interfaces/bugsummary.py
+++ b/lib/lp/bugs/interfaces/bugsummary.py
@@ -9,7 +9,7 @@ __all__ = [
 ]
 
 from zope.interface import Interface
-from zope.schema import Bool, Choice, Int, Object, Text
+from zope.schema import Bool, Choice, Int, Object, Text, TextLine
 
 from lp import _
 from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatusSearch
@@ -51,6 +51,8 @@ class IBugSummary(Interface):
 ociproject_id = Int(readonly=True)
 ociproject = Object(IOCIProject, readonly=True)
 
+channel = TextLine(readonly=True)
+
 milestone_id = Int(readonly=True)
 milestone = Object(IMilestone, readonly=True)
 
diff --git a/lib/lp/bugs/interfaces/bugtask.py b/lib/lp/bugs/interfaces/bugtask.py
index a8c4e45..d2586f7 100644
--- a/lib/lp/bugs/interfaces/bugtask.py
+++ b/lib/lp/bugs/interfaces/bugtask.py
@@ -475,6 +475,7 @@ class IBugTask(IHasBug, IBugTaskDelete):
 title=_("Series"), required=False, vocabulary="DistroSeries"
 )
 distroseries_id = Attribute("The distroseries ID")
+channel = TextLine(title=_("Channel"), required=False)
 milestone = exported(
 ReferenceChoice(
 title=_("Milestone"),
diff --git a/lib/lp/bugs/model/bugsummary.py b/lib/lp/bugs/model/bugsummary.py
index 9084e0e..2caabf6 100644
--- a/lib/lp/bugs/model/bugsummary.py
+++ b/lib/lp/bugs/model/bugsummary.py
@@ -9,6 +9,8 @@ __all__ = [
 "get_bugsummary_filter_for_user",
 ]
 
+from typing import Optional
+
 from storm.base import Storm
 from storm.expr import SQL, And, Or, Select
 from storm.properties import Bool, Int, Unicode
@@ -32,9 +34,10 @@ from lp.registry.model.product import Product
 from lp.registry.model.productseries import ProductSeries
 from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.registry.model.teammembership import TeamParticipation
+from lp.services.channels import channel_list_to_string
 from lp.services.database.enumcol import DBEnum
 from lp.services.database.interfaces import IStore
-from lp.services.database.stormexpr import WithMaterialized
+from lp.services.database.stormexpr import ImmutablePgJSON, WithMaterialized
 
 
 @implementer(IBugSummary)
@@ -64,6 +67,8 @@ class BugSummary(Storm):
 ociproject_id = Int(name="ociproject")
 ociproject = Reference(ociproject_id, "OCIProject.id")
 
+_channel = ImmutablePgJSON(name="channel")
+
 milestone_id = Int(name="milestone")
 milestone = Reference(milestone_id, Milestone.id)
 
@@ -80,6 +85,12 @@ class BugSummary(Storm):
 
 has_patch = Bool()
 
+@property
+def channel(self) -> Optional[str]:
+if self._channel is None:
+return None
+return channel_list_to_string(*self._channel)
+
 
 @implementer(IBugSummaryDimension)
 class CombineBugSummaryConstraint:
diff --git a/lib/lp/bugs/model/bugtask.py b/lib/lp/bugs/model/bugtask.py
index c006618..8955720 100644
--- a/lib/lp/bugs/model/bugtask.py
+++ b/lib/lp/bugs/model/bugtask.py
@@ -21,6 +21,7 @@ import re
 from collections import defaultdict
 from itertools import chain, repeat
 from operator import attrgetter, itemgetter
+from typing import Optional
 
 import pytz
 from lazr.lifecycle.event import ObjectDeletedEvent
@@ -98,6 +99,7 @@ from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
 from lp.registry.model.pillar import pillar_sort_key
 from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.services import features
+from lp.services.channels import channel_list_to

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-bug-task-channel-indexes into launchpad:db-devel

2022-12-15 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-bug-task-channel-indexes into launchpad:db-devel 
with ~andrey-fedoseev/launchpad:db-bug-task-channel as a prerequisite.

Commit message:
Include the new `channel` to the indexes

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/434688
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-bug-task-channel-indexes into launchpad:db-devel.
diff --git a/database/schema/patch-2211-15-1.sql b/database/schema/patch-2211-15-1.sql
new file mode 100644
index 000..cddc62d
--- /dev/null
+++ b/database/schema/patch-2211-15-1.sql
@@ -0,0 +1,61 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+-- Replacing previously renamed indexes.
+CREATE UNIQUE INDEX bugtask_distinct_sourcepackage_assignment
+ON bugtask (
+bug,
+COALESCE(sourcepackagename, '-1'::integer),
+COALESCE(distroseries, '-1'::integer),
+COALESCE(distribution, '-1'::integer),
+COALESCE(channel, '{}'::jsonb)
+)
+WHERE (
+product IS NULL
+AND productseries IS NULL
+AND ociproject IS NULL
+AND ociprojectseries IS NULL
+);
+DROP INDEX old__bugtask_distinct_sourcepackage_assignment;
+
+
+CREATE UNIQUE INDEX bugsummary__unique
+ON bugsummary (
+COALESCE(product, '-1'::integer),
+COALESCE(productseries, '-1'::integer),
+COALESCE(distribution, '-1'::integer),
+COALESCE(distroseries, '-1'::integer),
+COALESCE(sourcepackagename, '-1'::integer),
+COALESCE(ociproject, '-1'::integer),
+COALESCE(ociprojectseries, '-1'::integer),
+COALESCE(channel, '{}'::jsonb),
+status,
+importance,
+has_patch,
+COALESCE(tag, ''::text),
+COALESCE(milestone, '-1'::integer),
+COALESCE(viewed_by, '-1'::integer),
+COALESCE(access_policy, '-1'::integer)
+);
+DROP INDEX old__bugsummary__unique;
+
+CREATE INDEX bugsummaryjournal__full__idx
+ON bugsummaryjournal (
+status,
+product,
+productseries,
+distribution,
+distroseries,
+sourcepackagename,
+ociproject,
+ociprojectseries,
+channel,
+viewed_by,
+milestone,
+tag
+);
+DROP INDEX old__bugsummaryjournal__full__idx;
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 15, 1);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-bug-task-channel into launchpad:db-devel

2022-12-15 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-bug-task-channel into launchpad:db-devel.

Commit message:
Add `channel` field to `BugTask` and its derived tables/views

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/434686
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-bug-task-channel into launchpad:db-devel.
diff --git a/database/schema/patch-2211-14-0.sql b/database/schema/patch-2211-14-0.sql
new file mode 100644
index 000..719d4dd
--- /dev/null
+++ b/database/schema/patch-2211-14-0.sql
@@ -0,0 +1,542 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages = ERROR;
+
+ALTER TABLE BugTask
+ADD COLUMN channel jsonb;
+
+ALTER INDEX bugtask_distinct_sourcepackage_assignment
+RENAME TO old__bugtask_distinct_sourcepackage_assignment;
+
+ALTER TABLE BugTaskFlat
+ADD COLUMN channel jsonb;
+
+ALTER TABLE BugSummary
+ADD COLUMN channel jsonb,
+DROP CONSTRAINT bugtask_assignment_checks,
+ADD CONSTRAINT bugtask_assignment_checks CHECK (
+CASE
+WHEN product IS NOT NULL THEN
+productseries IS NULL
+AND distribution IS NULL
+AND distroseries IS NULL
+AND sourcepackagename IS NULL
+WHEN productseries IS NOT NULL THEN
+distribution IS NULL
+AND distroseries IS NULL
+AND sourcepackagename IS NULL
+AND ociproject IS NULL
+AND ociprojectseries IS NULL
+WHEN distribution IS NOT NULL THEN
+distroseries IS NULL
+WHEN distroseries IS NOT NULL THEN
+ociproject IS NULL
+AND ociprojectseries IS NULL
+WHEN ociproject IS NOT NULL THEN
+ociprojectseries IS NULL
+AND (distribution IS NOT NULL OR product IS NOT NULL)
+AND sourcepackagename IS NULL
+WHEN ociprojectseries IS NOT NULL THEN
+ociproject IS NULL
+AND (distribution IS NOT NULL OR product IS NOT NULL)
+AND sourcepackagename IS NULL
+WHEN channel IS NOT NULL THEN
+distroseries IS NOT NULL
+AND sourcepackagename IS NOT NULL
+ELSE false
+END) NOT VALID;
+
+ALTER INDEX bugsummary__unique
+RENAME TO old__bugsummary__unique;
+
+
+ALTER TABLE BugSummaryJournal ADD COLUMN channel jsonb;
+
+ALTER INDEX bugsummaryjournal__full__idx
+RENAME TO old__bugsummaryjournal__full__idx;
+
+
+-- Functions
+
+CREATE OR REPLACE FUNCTION bugtask_flatten(task_id integer, check_only boolean)
+RETURNS boolean
+SECURITY DEFINER
+SET search_path = public
+LANGUAGE plpgsql
+AS $$
+DECLARE
+bug_row Bug%ROWTYPE;
+task_row BugTask%ROWTYPE;
+old_flat_row BugTaskFlat%ROWTYPE;
+new_flat_row BugTaskFlat%ROWTYPE;
+_product_active boolean;
+_access_policies integer[];
+_access_grants integer[];
+BEGIN
+-- This is the master function to update BugTaskFlat, but there are
+-- maintenance triggers and jobs on the involved tables that update
+-- it directly. Any changes here probably require a corresponding
+-- change in other trigger functions.
+
+SELECT * INTO task_row FROM BugTask WHERE id = task_id;
+SELECT * INTO old_flat_row FROM BugTaskFlat WHERE bugtask = task_id;
+
+-- If the task doesn't exist, ensure that there's no flat row.
+IF task_row.id IS NULL THEN
+IF old_flat_row.bugtask IS NOT NULL THEN
+IF NOT check_only THEN
+DELETE FROM BugTaskFlat WHERE bugtask = task_id;
+END IF;
+RETURN FALSE;
+ELSE
+RETURN TRUE;
+END IF;
+END IF;
+
+SELECT * INTO bug_row FROM bug WHERE id = task_row.bug;
+
+-- If it's a product(series) task, we must consult the active flag.
+IF task_row.product IS NOT NULL THEN
+SELECT product.active INTO _product_active
+FROM product WHERE product.id = task_row.product LIMIT 1;
+ELSIF task_row.productseries IS NOT NULL THEN
+SELECT product.active INTO _product_active
+FROM
+product
+JOIN productseries ON productseries.product = product.id
+WHERE productseries.id = task_row.productseries LIMIT 1;
+END IF;
+
+SELECT policies, grants
+INTO _access_policies, _access_grants
+FROM bug_build_access_cache(bug_row.id, bug_row.information_type)
+AS (policies integer[], grants integer[]);
+
+-- Compile the new flat row.
+SELECT task_row.id, bug_row.id, task_row.datecreated,
+   bug_row.duplicateof

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:registry-can-delete-branch into launchpad:master

2022-12-12 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:registry-can-delete-branch into launchpad:master 
with ~ilasc/launchpad:registry-can-delete-branch as a prerequisite.

Commit message:
Registry experts can delete bzr branch

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/434537
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:registry-can-delete-branch into launchpad:master.
diff --git a/lib/lp/code/browser/tests/test_branch.py b/lib/lp/code/browser/tests/test_branch.py
index 84c4ed1..c42cbe0 100644
--- a/lib/lp/code/browser/tests/test_branch.py
+++ b/lib/lp/code/browser/tests/test_branch.py
@@ -707,62 +707,56 @@ class TestBranchDeletionView(BrowserTestCase):
 
 layer = DatabaseFunctionalLayer
 
+def setUp(self):
+super().setUp()
+self.branch = self.factory.makeAnyBranch()
+self.branch_name = self.branch.displayname
+self.branch_unique_name = self.branch.unique_name
+self.branch_url = canonical_url(
+self.branch, view_name="+delete", rootsite="code"
+)
+
 def test_owner_can_delete(self):
-branch = self.factory.makeAnyBranch()
-branch_name = branch.displayname
-branch_unique_name = branch.unique_name
-branch_url = canonical_url(
-branch, view_name="+delete", rootsite="code"
+browser = self.getUserBrowser(self.branch_url, user=self.branch.owner)
+browser.open(self.branch_url)
+self.assertIn(
+"Delete branch {}".format(self.branch_name), browser.contents
 )
-browser = self.getUserBrowser(branch_url, user=branch.owner)
-browser.open(branch_url)
-self.assertIn("Delete branch %s" % branch_name, browser.contents)
 
 browser.getControl("Delete").click()
 self.assertIn(
-"Branch %s deleted." % branch_unique_name, browser.contents
+"Branch {} deleted.".format(self.branch_unique_name),
+browser.contents,
 )
 
 def test_registry_expert_can_delete(self):
-expert = self.factory.makePerson(
-member_of=[getUtility(IPersonSet).getByName("registry")]
-)
-branch = self.factory.makeAnyBranch()
-branch_name = branch.displayname
-branch_unique_name = branch.unique_name
-branch_url = canonical_url(
-branch, view_name="+delete", rootsite="code"
+expert = self.factory.makeRegistryExpert()
+browser = self.getUserBrowser(self.branch_url, user=expert)
+browser.open(self.branch_url)
+self.assertIn(
+"Delete branch {}".format(self.branch_name), browser.contents
 )
-browser = self.getUserBrowser(branch_url, user=expert)
-browser.open(branch_url)
-self.assertIn("Delete branch %s" % branch_name, browser.contents)
 browser.getControl("Delete").click()
 self.assertIn(
-"Branch %s deleted." % branch_unique_name, browser.contents
+"Branch {} deleted.".format(self.branch_unique_name),
+browser.contents,
 )
 
 def test_commercial_admin_can_delete(self):
 commercial_admin = self.factory.makeCommercialAdmin()
-branch = self.factory.makeAnyBranch()
-branch_name = branch.displayname
-branch_unique_name = branch.unique_name
-branch_url = canonical_url(
-branch, view_name="+delete", rootsite="code"
+browser = self.getUserBrowser(self.branch_url, user=commercial_admin)
+browser.open(self.branch_url)
+self.assertIn(
+"Delete branch {}".format(self.branch_name), browser.contents
 )
-browser = self.getUserBrowser(branch_url, user=commercial_admin)
-browser.open(branch_url)
-self.assertIn("Delete branch %s" % branch_name, browser.contents)
 browser.getControl("Delete").click()
 self.assertIn(
-"Branch %s deleted." % branch_unique_name, browser.contents
+"Branch {} deleted.".format(self.branch_unique_name),
+browser.contents,
 )
 
 def test_other_user_can_not_delete(self):
-branch = self.factory.makeAnyBranch()
-branch_url = canonical_url(
-branch, view_name="+delete", rootsite="code"
-)
-self.assertRaises(Unauthorized, self.getUserBrowser, branch_url)
+self.assertRaises(Unauthorized, self.getUserBrowser, self.branch_url)
 
 
 class TestBranchRescanView(BrowserTestCase):
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-store-auth-error into launchpad:master

2022-11-29 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:snap-store-auth-error into launchpad:master.

Commit message:
Display info message when user tries to authorize store upload for snap that 
isn't registered


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1997565 in Launchpad itself: "snap /+authorize for brand new snap 
package name results in OOPS"
  https://bugs.launchpad.net/launchpad/+bug/1997565

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/433778

Previously, that would cause an Internal Server Error

LP: #1997565

Example: 
https://people.canonical.com/~afedoseev/%231997565/Screenshot_20221129_154226.png
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-store-auth-error into launchpad:master.
diff --git a/lib/lp/snappy/browser/tests/test_snap.py b/lib/lp/snappy/browser/tests/test_snap.py
index 6bde0c8..4c2fbdd 100644
--- a/lib/lp/snappy/browser/tests/test_snap.py
+++ b/lib/lp/snappy/browser/tests/test_snap.py
@@ -1828,6 +1828,26 @@ class TestSnapAuthorizeView(BaseTestSnapView):
 browser.headers["Location"],
 )
 
+@responses.activate
+def test_begin_authorization__snap_not_registered(self):
+snap_url = canonical_url(self.snap)
+self.pushConfig("snappy", store_url="http://sca.example/;)
+responses.add("POST", "http://sca.example/dev/api/acl/;, status=404)
+browser = self.getUserBrowser(
+url=snap_url + "/+authorize", user=self.snap.owner
+)
+browser.getControl("Begin authorization").click()
+self.assertEqual(snap_url, browser.url)
+messages = find_tags_by_class(
+browser.contents, "informational message"
+)
+self.assertEqual(1, len(messages))
+self.assertStartsWith(
+extract_text(messages[0]),
+"The requested snap name '{}' is not registered in the "
+"snap store".format(removeSecurityProxy(self.snap).store_name),
+)
+
 def test_complete_authorization_missing_discharge_macaroon(self):
 # If the form does not include a discharge macaroon, the "complete"
 # action fails.
diff --git a/lib/lp/snappy/interfaces/snapstoreclient.py b/lib/lp/snappy/interfaces/snapstoreclient.py
index e45e8a9..81cc293 100644
--- a/lib/lp/snappy/interfaces/snapstoreclient.py
+++ b/lib/lp/snappy/interfaces/snapstoreclient.py
@@ -10,6 +10,7 @@ __all__ = [
 "ISnapStoreClient",
 "NeedsRefreshResponse",
 "ScanFailedResponse",
+"SnapNotFoundResponse",
 "SnapStoreError",
 "UnauthorizedUploadResponse",
 "UploadFailedResponse",
@@ -38,6 +39,10 @@ class BadRequestPackageUploadResponse(SnapStoreError):
 pass
 
 
+class SnapNotFoundResponse(SnapStoreError):
+pass
+
+
 class UploadFailedResponse(SnapStoreError):
 pass
 
diff --git a/lib/lp/snappy/model/snap.py b/lib/lp/snappy/model/snap.py
index 35c54d3..e0b4975 100644
--- a/lib/lp/snappy/model/snap.py
+++ b/lib/lp/snappy/model/snap.py
@@ -174,7 +174,10 @@ from lp.snappy.interfaces.snapbase import ISnapBaseSet, NoSuchSnapBase
 from lp.snappy.interfaces.snapbuild import ISnapBuild, ISnapBuildSet
 from lp.snappy.interfaces.snapjob import ISnapRequestBuildsJobSource
 from lp.snappy.interfaces.snappyseries import ISnappyDistroSeriesSet
-from lp.snappy.interfaces.snapstoreclient import ISnapStoreClient
+from lp.snappy.interfaces.snapstoreclient import (
+ISnapStoreClient,
+SnapNotFoundResponse,
+)
 from lp.snappy.model.snapbase import SnapBase
 from lp.snappy.model.snapbuild import SnapBuild
 from lp.snappy.model.snapjob import SnapJob
@@ -737,9 +740,18 @@ class Snap(Storm, WebhookTargetMixin):
 "name."
 )
 snap_store_client = getUtility(ISnapStoreClient)
-root_macaroon_raw = snap_store_client.requestPackageUploadPermission(
-self.store_series, self.store_name
-)
+try:
+root_macaroon_raw = (
+snap_store_client.requestPackageUploadPermission(
+self.store_series, self.store_name
+)
+)
+except SnapNotFoundResponse:
+raise CannotAuthorizeStoreUploads(
+"The requested snap name '{}' is not registered in the snap "
+"store. You can register it at "
+"https://snapcraft.io/register-snap".format(self.store_name)
+)
 sso_caveats = self.extractSSOCaveats(
 Macaroon.deserialize(root_macaroon_raw)
 )
diff --git a/lib/lp/snappy/model/snapstoreclient.py b/lib/lp/snappy/model/snapstoreclient.py
index 387c678..53

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad-buildd:backend-open into launchpad-buildd:master

2022-11-25 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad-buildd:backend-open into launchpad-buildd:master.

Commit message:
Fix the bug with `Backend.open()` caused by file ownership in chroot environment

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad-buildd/+git/launchpad-buildd/+merge/433636

Previously, `Chroot.copy_out()` produced a file owned by root which prevented 
`Backend.open()` to open it for writing.

Now, the file created by `Chroot.copy_out()` is owned by `buildd`
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad-buildd:backend-open into launchpad-buildd:master.
diff --git a/lpbuildd/target/chroot.py b/lpbuildd/target/chroot.py
index 11752c8..80ad1b3 100644
--- a/lpbuildd/target/chroot.py
+++ b/lpbuildd/target/chroot.py
@@ -103,13 +103,17 @@ class Chroot(Backend):
  source_path, full_target_path])
 
 def copy_out(self, source_path, target_path):
-# We can just use a plain copy here, since the file ownership in the
-# host system isn't important.
+# Don't use install(1) here because running `os.stat` to get file mode
+# may be impossible. Instead, copy the with `cp` and set file ownership
+# to buildd (this is necessary so that buildd can read/write the copied
+# file).
 full_source_path = os.path.join(
 self.chroot_path, source_path.lstrip("/"))
 subprocess.check_call(
 ["sudo", "cp", "--preserve=timestamps",
  full_source_path, target_path])
+uid, gid = os.getuid(), os.getgid()
+subprocess.check_call(["sudo", "chown", f"{uid}:{gid}", target_path])
 
 def kill_processes(self):
 """See `Backend`."""
diff --git a/lpbuildd/target/tests/test_chroot.py b/lpbuildd/target/tests/test_chroot.py
index a8971d3..8f2fd38 100644
--- a/lpbuildd/target/tests/test_chroot.py
+++ b/lpbuildd/target/tests/test_chroot.py
@@ -181,10 +181,12 @@ class TestChroot(TestCase):
 Chroot("1", "xenial", "amd64").copy_out(
 "/path/to/source", "/path/to/target")
 
+uid, gid = os.getuid(), os.getgid()
 expected_args = [
 ["sudo", "cp", "--preserve=timestamps",
  "/expected/home/build-1/chroot-autobuild/path/to/source",
  "/path/to/target"],
+["sudo", "chown", f"{uid}:{gid}", "/path/to/target"],
 ]
 self.assertEqual(
 expected_args,
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~cjwatson/launchpad-mojo-specs/+git/private:vbuilder-hybrid-cgroup-hierarchy into ~launchpad/launchpad-mojo-specs/+git/private:vbuilder

2022-11-24 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/launchpad-mojo-specs/+git/private/+merge/433600
Your team Launchpad code reviewers is subscribed to branch 
~launchpad/launchpad-mojo-specs/+git/private:vbuilder.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~lgp171188/lpcraft:easier-way-to-add-a-ppa into lpcraft:main

2022-11-24 Thread Andrey Fedoseev



Diff comments:

> diff --git a/lpcraft/config.py b/lpcraft/config.py
> index d8d2045..f60cbc2 100644
> --- a/lpcraft/config.py
> +++ b/lpcraft/config.py
> @@ -126,12 +135,57 @@ class PackageRepository(ModelConfigDefaults):
>  """
>  
>  type: PackageType  # e.g. `apt``
> +ppa: Optional[PPAShortFormURL]  # e.g. `ppa:launchpad/ppa`
>  formats: List[PackageFormat]  # e.g. `[deb, deb-src]`
> -components: List[PackageComponent]  # e.g. `[main, universe]`
> +components: Optional[List[PackageComponent]]  # e.g. `[main, universe]`
>  suites: List[PackageSuite]  # e.g. `[bionic, focal]`
> -url: AnyHttpUrl
> +url: Optional[AnyHttpUrl]
>  trusted: Optional[bool]
>  
> +@root_validator(pre=True)
> +def validate_multiple_fields(
> +cls, values: Dict[str, Any]
> +) -> Dict[str, Any]:
> +if "url" not in values and "ppa" not in values:
> +raise ValueError(
> +"One of the following keys is required with an appropriate"
> +" value: 'url', 'ppa'."
> +)
> +elif "url" in values and "ppa" in values:
> +raise ValueError(
> +"Only one of the following keys can be specified:"
> +" 'url', 'ppa'."
> +)
> +elif "ppa" not in values and "components" not in values:
> +raise ValueError(
> +"One of the following keys is required with an appropriate"
> +" value: 'components', 'ppa'."
> +)
> +elif "ppa" in values and "components" in values:
> +raise ValueError(
> +"The 'components' key is not allowed when the 'ppa' key is"
> +" specified. PPAs only support the 'main' component."
> +)
> +return values
> +
> +@validator("components", pre=True, always=True)
> +def infer_components_if_ppa_is_set(
> +cls, v: List[PackageComponent], values: Dict[str, Any]
> +) -> List[PackageComponent]:
> +if v is None and values["ppa"]:
> +return ["main"]
> +return v
> +
> +@validator("url", pre=True, always=True)
> +def infer_url_if_ppa_is_set(
> +cls, v: AnyHttpUrl, values: Dict[str, Any]
> +) -> AnyHttpUrl:
> +if v is None and values["ppa"]:
> +return "{}/{}/ubuntu".format(
> +LAUNCHPAD_PPA_BASE_URL, values["ppa"].replace("ppa:", "")

`.replace("ppa:", "")` is probably unnecessary here

> +)
> +return v
> +
>  @validator("trusted")
>  def convert_trusted(cls, v: bool) -> str:
>  # trusted is True or False, but we need `yes` or `no`


-- 
https://code.launchpad.net/~lgp171188/lpcraft/+git/lpcraft/+merge/433493
Your team Launchpad code reviewers is requested to review the proposed merge of 
~lgp171188/lpcraft:easier-way-to-add-a-ppa into lpcraft:main.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~lgp171188/lpcraft:easier-way-to-add-a-ppa into lpcraft:main

2022-11-24 Thread Andrey Fedoseev



Diff comments:

> diff --git a/lpcraft/config.py b/lpcraft/config.py
> index d8d2045..f60cbc2 100644
> --- a/lpcraft/config.py
> +++ b/lpcraft/config.py
> @@ -119,6 +121,13 @@ class PackageSuite(str, Enum):
>  jammy = "jammy"  # 22.04
>  
>  
> +class PPAShortFormURL(pydantic.ConstrainedStr):
> +"""A string with a constrained syntax to match a PPA short form URL."""
> +
> +strict = True
> +regex = 
> re.compile(r"^[a-z0-9][a-z0-9\+\._\-]+/[a-z0-9][a-z0-9\+\._\-]+$")

This regex doesn't match `ppa:launchpad/ppa` form, it works only for 
`launchpad/ppa`. Is that intentional? I see that you use `ppa:launchpad/ppa` as 
an example below, but don't include that form in any of the tests.

> +
> +
>  class PackageRepository(ModelConfigDefaults):
>  """A representation of a package repository.
>  


-- 
https://code.launchpad.net/~lgp171188/lpcraft/+git/lpcraft/+merge/433493
Your team Launchpad code reviewers is requested to review the proposed merge of 
~lgp171188/lpcraft:easier-way-to-add-a-ppa into lpcraft:main.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~cjwatson/launchpad:personal-access-token-git into launchpad:master

2022-11-24 Thread Andrey Fedoseev



Diff comments:

> diff --git a/lib/lp/code/xmlrpc/git.py b/lib/lp/code/xmlrpc/git.py
> index 36a19eb..cbec524 100644
> --- a/lib/lp/code/xmlrpc/git.py
> +++ b/lib/lp/code/xmlrpc/git.py
> @@ -207,13 +289,21 @@ class GitAPI(LaunchpadXMLRPCView):
>  # macaroon that specifically grants access to this repository.
>  # This is only permitted for macaroons not bound to a user.
>  writable = _can_internal_issuer_write(verified)
> +elif (
> +isinstance(verified, AccessTokenVerificationResult)
> +and not verified.can_push
> +):
> +# The user authenticated with an access token without the

Is it possible for a user to bypass this check simply by not providing an 
access token?

> +# "repository:push" scope, so pushing isn't allowed no matter
> +# what permissions they might ordinarily have.
> +writable = False
> +elif repository.repository_type != GitRepositoryType.HOSTED:
> +# Normal users can never push to non-hosted repositories.
> +writable = False
>  else:
>  # This isn't an authorised internal service, so perform normal
>  # user authorisation.
> -writable = (
> -repository.repository_type == GitRepositoryType.HOSTED
> -and check_permission("launchpad.Edit", repository)
> -)
> +writable = check_permission("launchpad.Edit", repository)
>  if not writable:
>  grants = naked_repository.findRuleGrantsByGrantee(requester)
>  if not grants.is_empty():


-- 
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/433538
Your team Launchpad code reviewers is requested to review the proposed merge of 
~cjwatson/launchpad:personal-access-token-git into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad-buildd:update-docs into launchpad-buildd:master

2022-11-23 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad-buildd:update-docs into launchpad-buildd:master.

Commit message:
Update dogfood deployment instructions

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad-buildd/+git/launchpad-buildd/+merge/433517
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad-buildd:update-docs into launchpad-buildd:master.
diff --git a/docs/how-to/deployment.rst b/docs/how-to/deployment.rst
index 6952c28..8182070 100644
--- a/docs/how-to/deployment.rst
+++ b/docs/how-to/deployment.rst
@@ -32,9 +32,11 @@ Testing on dogfood
that the resulting package has been published in the `Launchpad PPA
<https://launchpad.net/~launchpad/+archive/ubuntu/ppa/+packages>`_.
 
-#. Run ``copy-package --from=ppa:launchpad/ubuntu/ppa --suite=focal
-   --to=ppa:launchpad/ubuntu/buildd-staging -b launchpad-buildd`` to copy
-   the current version of launchpad-buildd to the deployment PPA.
+#. Run ``copy-package --from=ppa:launchpad/ubuntu/ppa --suite=jammy
+   --to=ppa:launchpad/ubuntu/buildd-staging -b launchpad-buildd``
+   (from ``ubuntu-archive-tools``) to copy the current version of launchpad-buildd
+   to the deployment PPA (``jammy`` here refers to the series being used on
+   dogfood builder instances).
 
 #. `Wait for PPA publishing to complete
<https://launchpad.net/~launchpad/+archive/ubuntu/buildd-staging/+packages>`__.
@@ -48,9 +50,10 @@ Testing on dogfood
 #. Builders will get the new image after they finish their next build (or
are disabled) and go through being reset.  Since dogfood's build farm is
typically mostly idle, you can use ``manage-builders -l dogfood --reset``
-   to reset all builders and force them to pick up the new image.
+   to reset all builders and force them to pick up the new image
+   (from ``ubuntu-archive-tools``).
 
-#. Perform QA on dogfood until satisfied.
+#. Perform QA on dogfood until satisfied, see :doc:`/how-to/qa`.
 
 Releasing to production
 ---
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~cjwatson/launchpad-buildd:fix-dm-major-detection into launchpad-buildd:master

2022-11-23 Thread Andrey Fedoseev
The proposal to merge ~cjwatson/launchpad-buildd:fix-dm-major-detection into 
launchpad-buildd:master has been updated.

Status: Needs review => Approved

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-buildd/+git/launchpad-buildd/+merge/433516
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~cjwatson/launchpad-buildd:fix-dm-major-detection into launchpad-buildd:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master

2022-11-21 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.

Commit message:
Add redirects from old feature rules URLs

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/433363

/+feature-info -> /+feature-rules/info
/+feature-changelog -> /+feature-rules/changelog


Add `responseStatusCode` property to test browser classes

Update the existing tests to use the new property
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.
diff --git a/lib/lp/charms/browser/tests/test_charmrecipe.py b/lib/lp/charms/browser/tests/test_charmrecipe.py
index 7db9c4c..f3ca37e 100644
--- a/lib/lp/charms/browser/tests/test_charmrecipe.py
+++ b/lib/lp/charms/browser/tests/test_charmrecipe.py
@@ -430,7 +430,7 @@ class TestCharmRecipeAddView(BaseTestCharmRecipeView):
 ]
 ),
 )
-self.assertEqual(303, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(303, browser.responseStatusCode)
 return_to_matcher = AfterPreprocessing(
 urlsplit,
 MatchesStructure(
@@ -716,7 +716,7 @@ class TestCharmRecipeEditView(BaseTestCharmRecipeView):
 
 browser.getControl("Update charm recipe").click()
 
-self.assertEqual(303, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(303, browser.responseStatusCode)
 
 browser = self.getViewBrowser(recipe, user=self.person)
 content = find_main_content(browser.contents)
@@ -792,7 +792,7 @@ class TestCharmRecipeEditView(BaseTestCharmRecipeView):
 
 browser.getControl("Update charm recipe").click()
 
-self.assertEqual(303, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(303, browser.responseStatusCode)
 
 browser = self.getViewBrowser(recipe, user=self.person)
 content = find_main_content(browser.contents)
@@ -1101,7 +1101,7 @@ class TestCharmRecipeAuthorizeView(BaseTestCharmRecipeView):
 self.assertEqual(
 {"root": root_macaroon_raw}, self.recipe.store_secrets
 )
-self.assertEqual(303, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(303, browser.responseStatusCode)
 return_to_matcher = AfterPreprocessing(
 urlsplit,
 MatchesStructure(
diff --git a/lib/lp/charms/tests/test_charmrecipebuild.py b/lib/lp/charms/tests/test_charmrecipebuild.py
index 1e7b069..6a949db 100644
--- a/lib/lp/charms/tests/test_charmrecipebuild.py
+++ b/lib/lp/charms/tests/test_charmrecipebuild.py
@@ -985,7 +985,7 @@ class TestCharmRecipeBuildWebservice(TestCaseWithFactory):
 
 def assertCanOpenRedirectedUrl(self, browser, url):
 browser.open(url)
-self.assertEqual(303, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(303, browser.responseStatusCode)
 urlopen(browser.headers["Location"]).close()
 
 def test_logs(self):
diff --git a/lib/lp/code/browser/tests/test_branch.py b/lib/lp/code/browser/tests/test_branch.py
index e8d914e..8d49a15 100644
--- a/lib/lp/code/browser/tests/test_branch.py
+++ b/lib/lp/code/browser/tests/test_branch.py
@@ -1413,7 +1413,7 @@ class TestBranchDiffView(BrowserTestCase):
 browser = self.getUserBrowser()
 browser.raiseHttpErrors = False
 browser.open(branch_url + "/+diff/2/1")
-self.assertEqual(401, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(401, browser.responseStatusCode)
 self.assertEqual(
 "Proxying of branch diffs is disabled.\n", browser.contents
 )
diff --git a/lib/lp/code/model/tests/test_cibuild.py b/lib/lp/code/model/tests/test_cibuild.py
index 8f555a1..755eb96 100644
--- a/lib/lp/code/model/tests/test_cibuild.py
+++ b/lib/lp/code/model/tests/test_cibuild.py
@@ -1457,7 +1457,7 @@ class TestCIBuildWebservice(TestCaseWithFactory):
 
 def assertCanOpenRedirectedUrl(self, browser, url):
 browser.open(url)
-self.assertEqual(303, int(browser.headers["Status"].split(" ", 1)[0]))
+self.assertEqual(303, browser.responseStatusCode)
 urlopen(browser.headers["Location"]).close()
 
 def test_logs(self):
diff --git a/lib/lp/code/model/tests/test_revisionstatus.py b/lib/lp/code/model/tests/test_revisionstatus.py
index afc7ff2..1ab7618 100644
--- a/lib/lp/code/model/tests/test_revisionstatus.py
+++ b/lib/lp/code/model/tests/test_revisionstatus.py
@@ -452,9 +452,7 @@ class TestRevisionStatusReportWebservice(TestCaseWithFactory):

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:debian-non-free-firmware into launchpad:master

2022-11-17 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:debian-non-free-firmware into launchpad:master.

Commit message:
Add `non-free-firmware` component for Debian imports

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/433188
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:debian-non-free-firmware into launchpad:master.
diff --git a/lib/lp/archiveuploader/tests/data/suite/README b/lib/lp/archiveuploader/tests/data/suite/README
new file mode 100644
index 000..307827e
--- /dev/null
+++ b/lib/lp/archiveuploader/tests/data/suite/README
@@ -0,0 +1,18 @@
+Some files in this directory are PGP-signed
+
+See `lp/testing/gpgkeys/data/README` for more information about the keys being used.
+
+To sign a file you should
+
+1. Import the key:
+
+```
+gpg --import lib/lp/testing/gpgkeys/data/foo@canonical.com.pub
+gpg --import lib/lp/testing/gpgkeys/data/foo@canonical.com.sec
+```
+
+2. Add a signature like so:
+
+```
+gpg --clearsign -u foo@canonical.com PATH_TO_THE_FILE
+```
diff --git a/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1.diff.gz b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1.diff.gz
new file mode 100644
index 000..5f9eeb9
Binary files /dev/null and b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1.diff.gz differ
diff --git a/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1.dsc b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1.dsc
new file mode 100644
index 000..63c210a
--- /dev/null
+++ b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1.dsc
@@ -0,0 +1,21 @@
+-BEGIN PGP SIGNED MESSAGE-
+Hash: SHA1
+
+Format: 1.0
+Source: bar
+Version: 1.0-1
+Binary: bar
+Maintainer: Launchpad team 
+Architecture: any
+Standards-Version: 3.6.2
+Files: 
+ fc1464e5985b962a042d5354452f361d 164 bar_1.0.orig.tar.gz
+ 1e35b810764f140af9616de8274e6e73 537 bar_1.0-1.diff.gz
+
+-BEGIN PGP SIGNATURE-
+Version: GnuPG v1.4.3 (GNU/Linux)
+
+iD8DBQFFt7Cojn63CGxkqMURAo6FAJ9ZUagUNtYpmZrqFwL6LXDKOUSOPwCdFqPa
+BdrMeT+0Hg+yMS69uO+qJRI=
+=mjFU
+-END PGP SIGNATURE-
diff --git a/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1_source.changes b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1_source.changes
new file mode 100644
index 000..8fff1d9
--- /dev/null
+++ b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0-1_source.changes
@@ -0,0 +1,31 @@
+-BEGIN PGP SIGNED MESSAGE-
+Hash: SHA1
+
+Format: 1.7
+Date: Thu, 16 Feb 2006 15:34:09 +
+Source: bar
+Binary: bar
+Architecture: source
+Version: 1.0-1
+Distribution: breezy
+Urgency: low
+Maintainer: Launchpad team 
+Changed-By: Daniel Silverstone 
+Description: 
+ bar- Stuff for testing
+Changes: 
+ bar (1.0-1) breezy; urgency=low
+ .
+   * Initial version
+Files: 
+ 5d533778b698edc1a122098a98c8490e 512 non-free-firmware/devel optional bar_1.0-1.dsc
+ fc1464e5985b962a042d5354452f361d 164 non-free-firmware/devel optional bar_1.0.orig.tar.gz
+ 1e35b810764f140af9616de8274e6e73 537 non-free-firmware/devel optional bar_1.0-1.diff.gz
+-BEGIN PGP SIGNATURE-
+Comment: GPGTools - http://gpgtools.org
+
+iHQEARECADQWIQQ0DKO7Jw4nFsnuC3aOfrcIbGSoxQUCY3YW7xYcZm9vLmJhckBj
+YW5vbmljYWwuY29tAAoJEI5+twhsZKjF2dAAnihUwKujXW1eHT4QspWTSzW6PSRs
+AJ9lJOiYUiKXJXfEcfaG/Pi7G1cLZA==
+=R1Ut
+-END PGP SIGNATURE-
diff --git a/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0.orig.tar.gz b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0.orig.tar.gz
new file mode 100644
index 000..c5a58e8
Binary files /dev/null and b/lib/lp/archiveuploader/tests/data/suite/bar_1.0-1_nonfreefirmware_component/bar_1.0.orig.tar.gz differ
diff --git a/lib/lp/archiveuploader/tests/test_uploadprocessor.py b/lib/lp/archiveuploader/tests/test_uploadprocessor.py
index 29d3024..1c4c37f 100644
--- a/lib/lp/archiveuploader/tests/test_uploadprocessor.py
+++ b/lib/lp/archiveuploader/tests/test_uploadprocessor.py
@@ -1417,6 +1417,7 @@ class TestUploadProcessor(StatsMixin, TestUploadProcessorBase):
 # such that:
 #   'contrib' -> 'multiverse'
 #   'non-free' -> 'multiverse'
+#   'non-free-firmware' -> 'multiverse'
 #   everything else -> 'universe'
 #
 # This is to relieve the archive admins of some work where this is
@@ -1467,11 +1468,22 @@ class TestUploadProcessor(StatsMixin, TestUploadProcessorBase):
 "bar_1.0-1_nonfree_component", "multiverse"
 )
 
+def testUploadNonfr

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:jira-bug-watch into launchpad:master

2022-11-16 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:jira-bug-watch 
into launchpad:master.

Commit message:
Add external bug tracker for JIRA

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/433103
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:jira-bug-watch into launchpad:master.
diff --git a/lib/lp/bugs/externalbugtracker/__init__.py b/lib/lp/bugs/externalbugtracker/__init__.py
index 65c5333..d4b887d 100644
--- a/lib/lp/bugs/externalbugtracker/__init__.py
+++ b/lib/lp/bugs/externalbugtracker/__init__.py
@@ -51,6 +51,7 @@ from lp.bugs.externalbugtracker.bugzilla import Bugzilla
 from lp.bugs.externalbugtracker.debbugs import DebBugs, DebBugsDatabaseNotFound
 from lp.bugs.externalbugtracker.github import GitHub
 from lp.bugs.externalbugtracker.gitlab import GitLab
+from lp.bugs.externalbugtracker.jira import Jira
 from lp.bugs.externalbugtracker.mantis import Mantis
 from lp.bugs.externalbugtracker.roundup import Roundup
 from lp.bugs.externalbugtracker.rt import RequestTracker
@@ -68,6 +69,7 @@ BUG_TRACKER_CLASSES = {
 BugTrackerType.ROUNDUP: Roundup,
 BugTrackerType.RT: RequestTracker,
 BugTrackerType.SOURCEFORGE: SourceForge,
+BugTrackerType.JIRA: Jira,
 }
 
 
diff --git a/lib/lp/bugs/externalbugtracker/base.py b/lib/lp/bugs/externalbugtracker/base.py
index ee7be38..0d2efd4 100644
--- a/lib/lp/bugs/externalbugtracker/base.py
+++ b/lib/lp/bugs/externalbugtracker/base.py
@@ -279,16 +279,17 @@ class ExternalBugTracker:
 except requests.RequestException as e:
 raise BugTrackerConnectError(self.baseurl, e)
 
-def _postPage(self, page, form, repost_on_redirect=False):
+def _postPage(self, page, data, repost_on_redirect=False, json=False):
 """POST to the specified page and form.
 
-:param form: is a dict of form variables being POSTed.
+:param data: is a dict of form variables being POSTed.
 :param repost_on_redirect: override RFC-compliant redirect handling.
 By default, if the POST receives a redirect response, the
 request to the redirection's target URL will be a GET.  If
 `repost_on_redirect` is True, this method will do a second POST
 instead.  Do this only if you are sure that repeated POST to
 this page is safe, as is usually the case with search forms.
+:param json: if True, the data will be JSON encoded.
 :return: A `requests.Response` object.
 """
 hooks = (
@@ -301,8 +302,12 @@ class ExternalBugTracker:
 if not url.endswith("/"):
 url += "/"
 url = urljoin(url, page)
+if json:
+kwargs = {"json": data}
+else:
+kwargs = {"data": data}
 response = self.makeRequest(
-"POST", url, headers=self._getHeaders(), data=form, hooks=hooks
+"POST", url, headers=self._getHeaders(), hooks=hooks, **kwargs
 )
 raise_for_status_redacted(response)
 return response
diff --git a/lib/lp/bugs/externalbugtracker/jira.py b/lib/lp/bugs/externalbugtracker/jira.py
new file mode 100644
index 000..6f9541f
--- /dev/null
+++ b/lib/lp/bugs/externalbugtracker/jira.py
@@ -0,0 +1,268 @@
+# Copyright 2019 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Jira ExternalBugTracker utility."""
+
+__all__ = [
+"Jira",
+"JiraCredentials",
+"JiraBug",
+"JiraStatus",
+"JiraPriority",
+]
+
+import base64
+import datetime
+from enum import Enum
+from typing import Dict, Iterable, NamedTuple, Optional, Tuple
+from urllib.parse import urlunsplit
+
+import dateutil.parser
+
+from lp.bugs.externalbugtracker import (
+BugTrackerConnectError,
+ExternalBugTracker,
+)
+from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus
+from lp.services.config import config
+from lp.services.webapp.url import urlsplit
+
+JiraCredentials = NamedTuple(
+"JiraCredentials",
+(
+("username", str),
+("password", str),
+),
+)
+
+
+class JiraStatus(Enum):
+
+UNDEFINED = "undefined"
+NEW = "new"
+INDETERMINATE = "indeterminate"
+DONE = "done"
+
+@property
+def launchpad_status(self):
+if self == JiraStatus.UNDEFINED:
+return BugTaskStatus.UNKNOWN
+elif self == JiraStatus.NEW:
+return BugTaskStatus.NEW
+elif self == JiraStatus.INDETERMINATE:
+return BugTaskStatus.INPROGR

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad-buildd:backend-open into launchpad-buildd:master

2022-11-09 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad-buildd:backend-open into launchpad-buildd:master.

Commit message:
Use `Backend.open` to modify files in target environments

instead of using a local temporary file and `copy_out` / `copy_in` methods

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad-buildd/+git/launchpad-buildd/+merge/432731

A new method `open` is added to the base `Backend` class

The method access to the files in the target environment via a file-like object.

Under the hood it uses a temporary file on the host system and `copy_in` / 
`copy_out` methods to transfer the file to / from the target environment.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad-buildd:backend-open into launchpad-buildd:master.
diff --git a/lpbuildd/binarypackage.py b/lpbuildd/binarypackage.py
index c3fef09..3498e58 100644
--- a/lpbuildd/binarypackage.py
+++ b/lpbuildd/binarypackage.py
@@ -156,11 +156,11 @@ class BinaryPackageBuildManager(DebianBuildManager):
self.archive_purpose))
 if self.build_debug_symbols:
 currently_building_contents += 'Build-Debug-Symbols: yes\n'
-with tempfile.NamedTemporaryFile(mode='w+') as currently_building:
+with self.backend.open(
+'/CurrentlyBuilding', mode='w+'
+) as currently_building:
 currently_building.write(currently_building_contents)
-currently_building.flush()
 os.fchmod(currently_building.fileno(), 0o644)
-self.backend.copy_in(currently_building.name, '/CurrentlyBuilding')
 
 args = ["sbuild-package", self._buildid, self.arch_tag]
 args.append(self.suite)
diff --git a/lpbuildd/ci.py b/lpbuildd/ci.py
index 04aa5f8..601d8b4 100644
--- a/lpbuildd/ci.py
+++ b/lpbuildd/ci.py
@@ -6,7 +6,6 @@ from configparser import (
 NoSectionError,
 )
 import os
-import tempfile
 import yaml
 
 from twisted.internet import defer
@@ -168,14 +167,10 @@ class CIBuildManager(BuildManagerProxyMixin, DebianBuildManager):
 ["--plugin-setting", f"{key}={value}"])
 if self.secrets is not None:
 text = yaml.dump(self.secrets)
-with tempfile.NamedTemporaryFile(mode="w") as f:
+with self.backend.open(
+"/build/.launchpad-secrets.yaml", mode="w"
+) as f:
 f.write(text)
-f.flush()
-path_to_secrets = f.name
-self.backend.copy_in(
-source_path=path_to_secrets,
-target_path="/build/.launchpad-secrets.yaml"
-)
 args.extend(
 ["--secrets", "/build/.launchpad-secrets.yaml"])
 if self.scan_malware:
diff --git a/lpbuildd/target/apt.py b/lpbuildd/target/apt.py
index ebd4683..a411806 100644
--- a/lpbuildd/target/apt.py
+++ b/lpbuildd/target/apt.py
@@ -5,7 +5,6 @@ import logging
 import os
 import subprocess
 import sys
-import tempfile
 from textwrap import dedent
 import time
 
@@ -30,49 +29,44 @@ class OverrideSourcesList(Operation):
 
 def run(self):
 logger.info("Overriding sources.list in build-%s", self.args.build_id)
-with tempfile.NamedTemporaryFile(mode="w+") as sources_list:
+with self.backend.open(
+"/etc/apt/sources.list", mode="w+"
+) as sources_list:
 for archive in self.args.archives:
 print(archive, file=sources_list)
-sources_list.flush()
 os.fchmod(sources_list.fileno(), 0o644)
-self.backend.copy_in(sources_list.name, "/etc/apt/sources.list")
-with tempfile.NamedTemporaryFile(mode="w+") as apt_retries_conf:
+with self.backend.open(
+"/etc/apt/apt.conf.d/99retries", mode="w+"
+) as apt_retries_conf:
 print('Acquire::Retries "3";', file=apt_retries_conf)
-apt_retries_conf.flush()
 os.fchmod(apt_retries_conf.fileno(), 0o644)
-self.backend.copy_in(
-apt_retries_conf.name, "/etc/apt/apt.conf.d/99retries")
 # Versions of APT that support phased updates do this automatically
 # if running in a chroot, but builds may be running in a LXD
 # container instead.
-with tempfile.NamedTemporaryFile(mode="w+") as apt_phasing_conf:
+with self.backend.open(
+"/etc/apt/apt.conf.d/99phasing", mode="w+"
+) as apt_phasing_conf:
 print('APT::Get::Always-Include-Phased-Updates "true";',
   file=apt_phasing_conf)
-apt_pha

Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master

2022-11-06 Thread Andrey Fedoseev
Guruprasad, I've made the requested changes.
-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/432249
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master

2022-10-28 Thread Andrey Fedoseev
Colin, I updated this based on your suggestion.
-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/432249
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master

2022-10-27 Thread Andrey Fedoseev



Diff comments:

> diff --git a/lib/lp/services/features/browser/edit.py 
> b/lib/lp/services/features/browser/edit.py
> index 3acc671..36ea7a3 100644
> --- a/lib/lp/services/features/browser/edit.py
> +++ b/lib/lp/services/features/browser/edit.py
> @@ -69,7 +69,7 @@ class FeatureControlView(LaunchpadFormView):
>  
>  def canSubmit(self, action):
>  """Is the user authorized to change the rules?"""
> -return check_permission("launchpad.Admin", self.context)
> +return check_permission("launchpad.EditFeatureRules", self.context)

The context here is `ILaunchpadRoot`. I think that granting `launchpad.Admin` 
permissions on that object to launchpad developers might have some undesired 
consequences. So, we need to apply a more granular approach, thus the new 
permission.

>  
>  @action("Change", name="change", condition=canSubmit)
>  def change_action(self, action, data):


-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/432249
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master

2022-10-27 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.

Commit message:
Allow members of `launchpad` team to edit feature rules

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/432249
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:edit-feature-rules into launchpad:master.
diff --git a/lib/lp/permissions.zcml b/lib/lp/permissions.zcml
index dd5a177..0e45a78 100644
--- a/lib/lp/permissions.zcml
+++ b/lib/lp/permissions.zcml
@@ -110,4 +110,14 @@
 title="Special permission to allow only scripts to write."
 access_level="write" />
 
+  
+  
+  
+
 
diff --git a/lib/lp/services/features/browser/configure.zcml b/lib/lp/services/features/browser/configure.zcml
index d858fca..0511992 100644
--- a/lib/lp/services/features/browser/configure.zcml
+++ b/lib/lp/services/features/browser/configure.zcml
@@ -9,36 +9,27 @@
 xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc;
 i18n_domain="launchpad">
 
-
+
 
 
-
+
 
 
 
 
 
diff --git a/lib/lp/services/features/browser/edit.py b/lib/lp/services/features/browser/edit.py
index 3acc671..36ea7a3 100644
--- a/lib/lp/services/features/browser/edit.py
+++ b/lib/lp/services/features/browser/edit.py
@@ -69,7 +69,7 @@ class FeatureControlView(LaunchpadFormView):
 
 def canSubmit(self, action):
 """Is the user authorized to change the rules?"""
-return check_permission("launchpad.Admin", self.context)
+return check_permission("launchpad.EditFeatureRules", self.context)
 
 @action("Change", name="change", condition=canSubmit)
 def change_action(self, action, data):
diff --git a/lib/lp/services/features/browser/tests/test_feature_editor.py b/lib/lp/services/features/browser/tests/test_feature_editor.py
index a6fb812..98262d5 100644
--- a/lib/lp/services/features/browser/tests/test_feature_editor.py
+++ b/lib/lp/services/features/browser/tests/test_feature_editor.py
@@ -30,6 +30,27 @@ class TestFeatureControlPage(BrowserTestCase):
 def setUp(self):
 super().setUp()
 self.useFixture(FakeLogger())
+self.celebrities = getUtility(ILaunchpadCelebrities)
+
+@property
+def admin_browser(self):
+return self.getUserBrowserAsTeamMember([self.celebrities.admin])
+
+@property
+def launchpad_developer_browser(self):
+return self.getUserBrowserAsTeamMember(
+[self.celebrities.launchpad_developers]
+)
+
+@property
+def registry_expert_browser(self):
+return self.getUserBrowserAsTeamMember(
+[self.celebrities.registry_experts]
+)
+
+@property
+def unprivileged_browser(self):
+return self.getUserBrowserAsTeamMember([])
 
 def getUserBrowserAsTeamMember(self, teams):
 """Make a TestBrowser authenticated as a team member.
@@ -42,11 +63,6 @@ class TestFeatureControlPage(BrowserTestCase):
 team.addMember(self.user, reviewer=team.teamowner)
 return self.getUserBrowser(url=None, user=self.user)
 
-def getUserBrowserAsAdmin(self):
-"""Make a new TestBrowser logged in as an admin user."""
-admin_team = getUtility(ILaunchpadCelebrities).admin
-return self.getUserBrowserAsTeamMember([admin_team])
-
 def getFeatureRulesViewURL(self):
 root = getUtility(ILaunchpadRoot)
 return canonical_url(root, view_name="+feature-rules")
@@ -57,7 +73,7 @@ class TestFeatureControlPage(BrowserTestCase):
 
 def test_feature_page_default_value(self):
 """No rules in the sampledata gives no content in the page"""
-browser = self.getUserBrowserAsAdmin()
+browser = self.admin_browser
 browser.open(self.getFeatureRulesViewURL())
 textarea = browser.getControl(name="field.feature_rules")
 # and by default, since there are no rules in the sample data, it's
@@ -71,7 +87,7 @@ class TestFeatureControlPage(BrowserTestCase):
 ("ui.icing", "beta_user", 300, "4.0"),
 ]
 )
-browser = self.getUserBrowserAsAdmin()
+browser = self.admin_browser
 browser.open(self.getFeatureRulesViewURL())
 textarea = browser.getControl(name="field.feature_rules")
 self.assertThat(
@@ -87,27 +103,32 @@ class TestFeatureControlPage(BrowserTestCase):
 Unauthorized, browser.open, self.getFeatureRulesViewURL()
 )
 
-def test_feature_rules_plebian_unauthorized(self):
+def test_feature_rules_unprivileged_unauthorized(self):
 "&quo

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-export-break-fix into launchpad:master

2022-10-26 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-export-break-fix into launchpad:master 
with ~andrey-fedoseev/launchpad:bug-presense as a prerequisite.

Commit message:
UCT import/export: handle the `break-fix` entries

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/432181

For each `break-fix` entry create a `BugPresence` instance linked to the 
default git repository of the project (if exists)

If a `break-fix` entry includes multiple git commits in the "fixed" section it 
means that either of them fixes the issue. So, we create multiple `BugPresence` 
instances, one per commit listed in the "fixed" section.

Items such as `local-CVE-2022-23222-fix` are currently ignored
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-export-break-fix into launchpad:master.
diff --git a/lib/lp/bugs/model/bugpresence.py b/lib/lp/bugs/model/bugpresence.py
index d4f718b..749145a 100644
--- a/lib/lp/bugs/model/bugpresence.py
+++ b/lib/lp/bugs/model/bugpresence.py
@@ -20,6 +20,9 @@ class BugPresence(StormBase):
 """See `IBugPresence`."""
 
 __storm_table__ = "BugPresence"
+__storm_order__ = [
+"id",
+]
 
 id = Int(primary=True)
 
diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
index 20ae931..6bfe91c 100644
--- a/lib/lp/bugs/scripts/tests/test_uct.py
+++ b/lib/lp/bugs/scripts/tests/test_uct.py
@@ -6,10 +6,12 @@ from typing import List
 
 from pytz import UTC
 from zope.component import getUtility
+from zope.security.proxy import removeSecurityProxy
 
 from lp.app.enums import InformationType
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.bugs.enums import VulnerabilityStatus
+from lp.bugs.interfaces.bugpresence import IBugPresenceSet
 from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus
 from lp.bugs.model.bug import Bug
 from lp.bugs.model.bugtask import BugTask
@@ -274,6 +276,20 @@ class TestCVE(TestCaseWithFactory):
 tags=set(),
 patches=[
 UCTRecord.Patch(
+patch_type="break-fix",
+entry=(
+"457f44363a8894135c85b7a9afd2bd8196db24ab "
+"c25b2ae136039ffa820c26138ed4a5e5f3ab3841|"
+"4969c06a0d83c9c3dc50b8efcdc8eeedfce896f6"
+),
+),
+UCTRecord.Patch(
+patch_type="break-fix",
+entry=(
+"- c25b2ae136039ffa820c26138ed4a5e5f3ab3841"
+),
+),
+UCTRecord.Patch(
 patch_type="upstream",
 entry=(
 "https://github.com/389ds/389-ds-base/;
@@ -416,6 +432,30 @@ class TestCVE(TestCaseWithFactory):
 importance=None,
 status=BugTaskStatus.FIXRELEASED,
 status_explanation="reason 4",
+break_fixes=[
+CVE.BreakFix(
+broken_git_commit_sha1=(
+"457f44363a8894135c85b7a9afd2bd8196db24ab"
+),
+fixed_git_commit_sha1=(
+"c25b2ae136039ffa820c26138ed4a5e5f3ab3841"
+),
+),
+CVE.BreakFix(
+broken_git_commit_sha1=(
+"457f44363a8894135c85b7a9afd2bd8196db24ab"
+),
+fixed_git_commit_sha1=(
+"4969c06a0d83c9c3dc50b8efcdc8eeedfce896f6"
+),
+),
+CVE.BreakFix(
+broken_git_commit_sha1=None,
+fixed_git_commit_sha1=(
+"c25b2ae136039ffa820c26138ed4a5e5f3ab3841"
+),
+),
+],
 ),
 CVE.UpstreamPackage(
 target=product_2,
@@ -423,6 +463,7 @@ class TestCVE(TestCaseWithFactory):
 importance=None,
 status=BugTaskStatus.FIXRELEASED,
 status_explanation="",
+break_fixes

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:question-title into launchpad:master

2022-10-26 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:question-title 
into launchpad:master.

Commit message:
Include question title to the browser window title

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/432180
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:question-title into launchpad:master.
diff --git a/lib/lp/answers/browser/question.py b/lib/lp/answers/browser/question.py
index 7e5926a..65bbd94 100644
--- a/lib/lp/answers/browser/question.py
+++ b/lib/lp/answers/browser/question.py
@@ -296,6 +296,13 @@ class QuestionBreadcrumb(Breadcrumb):
 def text(self):
 return "Question #%d" % self.context.id
 
+@property
+def detail(self):
+return smartquote('%s "%s"') % (
+self.text,
+self.context.title,
+)
+
 
 class QuestionSetView(LaunchpadFormView):
 """View for the Answer Tracker index page."""
diff --git a/lib/lp/answers/browser/tests/test_views.py b/lib/lp/answers/browser/tests/test_views.py
index 9dd7757..c329907 100644
--- a/lib/lp/answers/browser/tests/test_views.py
+++ b/lib/lp/answers/browser/tests/test_views.py
@@ -33,7 +33,7 @@ class TestEmailObfuscated(BrowserTestCase):
 browser = self.getBrowserForQuestionWithEmail(
 email_address, no_login=False
 )
-self.assertEqual(4, browser.contents.count(email_address))
+self.assertEqual(6, browser.contents.count(email_address))
 
 def test_anonymous_sees_not_email_address(self):
 """The anonymous user cannot see the email address on the page."""
diff --git a/lib/lp/answers/stories/question-browse-and-search.rst b/lib/lp/answers/stories/question-browse-and-search.rst
index 90b15a7..61cc8cf 100644
--- a/lib/lp/answers/stories/question-browse-and-search.rst
+++ b/lib/lp/answers/stories/question-browse-and-search.rst
@@ -139,7 +139,7 @@ details of the question are available.
 
 >>> browser.getLink("Slow system").click()
 >>> print(browser.title)
-Question #7 : ...
+Question #7 “Slow system” : ...
 >>> soup = find_main_content(browser.contents)
 >>> soup("div", "report")
 [I get really poor hard drive
@@ -161,9 +161,8 @@ to jump to the question.
 >>> browser.open("http://answers.launchpad.test/;)
 >>> browser.getControl(name="field.search_text").value = "9"
 >>> browser.getControl("Find Answers").click()
->>> from lp.services.helpers import backslashreplace
->>> print(backslashreplace(browser.title))
-Question #9 : ...
+>>> print(browser.title)
+Question #9 ...
 
 While reading the Ubuntu forums for a solution to his problem,
 Average Joe finds some unlinked text that refers to how to
@@ -174,8 +173,8 @@ the answer.
 >>> browser.open("http://answers.launchpad.test/;)
 >>> browser.getControl(name="field.search_text").value = " #6 "
 >>> browser.getControl("Find Answers").click()
->>> print(backslashreplace(browser.title))
-Question #6 : ...
+>>> print(browser.title)
+Question #6 ...
 
 The Answer Tracker cannot identify Question ids within text. Average
 Joe finds a reference to question 8 in a blog. He copies 'question 8'
@@ -243,7 +242,7 @@ He clicks on the link to read the question description.
 
 >>> browser.getLink("Firefox is slow").click()
 >>> print(browser.title)
-Question #3 : ...
+Question #3 “Firefox is slow and consumes too much RAM” : ...
 
 The user must choose at least one status when searching questions. An
 error is displayed when the user forgets to select a status.
diff --git a/lib/lp/answers/stories/question-message.rst b/lib/lp/answers/stories/question-message.rst
index c6ca281..f733968 100644
--- a/lib/lp/answers/stories/question-message.rst
+++ b/lib/lp/answers/stories/question-message.rst
@@ -12,9 +12,6 @@ an email post to examine the markup rules. This message contains a
 quoted passage, and a signature with an email address in it.
 
 >>> user_browser.open("http://answers.launchpad.test/ubuntu/+question/11;)
->>> print(user_browser.title)
-Question #11 : ...
-
 >>> user_browser.getControl("Message").value = (
 ... "Top quoting is bad netiquette.\n"
 ... "The leading text will be displayed\n"
@@ -39,8 +36,6 @@ Email addresses are only shown to authenticated users
 Email addresses are visible to authenticated users. Sample Person is
 authenticated already, so they will see 'hu...@somewhe

Re: [Launchpad-reviewers] [Merge] ~lgp171188/launchpad:optimize-distribution-has-published-sources-queries into launchpad:master

2022-10-18 Thread Andrey Fedoseev
I've made a couple of similar optimizations. In my case, I've added a method to 
the corresponding `*Set` class that would load the necessary data for multiple 
objects at once, using a single database query. In your case it would mean 
loading published sources for multiple archives.

The `archive.getPublishedSources` method could be updated to call the new 
method from `ArchiveSet` to get published sources with a single-item list of 
archives.
-- 
https://code.launchpad.net/~lgp171188/launchpad/+git/launchpad/+merge/431724
Your team Launchpad code reviewers is requested to review the proposed merge of 
~lgp171188/launchpad:optimize-distribution-has-published-sources-queries into 
launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~lgp171188/launchpad:optimize-distribution-has-published-sources-queries into launchpad:master

2022-10-18 Thread Andrey Fedoseev
Could `lp.soyuz.model.archive.ArchiveSet.getPublicationsInArchives` be used 
here?
-- 
https://code.launchpad.net/~lgp171188/launchpad/+git/launchpad/+merge/431724
Your team Launchpad code reviewers is requested to review the proposed merge of 
~lgp171188/launchpad:optimize-distribution-has-published-sources-queries into 
launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-bug-presence into launchpad:db-devel

2022-10-18 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:db-bug-presence 
into launchpad:db-devel.

Commit message:
Add `BugPresence` table


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431711

It represents a range of versions or git commits in which the bug was present.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-bug-presence into launchpad:db-devel.
diff --git a/database/schema/patch-2211-12-0.sql b/database/schema/patch-2211-12-0.sql
new file mode 100644
index 000..24ecf86
--- /dev/null
+++ b/database/schema/patch-2211-12-0.sql
@@ -0,0 +1,60 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages = ERROR;
+
+CREATE TABLE BugPresence
+(
+id serial PRIMARY KEY,
+buginteger NOT NULL REFERENCES Bug ON DELETE CASCADE,
+projectinteger REFERENCES Product ON DELETE CASCADE,
+distribution   integer REFERENCES Distribution ON DELETE CASCADE,
+sourcepackagename  integer REFERENCES SourcePackageName ON DELETE CASCADE,
+git_repository integer REFERENCES GitRepository ON DELETE CASCADE,
+broken_version text,
+fixed_version  text,
+broken_git_commit_sha1 varchar(40),
+fixed_git_commit_sha1  varchar(40),
+CONSTRAINT version_or_git_range CHECK ((
+broken_version is NULL
+and fixed_version is NULL
+and project is NULL
+and distribution is NULL
+and BugPresence.sourcepackagename is NULL
+) != (
+broken_git_commit_sha1 is NULL
+and fixed_git_commit_sha1 is NULL
+and git_repository is NULL
+)),
+CONSTRAINT version_range_target CHECK (
+(
+broken_version is not NULL
+or BugPresence.fixed_version is not NULL
+) = (
+project is not NULL
+or distribution is not NULL
+or BugPresence.sourcepackagename is not NULL
+)
+),
+CONSTRAINT git_range_target CHECK (
+(
+broken_git_commit_sha1 is not NULL
+or fixed_git_commit_sha1 is not NULL
+) = (git_repository is not NULL)
+)
+);
+
+CREATE INDEX BugPresence__bug__idx ON BugPresence(bug);
+
+COMMENT ON TABLE BugPresence IS 'Range of versions or git commits in which the bug is present.';
+COMMENT ON COLUMN BugPresence.bug is 'The Bug this BugPresence related to.';
+COMMENT ON COLUMN BugPresence.project is 'The project in which the bug is present.';
+COMMENT ON COLUMN BugPresence.distribution is 'The distribution in which the bug is present.';
+COMMENT ON COLUMN BugPresence.sourcepackagename is 'The package in which the bug is present.';
+COMMENT ON COLUMN BugPresence.git_repository is 'The git repository in which the bug is present.';
+COMMENT ON COLUMN BugPresence.broken_version is 'The version in which the bug was introduced.';
+COMMENT ON COLUMN BugPresence.fixed_version is 'The version in which the bug was fixed.';
+COMMENT ON COLUMN BugPresence.broken_git_commit_sha1 is 'The git commit in which the bug was introduced.';
+COMMENT ON COLUMN BugPresence.fixed_git_commit_sha1 is 'The git commit in which the bug was fixed.';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 12, 0);
diff --git a/database/schema/security.cfg b/database/schema/security.cfg
index a7f801b..4d5ab4f 100644
--- a/database/schema/security.cfg
+++ b/database/schema/security.cfg
@@ -147,6 +147,7 @@ public.bugnotification  = SELECT, INSERT, UPDATE, DELETE
 public.bugnotificationattachment= SELECT, INSERT
 public.bugnotificationfilter= SELECT, INSERT, UPDATE, DELETE
 public.bugnotificationrecipient = SELECT, INSERT, UPDATE, DELETE
+public.bugpresence  = SELECT, INSERT, UPDATE, DELETE
 public.bugsummary   = SELECT
 public.bugsummaryjournal= SELECT
 public.bugsummary_rollup_journal(integer) = EXECUTE
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:bug-presense into launchpad:master

2022-10-18 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:bug-presense 
into launchpad:master.

Commit message:
Add `BugPresence` model

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431710

It represents a range of versions or git commits in which the bug was present.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:bug-presense into launchpad:master.
diff --git a/lib/lp/bugs/configure.zcml b/lib/lp/bugs/configure.zcml
index 6eaa58c..89e0402 100644
--- a/lib/lp/bugs/configure.zcml
+++ b/lib/lp/bugs/configure.zcml
@@ -1113,4 +1113,29 @@
 >
 
   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
diff --git a/lib/lp/bugs/interfaces/bugpresence.py b/lib/lp/bugs/interfaces/bugpresence.py
new file mode 100644
index 000..426a2d7
--- /dev/null
+++ b/lib/lp/bugs/interfaces/bugpresence.py
@@ -0,0 +1,85 @@
+from lazr.restful.fields import Reference
+from zope.interface import Attribute, Interface
+from zope.schema import Choice, Int, TextLine
+
+from lp import _
+from lp.services.fields import BugField
+
+__all__ = ["IBugPresence", "IBugPresenceSet"]
+
+
+class IBugPresence(Interface):
+"""
+Represents a range of versions or git commits in which the bug was present.
+"""
+
+id = Int()
+bug = BugField(title=_("Bug"), readonly=True)
+bug_id = Int()
+
+project = Choice(title=_("Project"), required=False, vocabulary="Product")
+project_id = Attribute("The product ID")
+sourcepackagename = Choice(
+title=_("Package"), required=False, vocabulary="SourcePackageName"
+)
+sourcepackagename_id = Attribute("The sourcepackagename ID")
+distribution = Choice(
+title=_("Distribution"), required=False, vocabulary="Distribution"
+)
+distribution_id = Attribute("The distribution ID")
+
+broken_version = TextLine(
+required=False, title=_("Version that introduced the bug")
+)
+fixed_version = TextLine(
+required=False, title=_("Version that fixed the bug")
+)
+
+git_repository = Choice(
+title=_("Git repository"), required=False, vocabulary="GitRepository"
+)
+git_repository_id = Attribute("The git repository ID")
+broken_git_commit_sha1 = TextLine(
+required=False,
+title=_("Git commit that introduced the bug"),
+max_length=40,
+)
+fixed_git_commit_sha1 = TextLine(
+required=False, title=_("Git commit that fixed the bug"), max_length=40
+)
+
+target = Reference(
+title=_("Target"),
+required=True,
+schema=Interface,  # IBugTarget|IGitRepository
+)
+
+
+class IBugPresenceSet(Interface):
+def new(
+bug,
+target,
+broken_version,
+fixed_version,
+broken_git_commit_sha1,
+fixed_git_commit_sha1,
+):
+"""Create new BugPresence instance.
+:param bug: a bug to create a bug presence for
+:param target: a project, a distribution, a distribution package or
+a git repository
+:param broken_version: version in which the bug was introduced
+:param fixed_version: version in which the bug was fixed
+:param broken_git_commit_sha1: git commit in which the bug
+was introduced (for git repository)
+:param fixed_git_commit_sha1: git commit in which the bug
+was fixed (for git repository)
+"""
+pass
+
+def getByBug(bug):
+"""Get all BugPresence instances for the given bug.
+:param bug: a bug to get the bug presence instances from
+:return: a collection of BugPresence instances
+"""
+pass
diff --git a/lib/lp/bugs/model/bugpresence.py b/lib/lp/bugs/model/bugpresence.py
new file mode 100644
index 000..d4f718b
--- /dev/null
+++ b/lib/lp/bugs/model/bugpresence.py
@@ -0,0 +1,138 @@
+from storm.properties import Int, Unicode
+from storm.references import Reference
+from zope.interface import implementer
+
+from lp.bugs.interfaces.bugpresence import IBugPresence, IBugPresenceSet
+from lp.code.interfaces.gitrepository import IGitRepository
+from lp.registry.interfaces.distribution import IDistribution
+from lp.registry.interfaces.distributionsourcepackage import (
+IDistributionSourcePackage,
+)
+from lp.registry.interfaces.product import IProduct
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
+
+__all__ = ["BugPresence", "BugPresenceSet&q

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-base-features into launchpad:master

2022-10-13 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.

Commit message:
Use `SnapBase.features` in `snapcraft.yaml` parser

to determine whether duplicate build-on values are allowed instead of relying 
on snap base name

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431544
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.
diff --git a/lib/lp/snappy/adapters/buildarch.py b/lib/lp/snappy/adapters/buildarch.py
index 102eb74..eb87a7d 100644
--- a/lib/lp/snappy/adapters/buildarch.py
+++ b/lib/lp/snappy/adapters/buildarch.py
@@ -9,6 +9,8 @@ from collections import Counter
 from typing import Any, Dict, List, Optional, Union
 
 from lp.services.helpers import english_list
+from lp.snappy.interfaces.snapbase import SnapBaseFeature
+from lp.snappy.model.snapbase import SnapBase
 
 
 class SnapArchitecturesParserError(Exception):
@@ -146,7 +148,7 @@ class SnapBuildInstance:
 
 
 def determine_architectures_to_build(
-snap_base: Optional[str],
+snap_base: Optional[SnapBase],
 snapcraft_data: Dict[str, Any],
 supported_arches: List[str],
 ) -> List[SnapBuildInstance]:
@@ -184,7 +186,11 @@ def determine_architectures_to_build(
 SnapArchitecture(build_on=a) for a in supported_arches
 ]
 
-if snap_base not in {"core22"}:
+allow_duplicate_build_on = (
+snap_base
+and snap_base.features.get(SnapBaseFeature.ALLOW_DUPLICATE_BUILD_ON)
+) or False
+if not allow_duplicate_build_on:
 # Ensure that multiple `build-on` items don't include the same
 # architecture; this is ambiguous and forbidden by snapcraft prior
 # to core22. Checking this here means that we don't get duplicate
diff --git a/lib/lp/snappy/adapters/tests/test_buildarch.py b/lib/lp/snappy/adapters/tests/test_buildarch.py
index db52baf..8a9ef2e 100644
--- a/lib/lp/snappy/adapters/tests/test_buildarch.py
+++ b/lib/lp/snappy/adapters/tests/test_buildarch.py
@@ -11,7 +11,9 @@ from lp.snappy.adapters.buildarch import (
 UnsupportedBuildOnError,
 determine_architectures_to_build,
 )
-from lp.testing import TestCase
+from lp.snappy.interfaces.snapbase import SnapBaseFeature
+from lp.testing import TestCase, TestCaseWithFactory
+from lp.testing.layers import ZopelessDatabaseLayer
 
 
 class TestSnapArchitecture(WithScenarios, TestCase):
@@ -174,11 +176,12 @@ class TestSnapBuildInstanceError(TestCase):
 self.assertEqual(["amd64"], raised.build_on)
 
 
-class TestDetermineArchitecturesToBuild(WithScenarios, TestCase):
-
+class TestDetermineArchitecturesToBuild(WithScenarios, TestCaseWithFactory):
 # Scenarios taken from the architectures document:
 # https://forum.snapcraft.io/t/architectures/4972
 
+layer = ZopelessDatabaseLayer
+
 scenarios = [
 (
 "none",
@@ -396,6 +399,9 @@ class TestDetermineArchitecturesToBuild(WithScenarios, TestCase):
 (
 "multiple build-for for the same build-on",
 {
+"snap_base_features": {
+SnapBaseFeature.ALLOW_DUPLICATE_BUILD_ON: True
+},
 "architectures": [
 {"build-on": "amd64", "build-for": ["amd64"]},
 {"build-on": "amd64", "build-for": ["i386"]},
@@ -418,7 +424,9 @@ class TestDetermineArchitecturesToBuild(WithScenarios, TestCase):
 (
 "multiple build-for for the same build-on: old base",
 {
-"snap_base": "core20",
+"snap_base_features": {
+SnapBaseFeature.ALLOW_DUPLICATE_BUILD_ON: False
+},
 "architectures": [
 {"build-on": "amd64", "build-for": ["amd64"]},
 {"build-on": "amd64", "build-for": ["i386"]},
@@ -431,7 +439,8 @@ class TestDetermineArchitecturesToBuild(WithScenarios, TestCase):
 
 def test_parser(self):
 snapcraft_data = {"architectures": self.architectures}
-snap_base = getattr(self, "snap_base", "core22")
+snap_base_features = getattr(self, "snap_base_features", {})
+snap_base = self.factory.makeSnapBase(features=snap_base_features)
 if hasattr(self, "expected_exception"):
 self.assertRaises(
 self.expected_exception,
diff --git a/lib/lp/snappy/model/snap.py b/lib/lp/snappy/model/snap.py
index 7728ecf..e60040f 100644
--- a/

Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master

2022-10-11 Thread Andrey Fedoseev
More screenshots:

Before:
https://people.canonical.com/~afedoseev/LP-912/before.png

After:
https://people.canonical.com/~afedoseev/LP-912/after.png
-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430983
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master

2022-10-11 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:bug-attachment-url into 
launchpad:master has been updated.

Description changed to:

`libraryfile` field of `BugAttachment` is not optional, an attachment can 
either contain a file, or have a URL

Add `displayed_url` property to `BugAttachment` that contains either a proxied 
attachment file URL, or the URL associated with the attachment.


Improve the `BugAttachment` links:

- Use the formatter API to create the links
- Use different icons depending on the link type: external URL, a patch, a 
downloadable file
- Add rel=nofollow to external URLs

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430983
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master

2022-10-10 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master with 
~andrey-fedoseev/launchpad:bug-attachment-url as a prerequisite.

Commit message:
UCT import/export: handle patch URLs


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431263

Patch URLs are imported as `BugAttachments` with URLs

Attachment title consists of:

1. package name, e.g. "linux"
2. patch type, e.g. "upstream" or "other"
3. optional notes, e.g. "1.5.4"
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222 b/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
index 30574d6..95a74f0 100644
--- a/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
+++ b/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
@@ -30,6 +30,8 @@ CVSS:
 
 Patches_linux:
  break-fix: 457f44363a8894135c85b7a9afd2bd8196db24ab c25b2ae136039ffa820c26138ed4a5e5f3ab3841|local-CVE-2022-23222-fix
+ upstream: https://github.com/389ds/389-ds-base/commit/58dbf084a63e6dbbd999bf6a70475fad8255f26a (1.4.4)
+ upstream: https://github.com/389ds/389-ds-base/commit/2e5b526012612d1d6ccace46398bee679a730271
 upstream_linux: released (5.17~rc1)
 impish_linux: released (5.13.0-37.42)
 devel_linux: not-affected (5.15.0-25.25)
diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
index 00bc2c8..04580b8 100644
--- a/lib/lp/bugs/scripts/tests/test_uct.py
+++ b/lib/lp/bugs/scripts/tests/test_uct.py
@@ -120,7 +120,19 @@ class TestUCTRecord(TestCase):
 "c25b2ae136039ffa820c26138ed4a5e5f3ab3841|"
 "local-CVE-2022-23222-fix"
 ),
-)
+),
+UCTRecord.Patch(
+patch_type="upstream",
+entry=(
+"https://github.com/389ds/389-ds-base/commit/58dbf084a63e6dbbd999bf6a70475fad8255f26a (1.4.4)"  # noqa: 501
+),
+),
+UCTRecord.Patch(
+patch_type="upstream",
+entry=(
+"https://github.com/389ds/389-ds-base/commit/2e5b526012612d1d6ccace46398bee679a730271;  # noqa: 501
+),
+),
 ],
 ),
 UCTRecord.Package(
@@ -260,7 +272,22 @@ class TestCVE(TestCaseWithFactory):
 ],
 priority=None,
 tags=set(),
-patches=[],
+patches=[
+UCTRecord.Patch(
+patch_type="upstream",
+entry=(
+"https://github.com/389ds/389-ds-base/;
+"commit/123 (1.4.4)"
+),
+),
+UCTRecord.Patch(
+patch_type="upstream",
+entry=(
+"https://github.com/389ds/389-ds-base/;
+"commit/456"
+),
+),
+],
 ),
 UCTRecord.Package(
 name=dsp2.sourcepackagename.name,
@@ -417,6 +444,20 @@ class TestCVE(TestCaseWithFactory):
 ),
 ),
 ],
+patch_urls=[
+CVE.PatchURL(
+package_name=dsp1.sourcepackagename,
+type="upstream",
+url="https://github.com/389ds/389-ds-base/; "commit/123",
+notes="1.4.4",
+),
+CVE.PatchURL(
+package_name=dsp1.sourcepackagename,
+type="upstream",
+url="https://github.com/389ds/389-ds-base/; "commit/456",
+notes=None,
+),
+],
 )
 
 def test_make_from_uct_record(self):
@@ -428,6 +469,40 @@ class TestCVE(TestCaseWithFactory):
 self.assertListEqual(self.uct_record.packages, uct_record.packages)
 self.assertDictEqual(self.uct_record.__dict__, uct_record.__dict__)
 
+def test_get_patches(self):
+spn =

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master

2022-10-10 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:uct-import-export-patches into 
launchpad:master has been updated.

Status: Needs review => Superseded

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431262
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master

2022-10-10 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master.

Commit message:
UCT import/export: handle patch URLs


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431262

Patch URLs are imported as `BugAttachments` with URLs

Attachment title consists of:

1. package name, e.g. "linux"
2. patch type, e.g. "upstream" or "other"
3. optional notes, e.g. "1.5.4"
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-export-patches into launchpad:master.
diff --git a/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css b/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css
index e4f4ff3..37487d2 100644
--- a/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css
+++ b/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css
@@ -132,3 +132,9 @@
 padding-right: 0.25em;
 }
 
+/**
+ Attachments portlet
+*/
+.side .portlet .download-attachment {
+word-break: break-word;
+}
diff --git a/lib/lp/bugs/adapters/bugchange.py b/lib/lp/bugs/adapters/bugchange.py
index c7babdc..e97d6e8 100644
--- a/lib/lp/bugs/adapters/bugchange.py
+++ b/lib/lp/bugs/adapters/bugchange.py
@@ -63,7 +63,6 @@ from lp.bugs.interfaces.bugtask import (
 IBugTask,
 )
 from lp.registry.interfaces.product import IProduct
-from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.webapp.publisher import canonical_url
 
 # These are used lp.bugs.model.bugactivity.BugActivity.attribute to normalize
@@ -698,11 +697,6 @@ class BugTagsChange(AttributeChange):
 return {"text": "\n".join(messages)}
 
 
-def download_url_of_bugattachment(attachment):
-"""Return the URL of the ProxiedLibraryFileAlias for the attachment."""
-return ProxiedLibraryFileAlias(attachment.libraryfile, attachment).http_url
-
-
 class BugAttachmentChange(AttributeChange):
 """Used to represent a change to an `IBug`'s attachments."""
 
@@ -712,13 +706,13 @@ class BugAttachmentChange(AttributeChange):
 old_value = None
 new_value = "%s %s" % (
 self.new_value.title,
-download_url_of_bugattachment(self.new_value),
+self.new_value.displayed_url,
 )
 else:
 what_changed = ATTACHMENT_REMOVED
 old_value = "%s %s" % (
 self.old_value.title,
-download_url_of_bugattachment(self.old_value),
+self.old_value.displayed_url,
 )
 new_value = None
 
@@ -737,7 +731,7 @@ class BugAttachmentChange(AttributeChange):
 message = '** %s added: "%s"\n   %s' % (
 attachment_str,
 self.new_value.title,
-download_url_of_bugattachment(self.new_value),
+self.new_value.displayed_url,
 )
 else:
 if self.old_value.is_patch:
@@ -747,7 +741,7 @@ class BugAttachmentChange(AttributeChange):
 message = '** %s removed: "%s"\n   %s' % (
 attachment_str,
 self.old_value.title,
-download_url_of_bugattachment(self.old_value),
+self.old_value.displayed_url,
 )
 
 return {"text": message}
diff --git a/lib/lp/bugs/browser/bug.py b/lib/lp/bugs/browser/bug.py
index 3a675a8..717f39c 100644
--- a/lib/lp/bugs/browser/bug.py
+++ b/lib/lp/bugs/browser/bug.py
@@ -85,7 +85,6 @@ from lp.registry.interfaces.person import IPersonSet
 from lp.services.compat import message_as_bytes
 from lp.services.features import getFeatureFlag
 from lp.services.fields import DuplicateBug
-from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.mail.mailwrapper import MailWrapper
 from lp.services.propertycache import cachedproperty
 from lp.services.searchbuilder import any, not_equals
@@ -534,17 +533,11 @@ class BugViewMixin:
 "other": [],
 }
 for attachment in self.context.attachments_unpopulated:
-info = {
-"attachment": attachment,
-"file": ProxiedLibraryFileAlias(
-attachment.libraryfile, attachment
-),
-}
 if attachment.type == BugAttachmentType.PATCH:
 key = attachment.type
 else:
 key = "other"
-result[key].append(info)
+result[key].append(attachment)
 return result
 
 @property
@@ -636,12 +629,6 

Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-base-features into launchpad:master

2022-10-07 Thread Andrey Fedoseev
This is a new nullable column that's been added recently

On Fri, Oct 7, 2022, 11:59 Jürgen Gmach 
wrote:

> How did they land in the database in the first place?
>
> Could we convert them to empty dicts?
> --
>
> https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431181
> You are the owner of ~andrey-fedoseev/launchpad:snap-base-features.
>
>

-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431181
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-base-features into launchpad:master

2022-10-06 Thread Andrey Fedoseev
None is an existing value in the database that we need to account for.

On Fri, Oct 7, 2022, 11:17 Jürgen Gmach 
wrote:

> I do not know what a SnapBase is, and the docstring for ISnapBase isn't
> helpful at all ("A base for snaps."), but I still wonder whether we could
> initialize `features` as an empty dict, so we could save us those `is None`
> checks.
> --
>
> https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431181
> You are the owner of ~andrey-fedoseev/launchpad:snap-base-features.
>
>

-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431181
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-base-features into launchpad:master

2022-10-06 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.

Commit message:
Fix the case when `SnapBase.feature` is `None`

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431181
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.
diff --git a/lib/lp/snappy/model/snapbase.py b/lib/lp/snappy/model/snapbase.py
index b6e8b33..a67159b 100644
--- a/lib/lp/snappy/model/snapbase.py
+++ b/lib/lp/snappy/model/snapbase.py
@@ -74,7 +74,7 @@ class SnapBase(Storm):
 
 is_default = Bool(name="is_default", allow_none=False)
 
-_features = PgJSON(name="features", allow_none=False)
+_features = PgJSON(name="features", allow_none=True)
 
 def __init__(
 self,
@@ -98,6 +98,8 @@ class SnapBase(Storm):
 
 @property
 def features(self) -> Dict[Item, bool]:
+if self._features is None:
+return {}
 features = {}
 for token, is_enabled in self._features.items():
 try:
diff --git a/lib/lp/snappy/tests/test_snapbase.py b/lib/lp/snappy/tests/test_snapbase.py
index 978e8b6..e7cd522 100644
--- a/lib/lp/snappy/tests/test_snapbase.py
+++ b/lib/lp/snappy/tests/test_snapbase.py
@@ -93,6 +93,11 @@ class TestSnapBase(TestCaseWithFactory):
 snap_base.features,
 )
 
+def test_blank_features(self):
+snap_base = self.factory.makeSnapBase(name="foo")
+removeSecurityProxy(snap_base)._features = None
+self.assertEqual({}, snap_base.features)
+
 
 class TestSnapBaseProcessors(TestCaseWithFactory):
 
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-fix-cve-discoverer-sampledata into launchpad:db-devel

2022-10-06 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-fix-cve-discoverer-sampledata into 
launchpad:db-devel.

Commit message:
Remove `cve.discoverer` from sampledata

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/43
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-fix-cve-discoverer-sampledata into 
launchpad:db-devel.
diff --git a/database/sampledata/current-dev.sql b/database/sampledata/current-dev.sql
index 6137bec..1a12d10 100644
--- a/database/sampledata/current-dev.sql
+++ b/database/sampledata/current-dev.sql
@@ -1301,16 +1301,16 @@ ALTER TABLE public.bug ENABLE TRIGGER ALL;
 
 ALTER TABLE public.cve DISABLE TRIGGER ALL;
 
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (1, '1999-8979', 2, 'Firefox crashes all the time', '2005-09-07 19:00:32.944561', '2005-09-13 14:00:03.508959', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (2, '1999-2345', 1, 'Possible data loss', '2005-09-07 19:00:32.944561', '2005-09-13 14:00:03.513099', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (3, '2005-2730', 1, 'The HTTP proxy in Astaro Security Linux 6.0 allows remote attackers to obtain sensitive information via an invalid request, which reveals a Proxy-authorization string in an error message.', '2005-09-13 14:05:15.669384', '2005-09-13 14:05:15.669384', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (4, '2005-2731', 1, 'Directory traversal vulnerability in Astaro Security Linux 6.0, when using Webmin, allows remote authenticated webmin users to read arbitrary files via a ..  (dot dot) in the wfe_download parameter to index.fpl.', '2005-09-13 14:05:15.91729', '2005-09-13 14:05:15.91729', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (5, '2005-2732', 1, 'AWStats 6.4, and possibly earlier versions, allows remote attackers to obtain sensitive information via a file that does not exist in the config parameter, which reveals the path in an error message.', '2005-09-13 14:05:15.992007', '2005-09-13 14:05:15.992007', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (6, '2005-2733', 1, 'upload_img_cgi.php in Simple PHP Blog (SPHPBlog) does not properly restrict file extensions of uploaded files, which could allow remote attackers to execute arbitrary code.', '2005-09-13 14:05:16.072418', '2005-09-13 14:05:16.072418', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (7, '2005-2734', 1, 'Cross-site scripting (XSS) vulnerability in Gallery 1.5.1-RC2 and earlier allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:16.202393', '2005-09-13 14:05:16.202393', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (8, '2005-2735', 1, 'Cross-site scripting (XSS) vulnerability in phpGraphy 0.9.9a and earlier allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:16.412226', '2005-09-13 14:05:16.412226', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (9, '2005-2736', 1, 'Cross-site scripting (XSS) vulnerability in YaPig 0.95 and earlier allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:16.841572', '2005-09-13 14:05:16.841572', NULL, NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss, discovered_by) VALUES (10, '2005-2737', 1, 'Cross-site scripting (XSS) vulnerability in PhotoPost PHP Pro 5.1 allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:17.043865', '2005-09-13 14:05:17.043865', NULL, NULL

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:fix-cvereport into launchpad:master

2022-10-05 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:fix-cvereport 
into launchpad:master.

Commit message:
CVEReportView: use lazy loading for `open_cve_bugtasks` and 
`resolved_cve_bugtasks`


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431036

Previously, these attributes were computed on view initialization, with the 
exception of the case when the context is a Distribution with no series.

Now, the attributes are always available, regardless of the context, but are 
computed on demand, when they are actually used.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:fix-cvereport into launchpad:master.
diff --git a/lib/lp/bugs/browser/cvereport.py b/lib/lp/bugs/browser/cvereport.py
index 393cd91..e2f2f7d 100644
--- a/lib/lp/bugs/browser/cvereport.py
+++ b/lib/lp/bugs/browser/cvereport.py
@@ -8,15 +8,17 @@ __all__ = [
 "CVEReportView",
 ]
 
+from typing import List, NamedTuple
+
 from zope.component import getUtility
 
 from lp.bugs.browser.buglisting import BugTaskListingItem
 from lp.bugs.interfaces.bugtask import RESOLVED_BUGTASK_STATUSES, IBugTaskSet
 from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
 from lp.bugs.interfaces.cve import ICveSet
-from lp.registry.interfaces.distribution import IDistribution
 from lp.registry.interfaces.person import IPersonSet
 from lp.services.helpers import shortlist
+from lp.services.propertycache import cachedproperty
 from lp.services.webapp import LaunchpadView
 from lp.services.webapp.escaping import structured
 from lp.services.webapp.publisher import canonical_url
@@ -37,6 +39,15 @@ class BugTaskCve:
 return self.bugtasks[0].bug
 
 
+BugTaskCves = NamedTuple(
+"BugTaskCves",
+(
+("open", List[BugTaskCve]),
+("resolved", List[BugTaskCve]),
+),
+)
+
+
 def get_cve_display_data(cve):
 """Return the data we need for display for the given CVE."""
 return {
@@ -63,18 +74,18 @@ class CVEReportView(LaunchpadView):
 """Update the search params for the context for a specific view."""
 raise NotImplementedError
 
-def initialize(self):
-"""See `LaunchpadView`."""
-super().initialize()
-self.open_cve_bugtasks = []
-self.resolved_cve_bugtasks = []
+@property
+def open_cve_bugtasks(self) -> List[BugTaskCve]:
+return self._bugtaskcves.open
 
-# If we are dealing with a distribution with one or more series,
-# there is no need to deal with the open and resolved CVE bugtasks.
-# This is because the template only renders links to the CVE report
-# page of each available series.
-if IDistribution.providedBy(self.context) and self.context.series:
-return
+@property
+def resolved_cve_bugtasks(self) -> List[BugTaskCve]:
+return self._bugtaskcves.resolved
+
+@cachedproperty
+def _bugtaskcves(self) -> BugTaskCves:
+
+bugtaskcves = BugTaskCves(open=[], resolved=[])
 
 search_params = BugTaskSearchParams(self.user, has_cve=True)
 bugtasks = shortlist(
@@ -82,7 +93,7 @@ class CVEReportView(LaunchpadView):
 )
 
 if not bugtasks:
-return
+return bugtaskcves
 
 bugtask_set = getUtility(IBugTaskSet)
 badge_properties = bugtask_set.getBugTaskBadgeProperties(bugtasks)
@@ -121,13 +132,13 @@ class CVEReportView(LaunchpadView):
 
 # Order the dictionary items by bug ID and then store only the
 # bugtaskcve objects.
-self.open_cve_bugtasks = [
+bugtaskcves.open.extend(
 bugtaskcve for bug, bugtaskcve in sorted(open_bugtaskcves.items())
-]
-self.resolved_cve_bugtasks = [
+)
+bugtaskcves.resolved.extend(
 bugtaskcve
 for bug, bugtaskcve in sorted(resolved_bugtaskcves.items())
-]
+)
 
 # The page contains links to the bug task assignees:
 # Pre-load the related Person and ValidPersonCache records
@@ -138,6 +149,8 @@ class CVEReportView(LaunchpadView):
 )
 )
 
+return bugtaskcves
+
 def renderCVELinks(self, cves):
 """Render the CVE links related to the given bug.
 
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-bug-attachment-url into launchpad:db-devel

2022-10-05 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-bug-attachment-url into launchpad:db-devel.

Commit message:
Add `BugAttachment.url` field


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/431023

The `BugAttachment.libraryfile` is now optional

A BugAttachment can either contain a file, or an external URL
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-bug-attachment-url into launchpad:db-devel.
diff --git a/database/schema/patch-2211-11-0.sql b/database/schema/patch-2211-11-0.sql
new file mode 100644
index 000..64c4a0e
--- /dev/null
+++ b/database/schema/patch-2211-11-0.sql
@@ -0,0 +1,13 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE BugAttachment
+ALTER COLUMN libraryfile drop not null,
+ADD COLUMN url text;
+
+COMMENT ON COLUMN BugAttachment.url
+IS 'External URL of the attachment.';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 11, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master

2022-10-04 Thread Andrey Fedoseev
Some screenshots:

https://people.canonical.com/~afedoseev/LP-912/Screenshot_20221004_195626.png
https://people.canonical.com/~afedoseev/LP-912/Screenshot_20221004_195659.png
https://people.canonical.com/~afedoseev/LP-912/Screenshot_20221004_195724.png
-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430983
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master

2022-10-04 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master.

Commit message:
Add `url` to `BugAttachment`


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430983

`libraryfile` field of `BugAttachment` is not optional, an attachment can 
either contain a file, or have a URL

Add `displayed_url` property to `BugAttachment` that contains either a proxied 
attachment file URL, or the URL associated with the attachment.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:bug-attachment-url into launchpad:master.
diff --git a/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css b/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css
index e4f4ff3..37487d2 100644
--- a/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css
+++ b/lib/canonical/launchpad/icing/css/components/sidebar_portlets.css
@@ -132,3 +132,9 @@
 padding-right: 0.25em;
 }
 
+/**
+ Attachments portlet
+*/
+.side .portlet .download-attachment {
+word-break: break-word;
+}
diff --git a/lib/lp/bugs/adapters/bugchange.py b/lib/lp/bugs/adapters/bugchange.py
index c7babdc..e97d6e8 100644
--- a/lib/lp/bugs/adapters/bugchange.py
+++ b/lib/lp/bugs/adapters/bugchange.py
@@ -63,7 +63,6 @@ from lp.bugs.interfaces.bugtask import (
 IBugTask,
 )
 from lp.registry.interfaces.product import IProduct
-from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.webapp.publisher import canonical_url
 
 # These are used lp.bugs.model.bugactivity.BugActivity.attribute to normalize
@@ -698,11 +697,6 @@ class BugTagsChange(AttributeChange):
 return {"text": "\n".join(messages)}
 
 
-def download_url_of_bugattachment(attachment):
-"""Return the URL of the ProxiedLibraryFileAlias for the attachment."""
-return ProxiedLibraryFileAlias(attachment.libraryfile, attachment).http_url
-
-
 class BugAttachmentChange(AttributeChange):
 """Used to represent a change to an `IBug`'s attachments."""
 
@@ -712,13 +706,13 @@ class BugAttachmentChange(AttributeChange):
 old_value = None
 new_value = "%s %s" % (
 self.new_value.title,
-download_url_of_bugattachment(self.new_value),
+self.new_value.displayed_url,
 )
 else:
 what_changed = ATTACHMENT_REMOVED
 old_value = "%s %s" % (
 self.old_value.title,
-download_url_of_bugattachment(self.old_value),
+self.old_value.displayed_url,
 )
 new_value = None
 
@@ -737,7 +731,7 @@ class BugAttachmentChange(AttributeChange):
 message = '** %s added: "%s"\n   %s' % (
 attachment_str,
 self.new_value.title,
-download_url_of_bugattachment(self.new_value),
+self.new_value.displayed_url,
 )
 else:
 if self.old_value.is_patch:
@@ -747,7 +741,7 @@ class BugAttachmentChange(AttributeChange):
 message = '** %s removed: "%s"\n   %s' % (
 attachment_str,
 self.old_value.title,
-download_url_of_bugattachment(self.old_value),
+self.old_value.displayed_url,
 )
 
 return {"text": message}
diff --git a/lib/lp/bugs/browser/bug.py b/lib/lp/bugs/browser/bug.py
index 3a675a8..717f39c 100644
--- a/lib/lp/bugs/browser/bug.py
+++ b/lib/lp/bugs/browser/bug.py
@@ -85,7 +85,6 @@ from lp.registry.interfaces.person import IPersonSet
 from lp.services.compat import message_as_bytes
 from lp.services.features import getFeatureFlag
 from lp.services.fields import DuplicateBug
-from lp.services.librarian.browser import ProxiedLibraryFileAlias
 from lp.services.mail.mailwrapper import MailWrapper
 from lp.services.propertycache import cachedproperty
 from lp.services.searchbuilder import any, not_equals
@@ -534,17 +533,11 @@ class BugViewMixin:
 "other": [],
 }
 for attachment in self.context.attachments_unpopulated:
-info = {
-"attachment": attachment,
-"file": ProxiedLibraryFileAlias(
-attachment.libraryfile, attachment
-),
-}
 if attachment.type == BugAttachmentType.PATCH:
 key = attachment.type
 else:
 key = "other"
-result[key].append(info)
+result[key].append(attachment)
 return result
 
 @property
@@ -636,12 +629,6

Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-remove-cve-discoverer into launchpad:db-devel

2022-09-29 Thread Andrey Fedoseev
> On its own I cannot approve this MP. Could you please link to the related MPs?

Here you go 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430020
-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430631
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-remove-cve-discoverer into launchpad:db-devel.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-remove-cve-discoverer into launchpad:db-devel

2022-09-28 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-remove-cve-discoverer into launchpad:db-devel.

Commit message:
Drop `Cve.discoverer` column

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430631

It is superseded by `Cve.discovered_by`
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-remove-cve-discoverer into launchpad:db-devel.
diff --git a/database/schema/patch-2211-09-0.sql b/database/schema/patch-2211-09-0.sql
new file mode 100644
index 000..819f866
--- /dev/null
+++ b/database/schema/patch-2211-09-0.sql
@@ -0,0 +1,9 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE Cve
+DROP COLUMN discoverer;
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 09, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:cve-discovered-by into launchpad:master

2022-09-26 Thread Andrey Fedoseev
> How do we handle PII removal in this case?

We discussed that with Colin and William and agreed to compromise on that.


-- 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430020
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:cve-discovered-by into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:merge-db-stable into launchpad:master

2022-09-20 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:merge-db-stable into 
launchpad:master has been updated.

Status: Needs review => Approved

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430135
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:merge-db-stable into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:merge-db-stable into launchpad:master

2022-09-20 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:merge-db-stable 
into launchpad:master.

Commit message:
Merge db-stable 69e0f179a17c9cb5507f4b23172ef62eff321efe (Add 
`SnapBase.features` column, Add `Cve.discovered_by` column)

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430135
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:merge-db-stable into launchpad:master.
diff --git a/database/schema/patch-2211-06-0.sql b/database/schema/patch-2211-06-0.sql
new file mode 100644
index 000..b58d4ea
--- /dev/null
+++ b/database/schema/patch-2211-06-0.sql
@@ -0,0 +1,13 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE SnapBase
+ADD COLUMN features jsonb;
+;
+
+COMMENT ON COLUMN SnapBase.features
+IS 'The features supported by this base.';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 06, 0);
diff --git a/database/schema/patch-2211-07-0.sql b/database/schema/patch-2211-07-0.sql
new file mode 100644
index 000..1cbcad4
--- /dev/null
+++ b/database/schema/patch-2211-07-0.sql
@@ -0,0 +1,12 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE Cve
+ADD COLUMN discovered_by text;
+
+COMMENT ON COLUMN Cve.discovered_by
+IS 'The name of person(s) or organization that discovered the CVE';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 07, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:packaging-security into launchpad:master

2022-09-20 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:packaging-security into launchpad:master.

Commit message:
Fix another failing test caused by the recent changes in `Packaging` security

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430130
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:packaging-security into launchpad:master.
diff --git a/lib/lp/code/model/tests/test_branchtarget.py b/lib/lp/code/model/tests/test_branchtarget.py
index 1b74d7a..b73a527 100644
--- a/lib/lp/code/model/tests/test_branchtarget.py
+++ b/lib/lp/code/model/tests/test_branchtarget.py
@@ -434,9 +434,10 @@ class TestProductBranchTarget(TestCaseWithFactory, BaseBranchTargetTests):
 # Packages that are linked to the products are mergeable.
 branch = self.factory.makePackageBranch()
 # Link it up.
-branch.sourcepackage.setPackaging(
-self.original.development_focus, branch.owner
-)
+with person_logged_in(branch.sourcepackage.owner):
+branch.sourcepackage.setPackaging(
+self.original.development_focus, branch.owner
+)
 self.assertTrue(self.target.areBranchesMergeable(branch.target))
 
 def test_default_merge_target(self):
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:packaging-security into launchpad:master

2022-09-19 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:packaging-security into launchpad:master.

Commit message:
Fix the failing tests caused by the recent changes in `Packaging` security

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430124
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:packaging-security into launchpad:master.
diff --git a/lib/lp/answers/browser/tests/test_questiontarget.py b/lib/lp/answers/browser/tests/test_questiontarget.py
index 5a289c0..b9a8bd2 100644
--- a/lib/lp/answers/browser/tests/test_questiontarget.py
+++ b/lib/lp/answers/browser/tests/test_questiontarget.py
@@ -180,9 +180,10 @@ class TestSearchQuestionsViewUnknown(TestCaseWithFactory):
 self.factory.makeSourcePackagePublishingHistory(
 sourcepackagename=sourcepackagename, distroseries=hoary
 )
-product.development_focus.setPackaging(
-hoary, sourcepackagename, product.owner
-)
+with person_logged_in(product.development_focus.owner):
+product.development_focus.setPackaging(
+hoary, sourcepackagename, product.owner
+)
 
 def setUp(self):
 super().setUp()
diff --git a/lib/lp/code/model/tests/test_branchtarget.py b/lib/lp/code/model/tests/test_branchtarget.py
index 19c3fb4..1b74d7a 100644
--- a/lib/lp/code/model/tests/test_branchtarget.py
+++ b/lib/lp/code/model/tests/test_branchtarget.py
@@ -180,9 +180,10 @@ class TestPackageBranchTarget(TestCaseWithFactory, BaseBranchTargetTests):
 # Products that are linked to the packages are mergeable.
 branch = self.factory.makeProductBranch()
 # Link it up.
-self.original.setPackaging(
-branch.product.development_focus, branch.owner
-)
+with person_logged_in(self.original.owner):
+self.original.setPackaging(
+branch.product.development_focus, branch.owner
+)
 self.assertTrue(self.target.areBranchesMergeable(branch.target))
 
 def test_default_merge_target(self):
diff --git a/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst b/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst
index 3b380bb..bc7a550 100644
--- a/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst
+++ b/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst
@@ -172,6 +172,7 @@ It will thus not be listed in the "...other untrusted versions of..." portlet.
 A /$DISTRO/+source/$PACKAGE page shows an overview of a source package in
 a distribution.  There are several sections of information.
 
+>>> user_browser = setupBrowser(auth="Basic l...@plone.org:test")
 >>> user_browser.open("http://launchpad.test/ubuntu/+source/iceweasel/;)
 
 The page has an appropriate title and main heading.
@@ -331,6 +332,7 @@ menu, and a "Subscribers" portlet.
 View full change log
 Subscribe to bug mail
 Edit bug mail
+Configure bug tracker
 
 >>> print(
 ... extract_text(find_tag_by_id(user_browser.contents, "involvement"))
@@ -361,9 +363,9 @@ distroseries.  The distroseries are presented in order, most recent first.
 
 >>> browser.open("http://launchpad.test/ubuntutest/+source/netapplet/;)
 >>> print(extract_text(find_tag_by_id(browser.contents, "packages_list")))
-Mock Hoary (active development)   Set upstream link
+Mock Hoary (active development)
   1.0.1a  release  (main)  ...
-Breezy Badger Autotest  (active development)  Set upstream link
+Breezy Badger Autotest  (active development)
   1.3.1   release  (main)  ...
 
 (See more about packaging in:
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 9965749..3ebd99c 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -1389,6 +1389,7 @@ class LaunchpadObjectFactory(ObjectFactory):
 sourcepackage=None,
 distroseries=None,
 sourcepackagename=None,
+owner=None,
 **kwargs
 ):
 """Make a package branch on an arbitrary package.
@@ -1407,9 +1408,13 @@ class LaunchpadObjectFactory(ObjectFactory):
 ), "Don't pass in both sourcepackage and sourcepackagename"
 if sourcepackage is None:
 sourcepackage = self.makeSourcePackage(
-sourcepackagename=sourcepackagename, distroseries=distroseries
+sourcepackagename=sourcepackagename,
+distroseries=distroseries,
+owner=owner,
 )
-return self.makeBranch(sourcepackage=sourcepackage, **kwargs)
+return self.makeBranch(
+sourcepackage=sourcepackage, owner=owner, **kwar

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:cve-discovered-by into launchpad:master

2022-09-16 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:cve-discovered-by into launchpad:master.

Commit message:
Replace `Cve.discoverer` with `discovered_by`

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/430020

`Cve.discoverer` is a reference to a `Person`, but it doesn't really work with 
the real data in Ubuntu CVE Tracker.

In UCT, `Discovered-By` is a free-form field which usually contains name of one 
or more people or an organization name which is impossible to map to a `Person`.

We agreed that a plain text field would work better for this case.


UCT import/export: handle the `cve.discovered_by` field
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:cve-discovered-by into launchpad:master.
diff --git a/database/sampledata/current-dev.sql b/database/sampledata/current-dev.sql
index ae1f035..2d95651 100644
--- a/database/sampledata/current-dev.sql
+++ b/database/sampledata/current-dev.sql
@@ -3257,16 +3257,16 @@ ALTER TABLE public.customlanguagecode ENABLE TRIGGER ALL;
 
 ALTER TABLE public.cve DISABLE TRIGGER ALL;
 
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (1, '1999-8979', 2, 'Firefox crashes all the time', '2005-09-07 19:00:32.944561', '2005-09-13 14:00:03.508959', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (2, '1999-2345', 1, 'Possible data loss', '2005-09-07 19:00:32.944561', '2005-09-13 14:00:03.513099', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (3, '2005-2730', 1, 'The HTTP proxy in Astaro Security Linux 6.0 allows remote attackers to obtain sensitive information via an invalid request, which reveals a Proxy-authorization string in an error message.', '2005-09-13 14:05:15.669384', '2005-09-13 14:05:15.669384', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (4, '2005-2731', 1, 'Directory traversal vulnerability in Astaro Security Linux 6.0, when using Webmin, allows remote authenticated webmin users to read arbitrary files via a ..  (dot dot) in the wfe_download parameter to index.fpl.', '2005-09-13 14:05:15.91729', '2005-09-13 14:05:15.91729', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (5, '2005-2732', 1, 'AWStats 6.4, and possibly earlier versions, allows remote attackers to obtain sensitive information via a file that does not exist in the config parameter, which reveals the path in an error message.', '2005-09-13 14:05:15.992007', '2005-09-13 14:05:15.992007', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (6, '2005-2733', 1, 'upload_img_cgi.php in Simple PHP Blog (SPHPBlog) does not properly restrict file extensions of uploaded files, which could allow remote attackers to execute arbitrary code.', '2005-09-13 14:05:16.072418', '2005-09-13 14:05:16.072418', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (7, '2005-2734', 1, 'Cross-site scripting (XSS) vulnerability in Gallery 1.5.1-RC2 and earlier allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:16.202393', '2005-09-13 14:05:16.202393', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (8, '2005-2735', 1, 'Cross-site scripting (XSS) vulnerability in phpGraphy 0.9.9a and earlier allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:16.412226', '2005-09-13 14:05:16.412226', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (9, '2005-2736', 1, 'Cross-site scripting (XSS) vulnerability in YaPig 0.95 and earlier allows remote attackers to inject arbitrary web script or HTML via EXIF data, such as the Camera Model Tag.', '2005-09-13 14:05:16.841572', '2005-09-13 14:05:16.841572', NULL, NULL, NULL, NULL);
-INSERT INTO public.cve (id, sequence, status, description, datecreated, datemodified, fti, date_made_public, discoverer, cvss) VALUES (10, '2005-2737', 1, 'Cross-site scripting (XSS) vulnerability in PhotoPost PHP

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-cve-discovered-by into launchpad:db-devel

2022-09-15 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-cve-discovered-by into launchpad:db-devel.

Commit message:
Add `Cve.discovered_by` column


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429958

It contains the name of person(s) or organization that discovered the CVE

This supersedes the existing `discoverer` column which is a reference to a 
`Person`
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-cve-discovered-by into launchpad:db-devel.
diff --git a/database/schema/patch-2211-07-0.sql b/database/schema/patch-2211-07-0.sql
new file mode 100644
index 000..1cbcad4
--- /dev/null
+++ b/database/schema/patch-2211-07-0.sql
@@ -0,0 +1,12 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE Cve
+ADD COLUMN discovered_by text;
+
+COMMENT ON COLUMN Cve.discovered_by
+IS 'The name of person(s) or organization that discovered the CVE';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 07, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-base-features into launchpad:master

2022-09-14 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.

Commit message:
Add `ISnapBase.features` field


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429878

The field is used to designate the features available for a snap base
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-base-features into launchpad:master.
diff --git a/lib/lp/snappy/interfaces/snapbase.py b/lib/lp/snappy/interfaces/snapbase.py
index 08cfd79..8fdc1f4 100644
--- a/lib/lp/snappy/interfaces/snapbase.py
+++ b/lib/lp/snappy/interfaces/snapbase.py
@@ -8,6 +8,8 @@ __all__ = [
 "ISnapBase",
 "ISnapBaseSet",
 "NoSuchSnapBase",
+"ALLOW_DUPLICATE_BUILD_ON",
+"SNAP_BASE_KNOWN_FEATURES",
 ]
 
 import http.client
@@ -74,6 +76,10 @@ class SnapBaseNameField(ContentNameField):
 return None
 
 
+ALLOW_DUPLICATE_BUILD_ON = "allow_duplicate_build_on"
+SNAP_BASE_KNOWN_FEATURES = {ALLOW_DUPLICATE_BUILD_ON}
+
+
 class ISnapBaseView(Interface):
 """`ISnapBase` attributes that anyone can view."""
 
@@ -181,6 +187,20 @@ class ISnapBaseEditableAttributes(Interface):
 )
 )
 
+features = exported(
+Dict(
+title=_("Features supported by this base"),
+key_type=TextLine(),
+required=False,
+readonly=False,
+description=_(
+"A dictionary designating the features supported by the base. "
+"Key is the name of a feature, value is a boolean indicating "
+"whether the feature is supported or not."
+),
+)
+)
+
 
 class ISnapBaseEdit(Interface):
 """`ISnapBase` methods that require launchpad.Edit permission."""
@@ -263,7 +283,14 @@ class ISnapBaseSetEdit(Interface):
 )
 )
 @export_factory_operation(
-ISnapBase, ["name", "display_name", "distro_series", "build_channels"]
+ISnapBase,
+[
+"name",
+"display_name",
+"distro_series",
+"build_channels",
+"features",
+],
 )
 @operation_for_version("devel")
 def new(
@@ -272,6 +299,7 @@ class ISnapBaseSetEdit(Interface):
 display_name,
 distro_series,
 build_channels,
+features,
 processors=None,
 date_created=None,
 ):
diff --git a/lib/lp/snappy/model/snapbase.py b/lib/lp/snappy/model/snapbase.py
index f87a3e6..e92f91a 100644
--- a/lib/lp/snappy/model/snapbase.py
+++ b/lib/lp/snappy/model/snapbase.py
@@ -7,7 +7,10 @@ __all__ = [
 "SnapBase",
 ]
 
+from typing import Dict, Optional
+
 import pytz
+from storm.databases.postgres import JSON as PgJSON
 from storm.locals import (
 JSON,
 Bool,
@@ -29,6 +32,7 @@ from lp.registry.model.person import Person
 from lp.services.database.constants import DEFAULT
 from lp.services.database.interfaces import IMasterStore, IStore
 from lp.snappy.interfaces.snapbase import (
+SNAP_BASE_KNOWN_FEATURES,
 CannotDeleteSnapBase,
 ISnapBase,
 ISnapBaseSet,
@@ -69,6 +73,8 @@ class SnapBase(Storm):
 
 is_default = Bool(name="is_default", allow_none=False)
 
+_features = PgJSON(name="features", allow_none=False)
+
 def __init__(
 self,
 registrant,
@@ -76,6 +82,7 @@ class SnapBase(Storm):
 display_name,
 distro_series,
 build_channels,
+features,
 date_created=DEFAULT,
 ):
 super().__init__()
@@ -85,8 +92,25 @@ class SnapBase(Storm):
 self.distro_series = distro_series
 self.build_channels = build_channels
 self.date_created = date_created
+self.features = features
 self.is_default = False
 
+@property
+def features(self) -> Dict[str, bool]:
+return {
+k: v
+for k, v in (self._features or {}).items()
+if k in SNAP_BASE_KNOWN_FEATURES
+}
+
+@features.setter
+def features(self, value: Optional[Dict[str, bool]]) -> None:
+self._features = {
+k: v
+for k, v in (value or {}).items()
+if k in SNAP_BASE_KNOWN_FEATURES
+}
+
 def _getProcessors(self):
 return list(
 Store.of(self).find(
@@ -217,6 +241,7 @@ class SnapBaseSet:
 display_name,
 distro_series,
 build_channels,
+features,
 processors=None,
 date_created=DEFAULT,
 ):
@@ -228,6 +253,7 @@ class SnapBaseSet:
 display

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-snap-base-features into launchpad:db-devel

2022-09-13 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-snap-base-features into launchpad:db-devel.

Commit message:
Add `SnapBase.features` column


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429817

The column is used to designate the features available for a snap base
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-snap-base-features into launchpad:db-devel.
diff --git a/database/schema/patch-2211-06-0.sql b/database/schema/patch-2211-06-0.sql
new file mode 100644
index 000..b58d4ea
--- /dev/null
+++ b/database/schema/patch-2211-06-0.sql
@@ -0,0 +1,13 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE SnapBase
+ADD COLUMN features jsonb;
+;
+
+COMMENT ON COLUMN SnapBase.features
+IS 'The features supported by this base.';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 06, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:packaging-security into launchpad:master

2022-09-12 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:packaging-security into launchpad:master.

Commit message:
New security model for `Packaging`

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429758

Only the product owners, package maintainers, admins and registry experts are 
now allowed to create, edit or remove package links

- {IProductSeries,ISourcePackage}.setPackaging is now protected with 
`launchpad.Edit` permission

- `launchpad.Edit` on `IPackaging`: True if user has `launchpad.Edit` on either 
corresponding `IProductSeries` or `ISourcePackage`

- /+ubuntupkg on `IProductSeries` is now protected with `launchpad.Edit`

- /+edit-packaging on `ISourcePackage` is now protected with `launchpad.Edit`

- /+remove-packaging on `ISourcePackage` is protected with `launchpad.Edit` 
applied to `sourcepackage.direct_packaging`; this allows product owners to 
unlink their products

- all tests are updated accordingly
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:packaging-security into launchpad:master.
diff --git a/lib/lp/registry/browser/configure.zcml b/lib/lp/registry/browser/configure.zcml
index 6f041d4..b90507b 100644
--- a/lib/lp/registry/browser/configure.zcml
+++ b/lib/lp/registry/browser/configure.zcml
@@ -2022,7 +2022,7 @@
 name="+ubuntupkg"
 for="lp.registry.interfaces.productseries.IProductSeries"
 class="lp.registry.browser.productseries.ProductSeriesUbuntuPackagingView"
-permission="launchpad.AnyPerson"
+permission="launchpad.Edit"
 template="../templates/productseries-ubuntupkg.pt"
 />
 
 >> _ = login_person(product.owner)
 >>> view = create_view(productseries, "+ubuntupkg")
 >>> print(view.label)
 Ubuntu source packaging
@@ -200,8 +201,7 @@ and a new entry can be added to the packaging history.
 ... )
 >>> grumpy_series.status = SeriesStatus.FROZEN
 
->>> a_user = factory.makePerson(name="hedgehog")
->>> ignored = login_person(a_user)
+>>> _ = login_person(product.owner)
 >>> form = {
 ... "field.sourcepackagename": "hot",
 ... "field.actions.continue": "Update",
diff --git a/lib/lp/registry/browser/tests/sourcepackage-views.rst b/lib/lp/registry/browser/tests/sourcepackage-views.rst
index b759ece..b3d2265 100644
--- a/lib/lp/registry/browser/tests/sourcepackage-views.rst
+++ b/lib/lp/registry/browser/tests/sourcepackage-views.rst
@@ -53,7 +53,9 @@ This is a multistep view. In the first step, the product is specified.
 >>> print(view.view.request.form)
 {'field.__visited_steps__': 'sourcepackage_change_upstream_step1'}
 
->>> ignored = login_person(product.owner)
+>>> from lp.registry.interfaces.person import IPersonSet
+>>> admin = getUtility(IPersonSet).getByEmail("ad...@canonical.com")
+>>> _ = login_person(admin)
 >>> form = {
 ... "field.product": "bonkers",
 ... "field.actions.continue": "Continue",
@@ -63,7 +65,7 @@ This is a multistep view. In the first step, the product is specified.
 ... package,
 ... name="+edit-packaging",
 ... form=form,
-... principal=product.owner,
+... principal=admin,
 ... )
 >>> view.view.errors
 []
@@ -88,7 +90,7 @@ product can be chosen from a list of options.
 ... package,
 ... name="+edit-packaging",
 ... form=form,
-... principal=product.owner,
+... principal=admin,
 ... )
 
 >>> ignored = view.view.render()
@@ -124,7 +126,7 @@ then the current product series will be the selected option.
 ... package,
 ... name="+edit-packaging",
 ... form=form,
-... principal=product.owner,
+... principal=admin,
 ... )
 >>> print(view.view.widgets.get("productseries")._getFormValue().name)
 crazy
@@ -141,7 +143,7 @@ empty.
 ... package,
 ... name="+edit-packaging",
 ... form=form,
-... principal=product.owner,
+... principal=admin,
 ... )
 >>> for error in view.view.errors:
 ... print(pretty(error.args))
@@ -161,7 +163,7 @@ but there is no notification message that the upstream link was updated.
 ... package,
 ... name="+edit-packaging",
 ... form=form,
-... principal=product.owner,
+... principal=admin,
 ... )
 >>> print(view.view)
 <...SourcePackageChangeU

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-directory into launchpad:master

2022-08-30 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-directory into launchpad:master.

Commit message:
UCT import: allow importing from a directory

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429130
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-directory into launchpad:master.
diff --git a/scripts/uct-import.py b/scripts/uct-import.py
index 5a37c77..946c484 100755
--- a/scripts/uct-import.py
+++ b/scripts/uct-import.py
@@ -5,17 +5,25 @@
 import _pythonpath  # noqa: F401
 
 import logging
+import re
 from pathlib import Path
 
 from lp.bugs.scripts.uct import UCTImporter
 from lp.services.scripts.base import LaunchpadScript
 
+CVE_RE = re.compile(r"^CVE-\d\d\d\d-[N\d]{4,7}$")
+
+
+logger = logging.getLogger(__name__)
+
 
 class UCTImportScript(LaunchpadScript):
 
-usage = "usage: %prog [options] CVE_FILE_PATH"
+usage = "usage: %prog [options] PATH"
 description = (
-"Import bugs into Launchpad from CVE entries in ubuntu-cve-tracker."
+"Import bugs into Launchpad from CVE entries in ubuntu-cve-tracker. "
+"PATH is either path to a CVE file, or path to a directory "
+"containing the CVE files"
 )
 loglevel = logging.INFO
 
@@ -30,12 +38,27 @@ class UCTImportScript(LaunchpadScript):
 
 def main(self):
 if len(self.args) != 1:
-self.parser.error("Please specify a CVE file to import")
+self.parser.error("Please specify a path to import")
 
-importer = UCTImporter(dry_run=self.options.dry_run)
+path = Path(self.args[0])
+if path.is_dir():
+logger.info(
+"Importing CVE files from directory: %s", path.resolve()
+)
+cve_paths = [
+p
+for p in path.rglob("CVE-*")
+if p.is_file() and CVE_RE.match(p.name)
+]
+if not cve_paths:
+logger.warning("Could not find CVE files in %s", path)
+return
+else:
+cve_paths = [path]
 
-cve_path = Path(self.args[0])
-importer.import_cve_from_file(cve_path)
+importer = UCTImporter(dry_run=self.options.dry_run)
+for cve_path in cve_paths:
+importer.import_cve_from_file(cve_path)
 
 
 if __name__ == "__main__":
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-upstream-packaging-model into launchpad:master

2022-08-30 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-upstream-packaging-model into 
launchpad:master.

Commit message:
UCT import: use `Packaging` model for `upstream`

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429109

Previously, we were trying to find an LP `Product` with exactly the same name 
as a package in UCT record to handle the status of `upstream`.

Now, we use the `Packaging` model to locate a `Product` by package name.

More specifically, we use the `DistributionSourcePackage.upstream_product` 
property for that.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-upstream-packaging-model into 
launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
index 00f995d..7d2688d 100644
--- a/lib/lp/bugs/scripts/tests/test_uct.py
+++ b/lib/lp/bugs/scripts/tests/test_uct.py
@@ -186,14 +186,17 @@ class TextCVE(TestCaseWithFactory):
 status=SeriesStatus.DEVELOPMENT,
 name="kinetic",
 )
-product_1 = self.factory.makeProduct()
-product_2 = self.factory.makeProduct()
-dsp1 = self.factory.makeDistributionSourcePackage(
-sourcepackagename=product_1.name, distribution=ubuntu
-)
-dsp2 = self.factory.makeDistributionSourcePackage(
-sourcepackagename=product_2.name, distribution=ubuntu
-)
+dsp1 = self.factory.makeDistributionSourcePackage(distribution=ubuntu)
+dsp2 = self.factory.makeDistributionSourcePackage(distribution=ubuntu)
+product_1 = self.factory.makePackagingLink(
+sourcepackagename=dsp1.sourcepackagename,
+distroseries=current_series,
+).productseries.product
+product_2 = self.factory.makePackagingLink(
+sourcepackagename=dsp2.sourcepackagename,
+distroseries=current_series,
+).productseries.product
+
 assignee = self.factory.makePerson()
 
 self.uct_record = UCTRecord(
@@ -374,12 +377,14 @@ class TextCVE(TestCaseWithFactory):
 upstream_packages=[
 CVE.UpstreamPackage(
 package=product_1,
+package_name=dsp1.sourcepackagename,
 importance=None,
 status=BugTaskStatus.FIXRELEASED,
 status_explanation="reason 4",
 ),
-CVE.SeriesPackage(
+CVE.UpstreamPackage(
 package=product_2,
+package_name=dsp2.sourcepackagename,
 importance=None,
 status=BugTaskStatus.FIXRELEASED,
 status_explanation="",
@@ -450,14 +455,21 @@ class TestUCTImporterExporter(TestCaseWithFactory):
 status=SeriesStatus.CURRENT,
 name="trusty",
 )
-self.product_1 = self.factory.makeProduct()
-self.product_2 = self.factory.makeProduct()
 self.ubuntu_package = self.factory.makeDistributionSourcePackage(
-sourcepackagename=self.product_1.name, distribution=self.ubuntu
+distribution=self.ubuntu
 )
 self.esm_package = self.factory.makeDistributionSourcePackage(
-sourcepackagename=self.product_2.name, distribution=self.esm
+distribution=self.esm
 )
+self.product_1 = self.factory.makePackagingLink(
+sourcepackagename=self.ubuntu_package.sourcepackagename,
+distroseries=self.ubuntu_current_series,
+).productseries.product
+self.product_2 = self.factory.makePackagingLink(
+sourcepackagename=self.esm_package.sourcepackagename,
+distroseries=self.esm_current_series,
+).productseries.product
+
 for series in (
 self.ubuntu_supported_series,
 self.ubuntu_current_series,
@@ -548,12 +560,14 @@ class TestUCTImporterExporter(TestCaseWithFactory):
 upstream_packages=[
 CVE.UpstreamPackage(
 package=self.product_1,
+package_name=self.ubuntu_package.sourcepackagename,
 importance=BugTaskImportance.HIGH,
 status=BugTaskStatus.FIXRELEASED,
 status_explanation="fix released",
 ),
 CVE.UpstreamPackage(
 package=self.product_2,
+package_name=self.esm_package.sourcepackagename,
 importance=BugTaskImportance.LOW,
 status=BugTaskStatus.WONTFIX,
 status_explanation="ignored",
@@ -646,7 +660,7 @@ class TestUCTImporterExporter(TestCaseWithFactory):

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:more-vulnerability-dates-new into launchpad:master

2022-08-26 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:more-vulnerability-dates-new into launchpad:master.

Commit message:
Add `Vulnerability.date_notice_issued` and `date_coordinated_release` fields

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/429006

Update the UCT import/export scripts accordingly
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:more-vulnerability-dates-new into launchpad:master.
diff --git a/lib/lp/bugs/interfaces/vulnerability.py b/lib/lp/bugs/interfaces/vulnerability.py
index 9d8292a..474309f 100644
--- a/lib/lp/bugs/interfaces/vulnerability.py
+++ b/lib/lp/bugs/interfaces/vulnerability.py
@@ -282,6 +282,27 @@ class IVulnerabilityEditableAttributes(Interface):
 as_of="devel",
 )
 
+date_notice_issued = exported(
+Datetime(
+title=_(
+"Date when a security notice was issued for this "
+"vulnerability."
+),
+required=False,
+readonly=False,
+),
+as_of="devel",
+)
+
+date_coordinated_release = exported(
+Datetime(
+title=_("Coordinated Release Date."),
+required=False,
+readonly=False,
+),
+as_of="devel",
+)
+
 
 class IVulnerabilityEdit(Interface):
 """`IVulnerability` attributes that require launchpad.Edit."""
@@ -315,6 +336,8 @@ class IVulnerabilitySet(Interface):
 mitigation=None,
 importance_explanation=None,
 date_made_public=None,
+date_notice_issued=None,
+date_coordinated_release=None,
 ):
 """Return a new vulnerability.
 
@@ -330,6 +353,9 @@ class IVulnerabilitySet(Interface):
 :param importance_explanation: Used to explain why our importance
  differs from somebody else's CVSS score.
 :param date_made_public: The date this vulnerability was made public.
+:param date_coordinated_release: Date when a security notice was issued
+ for this vulnerability.
+:param date_notice_issued: Coordinated Release Date.
 """
 
 def findByIds(vulnerability_ids, visible_by_user=None):
diff --git a/lib/lp/bugs/model/vulnerability.py b/lib/lp/bugs/model/vulnerability.py
index d8d00a7..075fba8 100644
--- a/lib/lp/bugs/model/vulnerability.py
+++ b/lib/lp/bugs/model/vulnerability.py
@@ -98,6 +98,12 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin):
 date_made_public = DateTime(
 name="date_made_public", tzinfo=pytz.UTC, allow_none=True
 )
+date_notice_issued = DateTime(
+name="date_notice_issued", tzinfo=pytz.UTC, allow_none=True
+)
+date_coordinated_release = DateTime(
+name="date_coordinated_release", tzinfo=pytz.UTC, allow_none=True
+)
 
 creator_id = Int(name="creator", allow_none=False)
 creator = Reference(creator_id, "Person.id")
@@ -115,6 +121,8 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin):
 mitigation=None,
 importance_explanation=None,
 date_made_public=None,
+date_notice_issued=None,
+date_coordinated_release=None,
 ):
 super().__init__()
 self.distribution = distribution
@@ -132,6 +140,8 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin):
 self.mitigation = mitigation
 self.importance_explanation = importance_explanation
 self.date_made_public = date_made_public
+self.date_notice_issued = date_notice_issued
+self.date_coordinated_release = date_coordinated_release
 self.date_created = UTC_NOW
 
 @property
@@ -323,6 +333,8 @@ class VulnerabilitySet:
 mitigation=None,
 importance_explanation=None,
 date_made_public=None,
+date_notice_issued=None,
+date_coordinated_release=None,
 ):
 """See `IVulnerabilitySet`."""
 store = IStore(Vulnerability)
@@ -338,6 +350,8 @@ class VulnerabilitySet:
 information_type=information_type,
 importance_explanation=importance_explanation,
 date_made_public=date_made_public,
+date_notice_issued=date_notice_issued,
+date_coordinated_release=date_coordinated_release,
 )
 store.add(vulnerability)
 vulnerability._reconcileAccess()
diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
index 00f995d..b0348f5 100644
--- a/lib/lp/bugs/scripts/tests/test_uct.py
+++ b/lib/lp/bugs/scripts/tests/test_uct.py
@@ -162,7 +162,7 @@ class TestUCTRecord(T

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:translation-suggestions into launchpad:master

2022-08-26 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:translation-suggestions into launchpad:master.

Commit message:
Don't show rejected messages in the list of suggestions

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428992

If a there's a message from an external project that has been rejected
(a newer message is set as current), that message should not be displayed
in the list of external suggestions.

Non-rejected suggestions (created after the current message has been approved) 
are still displayed.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:translation-suggestions into launchpad:master.
diff --git a/lib/lp/translations/browser/tests/test_translationmessage_view.py b/lib/lp/translations/browser/tests/test_translationmessage_view.py
index eff116c..74bb435 100644
--- a/lib/lp/translations/browser/tests/test_translationmessage_view.py
+++ b/lib/lp/translations/browser/tests/test_translationmessage_view.py
@@ -26,6 +26,7 @@ from lp.translations.browser.translationmessage import (
 revert_unselected_translations,
 )
 from lp.translations.enums import TranslationPermission
+from lp.translations.interfaces.potemplate import IPOTemplateSet
 from lp.translations.interfaces.side import ITranslationSideTraitsSet
 from lp.translations.interfaces.translations import TranslationConstants
 from lp.translations.interfaces.translationsperson import ITranslationsPerson
@@ -42,8 +43,8 @@ class TestCurrentTranslationMessage_can_dismiss(TestCaseWithFactory):
 yield now
 now += timedelta(milliseconds=1)
 
-def setUp(self):
-super().setUp()
+def setUp(self, *args, **kwargs):
+super().setUp(*args, **kwargs)
 self.owner = self.factory.makePerson()
 self.potemplate = self.factory.makePOTemplate(owner=self.owner)
 self.pofile = self.factory.makePOFile(potemplate=self.potemplate)
@@ -53,15 +54,15 @@ class TestCurrentTranslationMessage_can_dismiss(TestCaseWithFactory):
 
 def _createView(self, message):
 self.view = CurrentTranslationMessageView(
-message,
-LaunchpadTestRequest(),
-{},
-dict(enumerate(message.translations)),
-False,
-False,
-None,
-None,
-True,
+current_translation_message=message,
+request=LaunchpadTestRequest(),
+plural_indices_to_store={},
+translations=dict(enumerate(message.translations)),
+force_suggestion=False,
+force_diverge=False,
+error=None,
+second_lang_code=None,
+form_is_writeable=True,
 pofile=self.pofile,
 can_edit=True,
 )
@@ -222,6 +223,86 @@ class TestCurrentTranslationMessage_can_dismiss(TestCaseWithFactory):
 self._assertConfirmEmptyPluralOther(True, False, False, False)
 
 
+class TestCurrentTranslationMessageView(TestCaseWithFactory):
+
+layer = ZopelessDatabaseLayer
+
+def setUp(self, *args, **kwargs):
+super().setUp(*args, **kwargs)
+self.owner = self.factory.makePerson()
+self.potemplate = self.factory.makePOTemplate(owner=self.owner)
+self.pofile = self.factory.makePOFile(potemplate=self.potemplate)
+self.potmsgset = self.factory.makePOTMsgSet(
+self.potemplate, singular="original message"
+)
+
+def test_externally_used_and_suggested_messages(self):
+message = self.factory.makeCurrentTranslationMessage(
+self.pofile,
+self.potmsgset,
+translator=self.owner,
+)
+external_potemplate = self.factory.makePOTemplate(owner=self.owner)
+external_pofile = self.factory.makePOFile(
+potemplate=external_potemplate, language=self.pofile.language
+)
+external_potmsgset = self.factory.makePOTMsgSet(
+external_potemplate, singular="original message"
+)
+externally_used_message = self.factory.makeCurrentTranslationMessage(
+external_pofile,
+external_potmsgset,
+translator=self.owner,
+translations=["used message"],
+)
+externally_suggested_message = self.factory.makeSuggestion(
+external_pofile,
+external_potmsgset,
+translator=self.owner,
+translations=["suggested message"],
+date_created=externally_used_message.date_reviewed
++ timedelta(days=1),
+)
+externally_rejected_message = self.factory.makeSuggestion(
+external_pofile,
+external_potmsgset,
+translator=self.owner,
+translations=["rejected message"],
+

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-upstream into launchpad:master

2022-08-24 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:uct-upstream 
into launchpad:master with ~andrey-fedoseev/launchpad:uct-export as a 
prerequisite.

Commit message:
UCT import/export: handle upstream package status and ESM packages

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428893

This also includes the changes related to UCT export that were added in 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428152
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-upstream into launchpad:master.
diff --git a/lib/lp/bugs/interfaces/bugtask.py b/lib/lp/bugs/interfaces/bugtask.py
index a8c4e45..8fb2ce2 100644
--- a/lib/lp/bugs/interfaces/bugtask.py
+++ b/lib/lp/bugs/interfaces/bugtask.py
@@ -846,7 +846,7 @@ class IBugTask(IHasBug, IBugTaskDelete):
 @call_with(user=REQUEST_USER)
 @export_write_operation()
 @operation_for_version("beta")
-def transitionToMilestone(new_milestone, user=None):
+def transitionToMilestone(new_milestone, user):
 """Set the BugTask milestone.
 
 Set the bugtask milestone, making sure that the user is
@@ -859,7 +859,7 @@ class IBugTask(IHasBug, IBugTaskDelete):
 @call_with(user=REQUEST_USER)
 @export_write_operation()
 @operation_for_version("beta")
-def transitionToImportance(new_importance, user=None):
+def transitionToImportance(new_importance, user):
 """Set the BugTask importance.
 
 Set the bugtask importance, making sure that the user is
@@ -883,7 +883,7 @@ class IBugTask(IHasBug, IBugTaskDelete):
 @call_with(user=REQUEST_USER)
 @export_write_operation()
 @operation_for_version("beta")
-def transitionToStatus(new_status, user=None):
+def transitionToStatus(new_status, user):
 """Perform a workflow transition to the new_status.
 
 :new_status: new status from `BugTaskStatus`
diff --git a/lib/lp/bugs/model/bugtask.py b/lib/lp/bugs/model/bugtask.py
index 33d3647..90f4e36 100644
--- a/lib/lp/bugs/model/bugtask.py
+++ b/lib/lp/bugs/model/bugtask.py
@@ -933,9 +933,9 @@ class BugTask(StormBase):
 # setter methods directly.
 setattr(self, synched_attr, PassthroughValue(replica_attr_value))
 
-def transitionToMilestone(self, new_milestone, user=None):
+def transitionToMilestone(self, new_milestone, user):
 """See `IBugTask`."""
-if user and not self.userHasBugSupervisorPrivileges(user):
+if not self.userHasBugSupervisorPrivileges(user):
 raise UserCannotEditBugTaskMilestone(
 "User does not have sufficient permissions "
 "to edit the bug task milestone."
@@ -945,9 +945,9 @@ class BugTask(StormBase):
 # notified.
 self.bug.clearBugNotificationRecipientsCache()
 
-def transitionToImportance(self, new_importance, user=None):
+def transitionToImportance(self, new_importance, user):
 """See `IBugTask`."""
-if user and not self.userHasBugSupervisorPrivileges(user):
+if not self.userHasBugSupervisorPrivileges(user):
 raise UserCannotEditBugTaskImportance(
 "User does not have sufficient permissions "
 "to edit the bug task importance."
@@ -1030,9 +1030,9 @@ class BugTask(StormBase):
 # Non-supervisors can transition to non-supervisor statuses.
 return new_status not in BUG_SUPERVISOR_BUGTASK_STATUSES
 
-def transitionToStatus(self, new_status, user=None, when=None):
+def transitionToStatus(self, new_status, user, when=None):
 """See `IBugTask`."""
-if not new_status:
+if not new_status or user is None:
 # This is mainly to facilitate tests which, unlike the
 # normal status form, don't always submit a status when
 # testing the edit form.
@@ -1040,7 +1040,7 @@ class BugTask(StormBase):
 
 new_status = normalize_bugtask_status(new_status)
 
-if user and not self.canTransitionToStatus(new_status, user):
+if not self.canTransitionToStatus(new_status, user):
 raise UserCannotEditBugTaskStatus(
 "Only Bug Supervisors may change status to %s."
 % (new_status.title,)
diff --git a/lib/lp/bugs/scripts/bugimport.py b/lib/lp/bugs/scripts/bugimport.py
index 323c9b1..6694d86 100644
--- a/lib/lp/bugs/scripts/bugimport.py
+++ b/lib/lp/bugs/scripts/bugimport.py
@@ -356,10 +356,14 @@ class BugImporter:
 # set up bug task
 bugtask.datecreated = datecreated
 bugtask.transitionToImportance(
- 

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-upstream into launchpad:master

2022-08-24 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:uct-upstream into 
launchpad:master has been updated.

Status: Needs review => Superseded

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428533
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-upstream into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master

2022-08-24 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master with 
~andrey-fedoseev/launchpad:uct-upstream as a prerequisite.

Commit message:
Add `Vulnerability.date_notice_issued` and `date_coordinated_release` fields

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428892

Update the UCT import/export scripts accordingly

Note that this MP includes changes which are also present in other merge 
proposals:

https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428152
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428533
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master.
diff --git a/lib/lp/bugs/interfaces/vulnerability.py b/lib/lp/bugs/interfaces/vulnerability.py
index 9d8292a..474309f 100644
--- a/lib/lp/bugs/interfaces/vulnerability.py
+++ b/lib/lp/bugs/interfaces/vulnerability.py
@@ -282,6 +282,27 @@ class IVulnerabilityEditableAttributes(Interface):
 as_of="devel",
 )
 
+date_notice_issued = exported(
+Datetime(
+title=_(
+"Date when a security notice was issued for this "
+"vulnerability."
+),
+required=False,
+readonly=False,
+),
+as_of="devel",
+)
+
+date_coordinated_release = exported(
+Datetime(
+title=_("Coordinated Release Date."),
+required=False,
+readonly=False,
+),
+as_of="devel",
+)
+
 
 class IVulnerabilityEdit(Interface):
 """`IVulnerability` attributes that require launchpad.Edit."""
@@ -315,6 +336,8 @@ class IVulnerabilitySet(Interface):
 mitigation=None,
 importance_explanation=None,
 date_made_public=None,
+date_notice_issued=None,
+date_coordinated_release=None,
 ):
 """Return a new vulnerability.
 
@@ -330,6 +353,9 @@ class IVulnerabilitySet(Interface):
 :param importance_explanation: Used to explain why our importance
  differs from somebody else's CVSS score.
 :param date_made_public: The date this vulnerability was made public.
+:param date_coordinated_release: Date when a security notice was issued
+ for this vulnerability.
+:param date_notice_issued: Coordinated Release Date.
 """
 
 def findByIds(vulnerability_ids, visible_by_user=None):
diff --git a/lib/lp/bugs/model/vulnerability.py b/lib/lp/bugs/model/vulnerability.py
index d8d00a7..075fba8 100644
--- a/lib/lp/bugs/model/vulnerability.py
+++ b/lib/lp/bugs/model/vulnerability.py
@@ -98,6 +98,12 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin):
 date_made_public = DateTime(
 name="date_made_public", tzinfo=pytz.UTC, allow_none=True
 )
+date_notice_issued = DateTime(
+name="date_notice_issued", tzinfo=pytz.UTC, allow_none=True
+)
+date_coordinated_release = DateTime(
+name="date_coordinated_release", tzinfo=pytz.UTC, allow_none=True
+)
 
 creator_id = Int(name="creator", allow_none=False)
 creator = Reference(creator_id, "Person.id")
@@ -115,6 +121,8 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin):
 mitigation=None,
 importance_explanation=None,
 date_made_public=None,
+date_notice_issued=None,
+date_coordinated_release=None,
 ):
 super().__init__()
 self.distribution = distribution
@@ -132,6 +140,8 @@ class Vulnerability(StormBase, BugLinkTargetMixin, InformationTypeMixin):
 self.mitigation = mitigation
 self.importance_explanation = importance_explanation
 self.date_made_public = date_made_public
+self.date_notice_issued = date_notice_issued
+self.date_coordinated_release = date_coordinated_release
 self.date_created = UTC_NOW
 
 @property
@@ -323,6 +333,8 @@ class VulnerabilitySet:
 mitigation=None,
 importance_explanation=None,
 date_made_public=None,
+date_notice_issued=None,
+date_coordinated_release=None,
 ):
 """See `IVulnerabilitySet`."""
 store = IStore(Vulnerability)
@@ -338,6 +350,8 @@ class VulnerabilitySet:
 information_type=information_type,
 importance_explanation=importance_explanation,
 date_made_public=date_made_public,
+date_notice_issued=date_notice_issued,
+date_coordinated_release=date_coordinated_release,
 )
 store.add(vul

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master

2022-08-24 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:more-vulnerability-dates into 
launchpad:master has been updated.

Status: Needs review => Superseded

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428705
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:merge-db-stable into launchpad:master

2022-08-24 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:merge-db-stable 
into launchpad:master.

Commit message:
Merge db-stable 66c4831c8a3c7d1a5768fcdfd41634e76e7de853 (add 
`vulnerability.date_notice_issued` and `.date_coordinated_release` columns)

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428847
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:merge-db-stable into launchpad:master.
diff --git a/database/schema/patch-2211-04-0.sql b/database/schema/patch-2211-04-0.sql
new file mode 100644
index 000..2435222
--- /dev/null
+++ b/database/schema/patch-2211-04-0.sql
@@ -0,0 +1,20 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE Vulnerability
+ADD COLUMN date_notice_issued timestamp without time zone
+;
+
+ALTER TABLE Vulnerability
+ADD COLUMN date_coordinated_release timestamp without time zone
+;
+
+COMMENT ON COLUMN Vulnerability.date_notice_issued
+IS 'Date when a security notice was issued for this vulnerability';
+
+COMMENT ON COLUMN Vulnerability.date_coordinated_release
+IS 'Coordinated Release Date';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 04, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] lp:~cjwatson/meta-lp-deps/remove-bzr into lp:meta-lp-deps

2022-08-23 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/meta-lp-deps/remove-bzr/+merge/428803
Your team Launchpad code reviewers is subscribed to branch lp:meta-lp-deps.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master

2022-08-22 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:more-vulnerability-dates into 
launchpad:master has been updated.

Description changed to:

Update the UCT import/export scripts accordingly

Note that this MP includes changes which are also present in other merge 
proposals:

https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428152
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428533

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428705
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master

2022-08-22 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master.

Commit message:
Add `Vulnerability.date_notice_issued` and `date_coordinated_release` fields

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428705

Update the UCT import/export scripts accordingly
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:more-vulnerability-dates into launchpad:master.
diff --git a/lib/contrib/cve_lib.py b/lib/contrib/cve_lib.py
index 6672864..da211fd 100644
--- a/lib/contrib/cve_lib.py
+++ b/lib/contrib/cve_lib.py
@@ -11,6 +11,7 @@ import math
 import os
 import re
 import sys
+from collections import OrderedDict
 
 import yaml
 
@@ -1195,17 +1196,17 @@ def load_cve(cve, strict=False, srcmap=None):
 ]
 extra_fields = ["CRD", "PublicDateAtUSN", "Mitigation"]
 
-data = dict()
+data = OrderedDict()
 # maps entries in data to their source line - if didn't supply one
 # create a local one to simplify the code
 if srcmap is None:
-srcmap = dict()
-srcmap.setdefault("pkgs", dict())
-srcmap.setdefault("tags", dict())
-data.setdefault("tags", dict())
-srcmap.setdefault("patches", dict())
-data.setdefault("patches", dict())
-affected = dict()
+srcmap = OrderedDict()
+srcmap.setdefault("pkgs", OrderedDict())
+srcmap.setdefault("tags", OrderedDict())
+data.setdefault("tags", OrderedDict())
+srcmap.setdefault("patches", OrderedDict())
+data.setdefault("patches", OrderedDict())
+affected = OrderedDict()
 lastfield = ""
 fields_seen = []
 if not os.path.exists(cve):
@@ -1254,7 +1255,7 @@ def load_cve(cve, strict=False, srcmap=None):
 code = EXIT_FAIL
 elif lastfield == "CVSS":
 try:
-cvss = dict()
+cvss = OrderedDict()
 result = re.search(
 r" (.+)\: (\S+)( \[(.*) (.*)\])?", line
 )
@@ -1277,7 +1278,7 @@ def load_cve(cve, strict=False, srcmap=None):
 # line where the CVSS block starts - so convert it
 # to a dict first if needed
 if type(srcmap["CVSS"]) is tuple:
-srcmap["CVSS"] = dict()
+srcmap["CVSS"] = OrderedDict()
 srcmap["CVSS"].setdefault(
 cvss["source"], (cve, linenum)
 )
@@ -1419,7 +1420,7 @@ def load_cve(cve, strict=False, srcmap=None):
 msg += "%s: %d: unknown entry '%s'\n" % (cve, linenum, rel)
 code = EXIT_FAIL
 continue
-affected.setdefault(pkg, dict())
+affected.setdefault(pkg, OrderedDict())
 if rel in affected[pkg]:
 msg += (
 "%s: %d: duplicate entry for '%s': original at line %d\n"
@@ -1433,7 +1434,7 @@ def load_cve(cve, strict=False, srcmap=None):
 code = EXIT_FAIL
 continue
 affected[pkg].setdefault(rel, [state, details])
-srcmap["pkgs"].setdefault(pkg, dict())
+srcmap["pkgs"].setdefault(pkg, OrderedDict())
 srcmap["pkgs"][pkg].setdefault(rel, (cve, linenum))
 elif field not in required_fields + extra_fields:
 msg += "%s: %d: unknown field '%s'\n" % (cve, linenum, field)
@@ -1539,9 +1540,9 @@ def amend_external_subproject_pkg(cve, data, srcmap, amendments, code, msg):
 if not success:
 return code, msg
 
-data.setdefault("pkgs", dict())
-data["pkgs"].setdefault(pkg, dict())
-srcmap["pkgs"].setdefault(pkg, dict())
+data.setdefault("pkgs", OrderedDict())
+data["pkgs"].setdefault(pkg, OrderedDict())
+srcmap["pkgs"].setdefault(pkg, OrderedDict())
 # override existing release info if it exists
 data["pkgs"][pkg][release] = [state, details]
 srcmap["pkgs"][pkg][release] = (cve, linenum)
diff --git a/lib/lp/bugs/interfaces/vulnerability.py b/lib/lp/bugs/interfaces/vulnerability.py
index 6fe9abc..4b935d5 100644
--- a/lib/lp/bugs/interfaces/vulnerability.py
+++ b/lib/lp/bugs/interfaces/vulnerability.py
@@ -264,6 +264,27 @@ class IVulnerabilityEditableAttributes(Interface):
 as_of="devel",
 )

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:db-more-vulnerability-dates into launchpad:db-devel

2022-08-19 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:db-more-vulnerability-dates into launchpad:db-devel.

Commit message:
DB patch to add `vulnerability.crd` and `.date_made_public_at_usn` columns

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428613
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:db-more-vulnerability-dates into launchpad:db-devel.
diff --git a/database/schema/patch-2211-04-0.sql b/database/schema/patch-2211-04-0.sql
new file mode 100644
index 000..68cb09a
--- /dev/null
+++ b/database/schema/patch-2211-04-0.sql
@@ -0,0 +1,20 @@
+-- Copyright 2022 Canonical Ltd.  This software is licensed under the
+-- GNU Affero General Public License version 3 (see the file LICENSE).
+
+SET client_min_messages=ERROR;
+
+ALTER TABLE Vulnerability
+ADD COLUMN date_made_public_at_usn timestamp without time zone
+;
+
+ALTER TABLE Vulnerability
+ADD COLUMN crd timestamp without time zone
+;
+
+COMMENT ON COLUMN Vulnerability.date_made_public_at_usn
+IS 'The date this vulnerability was made public at Ubuntu Security Notices';
+
+COMMENT ON COLUMN Vulnerability.crd
+IS 'Coordinated Release Date';
+
+INSERT INTO LaunchpadDatabaseRevision VALUES (2211, 04, 0);
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:snap-arch-multi-build-on into launchpad:master

2022-08-19 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:snap-arch-multi-build-on into launchpad:master.

Commit message:
Allow duplicate `build-on` for `core22`


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428596

This allows the following configuration in `snapcraft.yaml` which is legit only 
for `core22`

architectures:
  - build-on: amd64
  - build-on: amd64
build-for: [arm64]
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:snap-arch-multi-build-on into launchpad:master.
diff --git a/lib/lp/snappy/adapters/buildarch.py b/lib/lp/snappy/adapters/buildarch.py
index e4e92f7..9193038 100644
--- a/lib/lp/snappy/adapters/buildarch.py
+++ b/lib/lp/snappy/adapters/buildarch.py
@@ -146,11 +146,13 @@ class SnapBuildInstance:
 
 
 def determine_architectures_to_build(
+snap_base: Optional[str],
 snapcraft_data: Dict[str, Any],
 supported_arches: List[str],
 ) -> List[SnapBuildInstance]:
 """Return a list of architectures to build based on snapcraft.yaml.
 
+:param snap_base: Name of the snap base.
 :param snapcraft_data: A parsed snapcraft.yaml.
 :param supported_arches: An ordered list of all architecture tags that
 we can create builds for.
@@ -182,16 +184,17 @@ def determine_architectures_to_build(
 SnapArchitecture(build_on=a) for a in supported_arches
 ]
 
-# Ensure that multiple `build-on` items don't include the same
-# architecture; this is ambiguous and forbidden by snapcraft.  Checking
-# this here means that we don't get duplicate supported_arch results
-# below.
-build_ons = Counter()
-for arch in architectures:
-build_ons.update(arch.build_on)
-duplicates = {arch for arch, count in build_ons.items() if count > 1}
-if duplicates:
-raise DuplicateBuildOnError(duplicates)
+if snap_base not in {"core22"}:
+# Ensure that multiple `build-on` items don't include the same
+# architecture; this is ambiguous and forbidden by snapcraft prior
+# to core22. Checking this here means that we don't get duplicate
+# supported_arch results below.
+build_ons = Counter()
+for arch in architectures:
+build_ons.update(arch.build_on)
+duplicates = {arch for arch, count in build_ons.items() if count > 1}
+if duplicates:
+raise DuplicateBuildOnError(duplicates)
 
 architectures_to_build = []
 for arch in architectures:
diff --git a/lib/lp/snappy/adapters/tests/test_buildarch.py b/lib/lp/snappy/adapters/tests/test_buildarch.py
index 81f3c87..db52baf 100644
--- a/lib/lp/snappy/adapters/tests/test_buildarch.py
+++ b/lib/lp/snappy/adapters/tests/test_buildarch.py
@@ -5,6 +5,7 @@ from testscenarios import WithScenarios, load_tests_apply_scenarios
 from testtools.matchers import HasLength
 
 from lp.snappy.adapters.buildarch import (
+DuplicateBuildOnError,
 SnapArchitecture,
 SnapBuildInstance,
 UnsupportedBuildOnError,
@@ -392,16 +393,60 @@ class TestDetermineArchitecturesToBuild(WithScenarios, TestCase):
 ],
 },
 ),
+(
+"multiple build-for for the same build-on",
+{
+"architectures": [
+{"build-on": "amd64", "build-for": ["amd64"]},
+{"build-on": "amd64", "build-for": ["i386"]},
+],
+"supported_architectures": ["amd64", "i386", "armhf"],
+"expected": [
+{
+"architecture": "amd64",
+"target_architectures": ["amd64"],
+"required": True,
+},
+{
+"architecture": "amd64",
+"target_architectures": ["i386"],
+"required": True,
+},
+],
+},
+),
+(
+"multiple build-for for the same build-on: old base",
+{
+"snap_base": "core20",
+"architectures": [
+{"build-on": "amd64", "build-for": ["amd64"]},
+{"build-on": "amd64", "build-for": ["i386"]},
+],
+"supported_architectures": ["amd64", "i386", "armhf"],
+"expe

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-upstream into launchpad:master

2022-08-18 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:uct-upstream 
into launchpad:master.

Commit message:
UCT import/export: handle upstream package status and ESM packages

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428533

This also includes the changes related to UCT export that were added in 
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428152
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-upstream into launchpad:master.
diff --git a/lib/contrib/cve_lib.py b/lib/contrib/cve_lib.py
index 6672864..da211fd 100644
--- a/lib/contrib/cve_lib.py
+++ b/lib/contrib/cve_lib.py
@@ -11,6 +11,7 @@ import math
 import os
 import re
 import sys
+from collections import OrderedDict
 
 import yaml
 
@@ -1195,17 +1196,17 @@ def load_cve(cve, strict=False, srcmap=None):
 ]
 extra_fields = ["CRD", "PublicDateAtUSN", "Mitigation"]
 
-data = dict()
+data = OrderedDict()
 # maps entries in data to their source line - if didn't supply one
 # create a local one to simplify the code
 if srcmap is None:
-srcmap = dict()
-srcmap.setdefault("pkgs", dict())
-srcmap.setdefault("tags", dict())
-data.setdefault("tags", dict())
-srcmap.setdefault("patches", dict())
-data.setdefault("patches", dict())
-affected = dict()
+srcmap = OrderedDict()
+srcmap.setdefault("pkgs", OrderedDict())
+srcmap.setdefault("tags", OrderedDict())
+data.setdefault("tags", OrderedDict())
+srcmap.setdefault("patches", OrderedDict())
+data.setdefault("patches", OrderedDict())
+affected = OrderedDict()
 lastfield = ""
 fields_seen = []
 if not os.path.exists(cve):
@@ -1254,7 +1255,7 @@ def load_cve(cve, strict=False, srcmap=None):
 code = EXIT_FAIL
 elif lastfield == "CVSS":
 try:
-cvss = dict()
+cvss = OrderedDict()
 result = re.search(
 r" (.+)\: (\S+)( \[(.*) (.*)\])?", line
 )
@@ -1277,7 +1278,7 @@ def load_cve(cve, strict=False, srcmap=None):
 # line where the CVSS block starts - so convert it
 # to a dict first if needed
 if type(srcmap["CVSS"]) is tuple:
-srcmap["CVSS"] = dict()
+srcmap["CVSS"] = OrderedDict()
 srcmap["CVSS"].setdefault(
 cvss["source"], (cve, linenum)
 )
@@ -1419,7 +1420,7 @@ def load_cve(cve, strict=False, srcmap=None):
 msg += "%s: %d: unknown entry '%s'\n" % (cve, linenum, rel)
 code = EXIT_FAIL
 continue
-affected.setdefault(pkg, dict())
+affected.setdefault(pkg, OrderedDict())
 if rel in affected[pkg]:
 msg += (
 "%s: %d: duplicate entry for '%s': original at line %d\n"
@@ -1433,7 +1434,7 @@ def load_cve(cve, strict=False, srcmap=None):
 code = EXIT_FAIL
 continue
 affected[pkg].setdefault(rel, [state, details])
-srcmap["pkgs"].setdefault(pkg, dict())
+srcmap["pkgs"].setdefault(pkg, OrderedDict())
 srcmap["pkgs"][pkg].setdefault(rel, (cve, linenum))
 elif field not in required_fields + extra_fields:
 msg += "%s: %d: unknown field '%s'\n" % (cve, linenum, field)
@@ -1539,9 +1540,9 @@ def amend_external_subproject_pkg(cve, data, srcmap, amendments, code, msg):
 if not success:
 return code, msg
 
-data.setdefault("pkgs", dict())
-data["pkgs"].setdefault(pkg, dict())
-srcmap["pkgs"].setdefault(pkg, dict())
+data.setdefault("pkgs", OrderedDict())
+data["pkgs"].setdefault(pkg, OrderedDict())
+srcmap["pkgs"].setdefault(pkg, OrderedDict())
 # override existing release info if it exists
 data["pkgs"][pkg][release] = [state, details]
 srcmap["pkgs"][pkg][release] = (cve, linenum)
diff --git a/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222 b/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
index 6d665be..30574d6 100644
--- a/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
+++ b/lib/lp/bugs/scripts/tests/sampledata/C

Re: [Launchpad-reviewers] [Merge] ~jugmac00/launchpad-buildd:provide-additional-repositories-instead-of-replacing-them into launchpad-buildd:master

2022-08-17 Thread Andrey Fedoseev
I don't quite understand how the commit message

"Provide additional package repositories for CI builds rather than replacing 
the base repositories." 

is related to the actual changes -- using `package_repositories` argument 
instead of `apt_repositories`
-- 
https://code.launchpad.net/~jugmac00/launchpad-buildd/+git/launchpad-buildd/+merge/428410
Your team Launchpad code reviewers is requested to review the proposed merge of 
~jugmac00/launchpad-buildd:provide-additional-repositories-instead-of-replacing-them
 into launchpad-buildd:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] lp:~andrey-fedoseev/meta-lp-deps/remove-gir into lp:meta-lp-deps

2022-08-17 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
lp:~andrey-fedoseev/meta-lp-deps/remove-gir into lp:meta-lp-deps.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/meta-lp-deps/remove-gir/+merge/428466
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~andrey-fedoseev/meta-lp-deps/remove-gir into lp:meta-lp-deps.
=== modified file 'debian/changelog'
--- debian/changelog	2022-07-27 17:36:15 +
+++ debian/changelog	2022-08-17 10:07:43 +
@@ -13,6 +13,7 @@
   [ Andrey Fedoseev ]
   * Add firefox-geckodriver to launchpad-developer-dependencies;
 this is required for Selenium-based test browser
+  * Remove gir1.2-* dependencies; it is superseded with firefox/selenium.
 
  -- Colin Watson   Fri, 06 May 2022 12:26:43 +0200
 

=== modified file 'debian/control'
--- debian/control	2022-07-27 17:36:15 +
+++ debian/control	2022-08-17 10:07:43 +
@@ -57,9 +57,6 @@
   mhonarc,
   fakeroot, rsync, memcached,
   xvfb, firefox, firefox-geckodriver, intltool,
-  gir1.2-glib-2.0,
-  gir1.2-gtk-3.0,
-  gir1.2-webkit-3.0,
   ${misc:Depends}
 Recommends: subunit
 Suggests: apache2, libapache2-mod-wsgi

___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:ci-build-email into launchpad:master

2022-08-16 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:ci-build-email 
into launchpad:master.

Commit message:
Allow notifications for failed CI builds

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428395

One line change to allow the buildd manager to send notifications for the 
failed CI builds
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:ci-build-email into launchpad:master.
diff --git a/lib/lp/code/model/cibuildbehaviour.py b/lib/lp/code/model/cibuildbehaviour.py
index 7655ff8..726bb80 100644
--- a/lib/lp/code/model/cibuildbehaviour.py
+++ b/lib/lp/code/model/cibuildbehaviour.py
@@ -108,7 +108,7 @@ class CIBuildBehaviour(BuilderProxyMixin, BuildFarmJobBehaviourBase):
 builder_type = "ci"
 image_types = [BuildBaseImageType.LXD, BuildBaseImageType.CHROOT]
 
-ALLOWED_STATUS_NOTIFICATIONS = []
+ALLOWED_STATUS_NOTIFICATIONS = ["PACKAGEFAIL"]
 
 def redactXmlrpcArguments(self, args):
 # we do not want to have secrets in logs
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:close-account into launchpad:master

2022-08-12 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:close-account 
into launchpad:master.

Commit message:
close-account: handle the referenced deleted PPAs

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428250

If a deleted PPA is not referenced, or the references allows cascade deletion, 
it gets purged. Otherwise, it is ignored.

Non-deleted PPAs still block account closing.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:close-account into launchpad:master.
diff --git a/lib/lp/registry/scripts/closeaccount.py b/lib/lp/registry/scripts/closeaccount.py
index 8f24d6f..7a21c56 100644
--- a/lib/lp/registry/scripts/closeaccount.py
+++ b/lib/lp/registry/scripts/closeaccount.py
@@ -11,7 +11,6 @@ __all__ = [
 from typing import List, Tuple
 
 import six
-from storm.exceptions import IntegrityError
 from storm.expr import And, LeftJoin, Lower, Or
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
@@ -409,26 +408,60 @@ def close_account(username, log):
 (person.id,),
 )
 
-# Purge deleted PPAs.  This is safe because the archive can only be in
-# the DELETED status if the publisher has removed it from disk and set
-# all its publications to DELETED.
-# XXX cjwatson 2019-08-09: This will fail if anything non-trivial has
-# been done in this person's PPAs; and it's not obvious what to do in
-# more complicated cases such as builds having been copied out
-# elsewhere.  It's good enough for some simple cases, though.
-try:
+# Purge deleted PPAs that aren't referenced anywhere.
+# This is safe because the archive can only be in the DELETED status if
+# the publisher has removed it from disk and set all its publications
+# to DELETED.
+# Deleted PPAs that are still referenced are ignored.
+deleted_ppa_ids = set(
 store.find(
-Archive,
+Archive.id,
 Archive.owner == person,
 Archive.status == ArchiveStatus.DELETED,
-).remove()
-except IntegrityError:
-raise LaunchpadScriptFailure(
-"Can't delete non-trivial PPAs for user %s" % person_name
 )
+)
+ppa_references = list(postgresql.listReferences(cur, "archive", "id"))
+referenced_ppa_ids = set()
+for ppa_id in deleted_ppa_ids:
+for src_tab, src_col, *_, delete_action in ppa_references:
+if delete_action == "c":
+# cascade deletion is enabled, so the reference may be ignored
+continue
+result = store.execute(
+"""
+SELECT COUNT(*) FROM %(src_tab)s WHERE %(src_col)s = ?
+"""
+% {
+"src_tab": src_tab,
+"src_col": src_col,
+},
+(ppa_id,),
+)
+count = result.get_one()[0]
+if count:
+referenced_ppa_ids.add(ppa_id)
+reference = "{}.{}".format(src_tab, src_col)
+log.warning(
+"PPA %d is still referenced by %d %s values"
+% (ppa_id, count, reference)
+)
+
+non_referenced_ppa_ids = deleted_ppa_ids - referenced_ppa_ids
+if non_referenced_ppa_ids:
+store.find(Archive, Archive.id.is_in(non_referenced_ppa_ids)).remove()
 
 reference_counts = []  # type: List[Tuple[str, int]]
 
+# Check for non-deleted PPAs
+count = store.find(
+Archive,
+Archive.owner == person,
+Archive.status != ArchiveStatus.DELETED,
+).count()
+if count:
+reference_counts.append(("archive.owner", count))
+skip.add(("archive", "owner"))
+
 # Check for active related projects, and skip inactive ones.
 for col in "bug_supervisor", "driver", "owner":
 # Raw SQL because otherwise using Product._owner while displaying it
@@ -549,7 +582,7 @@ def close_account(username, log):
 # by this point.  If not, it's safer to bail out.  It's OK if this
 # doesn't work in all conceivable situations, since some of them may
 # require careful thought and decisions by a human administrator.
-for src_tab, src_col, ref_tab, ref_col, updact, delact in references:
+for src_tab, src_col, *_ in references:
 if (src_tab, src_col) in skip:
 continue
 result = store.execute(
diff --git a/lib/lp/registry/scripts/tests/test_closeaccount.py b/lib/lp/registry/scripts/tests/test_closeaccount.py
index 120328c..7a13f9d 100644
--- a/lib/lp/registry/scripts/tests/test_closeaccount.py
+++ b/lib/lp/regi

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:close-account into launchpad:master

2022-08-10 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:close-account 
into launchpad:master.

Commit message:
Skip certain fields reference checking in `close-account`:

 - branch.{owner,reviewer,registrant} from inactive products
 - specification.assignee from inactive products

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428163
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:close-account into launchpad:master.
diff --git a/lib/lp/registry/scripts/closeaccount.py b/lib/lp/registry/scripts/closeaccount.py
index 708bd5b..063e0a5 100644
--- a/lib/lp/registry/scripts/closeaccount.py
+++ b/lib/lp/registry/scripts/closeaccount.py
@@ -19,7 +19,9 @@ from zope.security.proxy import removeSecurityProxy
 from lp.answers.enums import QuestionStatus
 from lp.answers.model.question import Question
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
+from lp.blueprints.model.specification import Specification
 from lp.bugs.model.bugtask import BugTask
+from lp.code.model.branch import Branch
 from lp.registry.interfaces.person import PersonCreationRationale
 from lp.registry.model.announcement import Announcement
 from lp.registry.model.milestone import Milestone
@@ -509,6 +511,40 @@ def close_account(username, log):
 reference_counts.append(("productreleasefile.uploader", count))
 skip.add(("productreleasefile", "uploader"))
 
+# Check Branches, skipping the ones that are related to inactive products.
+for col_name in "owner", "reviewer", "registrant":
+count = store.find(
+Branch,
+Or(
+And(
+Branch.product == Product.id,
+Product.active,
+),
+Branch.product == None,
+),
+getattr(Branch, col_name) == person.id,
+).count()
+if count:
+reference_counts.append(("branch.{}".format(col_name), count))
+skip.add(("branch", col_name))
+
+# Check Specification, skipping the ones
+# that are related to inactive products / product series.
+count = store.find(
+Specification,
+Or(
+And(
+Specification.product == Product.id,
+Product.active,
+),
+Specification.product == None,
+),
+Specification._assignee == person.id,
+).count()
+if count:
+reference_counts.append(("specification.assignee", count))
+skip.add(("specification", "assignee"))
+
 # Closing the account will only work if all references have been handled
 # by this point.  If not, it's safer to bail out.  It's OK if this
 # doesn't work in all conceivable situations, since some of them may
diff --git a/lib/lp/registry/scripts/tests/test_closeaccount.py b/lib/lp/registry/scripts/tests/test_closeaccount.py
index b78ff60..9cac8fc 100644
--- a/lib/lp/registry/scripts/tests/test_closeaccount.py
+++ b/lib/lp/registry/scripts/tests/test_closeaccount.py
@@ -1174,3 +1174,71 @@ class TestCloseAccount(TestCaseWithFactory):
 else:
 self.runScript(script)
 self.assertRemoved(account_id, person_id)
+
+def test_skip_branches_from_inactive_products(self):
+active_product = self.factory.makeProduct()
+inactive_product = self.factory.makeProduct()
+inactive_product.active = False
+
+for branch_target, expected_to_be_removed in (
+(active_product, False),
+(inactive_product, True),
+(self.factory.makeSourcePackage(), False),
+):
+for col_name in "owner", "reviewer", "registrant":
+person = self.factory.makePerson()
+make_branch_kwargs = {col_name: person}
+if col_name == "registrant":
+make_branch_kwargs["owner"] = self.factory.makeTeam(
+members=[person]
+)
+self.factory.makeBranch(
+target=branch_target, **make_branch_kwargs
+)
+
+person_id = person.id
+account_id = person.account.id
+script = self.makeScript([person.name])
+with dbuser("launchpad"):
+if not expected_to_be_removed:
+self.assertRaisesWithContent(
+LaunchpadScriptFailure,
+"User %s is still referenced" % person.name,
+self.runScript,
+script,
+)
+   

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-export into launchpad:master

2022-08-10 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:uct-export into 
launchpad:master has been updated.

Description changed to:

This adds new `UCTExporter` class and related script.

The following changes are made to the importer:

 - ubuntu-description is now saved to `Vulnerability.description`
 - CVSS is saved to `Cve.cvss`

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428152
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-export into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-export into launchpad:master

2022-08-10 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:uct-export into 
launchpad:master.

Commit message:
Enable exporting bugs to UCT CVE records

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428152
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-export into launchpad:master.
diff --git a/lib/contrib/cve_lib.py b/lib/contrib/cve_lib.py
index 6672864..da211fd 100644
--- a/lib/contrib/cve_lib.py
+++ b/lib/contrib/cve_lib.py
@@ -11,6 +11,7 @@ import math
 import os
 import re
 import sys
+from collections import OrderedDict
 
 import yaml
 
@@ -1195,17 +1196,17 @@ def load_cve(cve, strict=False, srcmap=None):
 ]
 extra_fields = ["CRD", "PublicDateAtUSN", "Mitigation"]
 
-data = dict()
+data = OrderedDict()
 # maps entries in data to their source line - if didn't supply one
 # create a local one to simplify the code
 if srcmap is None:
-srcmap = dict()
-srcmap.setdefault("pkgs", dict())
-srcmap.setdefault("tags", dict())
-data.setdefault("tags", dict())
-srcmap.setdefault("patches", dict())
-data.setdefault("patches", dict())
-affected = dict()
+srcmap = OrderedDict()
+srcmap.setdefault("pkgs", OrderedDict())
+srcmap.setdefault("tags", OrderedDict())
+data.setdefault("tags", OrderedDict())
+srcmap.setdefault("patches", OrderedDict())
+data.setdefault("patches", OrderedDict())
+affected = OrderedDict()
 lastfield = ""
 fields_seen = []
 if not os.path.exists(cve):
@@ -1254,7 +1255,7 @@ def load_cve(cve, strict=False, srcmap=None):
 code = EXIT_FAIL
 elif lastfield == "CVSS":
 try:
-cvss = dict()
+cvss = OrderedDict()
 result = re.search(
 r" (.+)\: (\S+)( \[(.*) (.*)\])?", line
 )
@@ -1277,7 +1278,7 @@ def load_cve(cve, strict=False, srcmap=None):
 # line where the CVSS block starts - so convert it
 # to a dict first if needed
 if type(srcmap["CVSS"]) is tuple:
-srcmap["CVSS"] = dict()
+srcmap["CVSS"] = OrderedDict()
 srcmap["CVSS"].setdefault(
 cvss["source"], (cve, linenum)
 )
@@ -1419,7 +1420,7 @@ def load_cve(cve, strict=False, srcmap=None):
 msg += "%s: %d: unknown entry '%s'\n" % (cve, linenum, rel)
 code = EXIT_FAIL
 continue
-affected.setdefault(pkg, dict())
+affected.setdefault(pkg, OrderedDict())
 if rel in affected[pkg]:
 msg += (
 "%s: %d: duplicate entry for '%s': original at line %d\n"
@@ -1433,7 +1434,7 @@ def load_cve(cve, strict=False, srcmap=None):
 code = EXIT_FAIL
 continue
 affected[pkg].setdefault(rel, [state, details])
-srcmap["pkgs"].setdefault(pkg, dict())
+srcmap["pkgs"].setdefault(pkg, OrderedDict())
 srcmap["pkgs"][pkg].setdefault(rel, (cve, linenum))
 elif field not in required_fields + extra_fields:
 msg += "%s: %d: unknown field '%s'\n" % (cve, linenum, field)
@@ -1539,9 +1540,9 @@ def amend_external_subproject_pkg(cve, data, srcmap, amendments, code, msg):
 if not success:
 return code, msg
 
-data.setdefault("pkgs", dict())
-data["pkgs"].setdefault(pkg, dict())
-srcmap["pkgs"].setdefault(pkg, dict())
+data.setdefault("pkgs", OrderedDict())
+data["pkgs"].setdefault(pkg, OrderedDict())
+srcmap["pkgs"].setdefault(pkg, OrderedDict())
 # override existing release info if it exists
 data["pkgs"][pkg][release] = [state, details]
 srcmap["pkgs"][pkg][release] = (cve, linenum)
diff --git a/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222 b/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
index 6d665be..30574d6 100644
--- a/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
+++ b/lib/lp/bugs/scripts/tests/sampledata/CVE-2022-23222
@@ -14,7 +14,7 @@ Ubuntu-Description:
  execute arbitrary code.
 Notes:
  sbeattie> Ubuntu 21.10 / 5.13+ kernels disable unprivileged BPF by default.
- sbeattie> kernels 5.

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:close-account into launchpad:master

2022-08-09 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:close-account 
into launchpad:master.

Commit message:
close-account script: skip references related to inactive products

announcement.registrant
milestonetag.created_by
productrelease.owner
productreleasefile.uploader

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/428085
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:close-account into launchpad:master.
diff --git a/lib/lp/registry/scripts/closeaccount.py b/lib/lp/registry/scripts/closeaccount.py
index c4e59fd..31e64ad 100644
--- a/lib/lp/registry/scripts/closeaccount.py
+++ b/lib/lp/registry/scripts/closeaccount.py
@@ -8,9 +8,11 @@ __all__ = [
 "CloseAccountScript",
 ]
 
+from typing import List, Tuple
+
 import six
 from storm.exceptions import IntegrityError
-from storm.expr import LeftJoin, Lower, Or
+from storm.expr import And, LeftJoin, Lower, Or
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
@@ -19,8 +21,12 @@ from lp.answers.model.question import Question
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.bugs.model.bugtask import BugTask
 from lp.registry.interfaces.person import PersonCreationRationale
+from lp.registry.model.announcement import Announcement
+from lp.registry.model.milestone import Milestone
+from lp.registry.model.milestonetag import MilestoneTag
 from lp.registry.model.person import Person, PersonSettings
 from lp.registry.model.product import Product
+from lp.registry.model.productrelease import ProductRelease, ProductReleaseFile
 from lp.registry.model.productseries import ProductSeries
 from lp.services.database import postgresql
 from lp.services.database.constants import DEFAULT
@@ -419,7 +425,7 @@ def close_account(username, log):
 "Can't delete non-trivial PPAs for user %s" % person_name
 )
 
-has_references = False
+reference_counts = []  # type: List[Tuple[str, int]]
 
 # Check for active related projects, and skip inactive ones.
 for col in "bug_supervisor", "driver", "owner":
@@ -434,11 +440,7 @@ def close_account(username, log):
 )
 count = result.get_one()[0]
 if count:
-log.error(
-"User %s is still referenced by %d product.%s values"
-% (person_name, count, col)
-)
-has_references = True
+reference_counts.append(("product.{}".format(col), count))
 skip.add(("product", col))
 for col in "driver", "owner":
 count = store.find(
@@ -448,13 +450,65 @@ def close_account(username, log):
 getattr(ProductSeries, col) == person,
 ).count()
 if count:
-log.error(
-"User %s is still referenced by %d productseries.%s values"
-% (person_name, count, col)
-)
-has_references = True
+reference_counts.append(("productseries.{}".format(col), count))
 skip.add(("productseries", col))
 
+# Check announcements, skipping the ones
+# that are related to inactive products.
+count = store.find(
+Announcement,
+Or(
+And(Announcement.product == Product.id, Product.active),
+Announcement.product == None,
+),
+Announcement.registrant == person,
+).count()
+if count:
+reference_counts.append(("announcement.registrant", count))
+skip.add(("announcement", "registrant"))
+
+# Check MilestoneTags, skipping the ones
+# that are related to inactive products / product series.
+count = store.find(
+MilestoneTag,
+MilestoneTag.milestone_id == Milestone.id,
+Or(
+And(Milestone.product == Product.id, Product.active),
+Milestone.product == None,
+),
+MilestoneTag.created_by_id == person.id,
+).count()
+if count:
+reference_counts.append(("milestonetag.created_by", count))
+skip.add(("milestonetag", "created_by"))
+
+# Check ProduceReleases, skipping the ones
+# that are related to inactive products / product series.
+count = store.find(
+ProductRelease,
+ProductRelease.milestone == Milestone.id,
+Milestone.product == Product.id,
+Product.active,
+ProductRelease.owner == person.id,
+).count()
+if count:
+reference_counts.append(("productrelease.owner", count))
+skip.add(("productrelease", "owner"))
+
+# Check ProduceReleases, skipping the ones
+# that are related to inactive pro

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-fixes into launchpad:master

2022-08-03 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-fixes into launchpad:master.

Commit message:
Fix the issues in the UCT import script


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427752

- Vulnerability.date_made_public requires a timezone-aware datetime instance 
but the script passes a naive datetime object.

- The log line after creating a vulnerability tries to log the vulnerability ID 
but the passed parameter is a Vulnerability instance.

- The transaction started by the script run is not committed. Colin suggested 
adding a --dry-run flag and either aborting or committing the transaction based 
on whether the flag is passed or not.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-fixes into launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/test_uctimport.py b/lib/lp/bugs/scripts/tests/test_uctimport.py
index 77a37d6..19f2904 100644
--- a/lib/lp/bugs/scripts/tests/test_uctimport.py
+++ b/lib/lp/bugs/scripts/tests/test_uctimport.py
@@ -4,6 +4,7 @@ import datetime
 from pathlib import Path
 from typing import List
 
+from pytz import UTC
 from zope.component import getUtility
 
 from lp.app.enums import InformationType
@@ -22,7 +23,7 @@ from lp.registry.interfaces.series import SeriesStatus
 from lp.registry.model.sourcepackage import SourcePackage
 from lp.services.propertycache import clear_property_cache
 from lp.testing import TestCase, TestCaseWithFactory
-from lp.testing.layers import ZopelessDatabaseLayer
+from lp.testing.layers import LaunchpadZopelessLayer, ZopelessDatabaseLayer
 
 
 class TestUCTRecord(TestCase):
@@ -352,7 +353,7 @@ class TextCVE(TestCaseWithFactory):
 
 class TestUCTImporter(TestCaseWithFactory):
 
-layer = ZopelessDatabaseLayer
+layer = LaunchpadZopelessLayer
 
 def setUp(self, *args, **kwargs):
 super().setUp(*args, **kwargs)
@@ -474,7 +475,8 @@ class TestUCTImporter(TestCaseWithFactory):
 notes="author> text",
 mitigation="mitigation",
 )
-self.importer = UCTImporter()
+self.layer.txn.commit()
+self.importer = UCTImporter(self.layer.txn)
 
 def checkBug(self, bug: Bug, cve: CVE):
 self.assertEqual(cve.sequence, bug.title)
@@ -797,3 +799,23 @@ class TestUCTImporter(TestCaseWithFactory):
 cve.references.pop(0)
 self.importer.update_bug(bug, cve, self.lp_cve)
 self.checkBug(bug, cve)
+
+def test_import_cve(self):
+self.importer.import_cve(self.cve)
+self.assertIsNotNone(
+self.importer.find_existing_bug(self.cve, self.lp_cve)
+)
+
+def test_import_cve_dry_run(self):
+importer = UCTImporter(self.layer.txn, dry_run=True)
+importer.import_cve(self.cve)
+self.assertIsNone(importer.find_existing_bug(self.cve, self.lp_cve))
+
+def test_naive_date_made_public(self):
+cve = self.cve
+cve.date_made_public = cve.date_made_public.replace(tzinfo=None)
+bug = self.importer.create_bug(cve, self.lp_cve)
+self.assertEqual(
+UTC,
+bug.vulnerabilities[0].date_made_public.tzinfo,
+)
diff --git a/lib/lp/bugs/scripts/uctimport.py b/lib/lp/bugs/scripts/uctimport.py
index 6d1c216..a1a8f23 100644
--- a/lib/lp/bugs/scripts/uctimport.py
+++ b/lib/lp/bugs/scripts/uctimport.py
@@ -16,7 +16,7 @@ For each entry in UCT we:
 4. Update the statuses of Bug Tasks based on the information in the CVE entry
 """
 import logging
-from datetime import datetime
+from datetime import datetime, timezone
 from enum import Enum
 from itertools import chain
 from pathlib import Path
@@ -543,7 +543,9 @@ class UCTImportError(Exception):
 
 
 class UCTImporter:
-def __init__(self):
+def __init__(self, transaction, dry_run=False):
+self.transaction = transaction
+self.dry_run = dry_run
 self.bug_importer = getUtility(ILaunchpadCelebrities).bug_importer
 
 def import_cve_from_file(self, cve_path: Path) -> None:
@@ -562,10 +564,21 @@ class UCTImporter:
 logger.warning("Could not find the CVE in LP: %s", cve.sequence)
 return
 bug = self.find_existing_bug(cve, lp_cve)
-if bug is None:
-self.create_bug(cve, lp_cve)
+self.transaction.begin()
+try:
+if bug is None:
+self.create_bug(cve, lp_cve)
+else:
+self.update_bug(bug, cve, lp_cve)
+except Exception:
+self.transaction.abort()
+raise
+
+if self.dry_run:
+logger.info("Dry-run mode enabled, all changes are reverted.")
+self.transaction.abort()
 else:
-self.update_bug(bug, cve, lp_cve)
+self.tra

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master

2022-07-31 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master.

Commit message:
Fix the `xx-bug.rst` doctests

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427657

Bugs API response now includes `vulnerabilities_collection_link` attribute
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master.
diff --git a/lib/lp/bugs/stories/webservice/xx-bug.rst b/lib/lp/bugs/stories/webservice/xx-bug.rst
index 2e73f9f..6543065 100644
--- a/lib/lp/bugs/stories/webservice/xx-bug.rst
+++ b/lib/lp/bugs/stories/webservice/xx-bug.rst
@@ -52,6 +52,7 @@ Bugs are indexed by number beneath the top-level collection.
   'http://.../bugs/1/users_affected_with_dupes'
 users_unaffected_collection_link: 'http://.../bugs/1/users_unaffected'
 users_unaffected_count: 0
+vulnerabilities_collection_link: 'http://.../bugs/1/vulnerabilities'
 web_link: 'http://bugs.../bugs/1'
 who_made_private_link: None
 
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:selenium into launchpad:master

2022-07-29 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:selenium into 
launchpad:master.

Commit message:
Increase the timeout value in html5browser test

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427612

Hopefully, this will prevent test flakiness in the build environment
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:selenium into launchpad:master.
diff --git a/lib/lp/testing/tests/test_html5browser.py b/lib/lp/testing/tests/test_html5browser.py
index 5118843..bdc6229 100644
--- a/lib/lp/testing/tests/test_html5browser.py
+++ b/lib/lp/testing/tests/test_html5browser.py
@@ -40,9 +40,9 @@ class TestBrowser(TestCase):
 results: {"spam": "ham"},
 type: "complete"
 });
-}, 200);
-}, 200);
-}, 100);
+}, 2000);
+}, 2000);
+}, 1000);
 };
 
 
@@ -55,7 +55,7 @@ class TestBrowser(TestCase):
 self.addCleanup(self.browser.close)
 
 def test_load_test_results(self):
-results = self.browser.run_tests(self.file_uri, timeout=1000)
+results = self.browser.run_tests(self.file_uri, timeout=1)
 self.assertEqual(results.status, results.Status.SUCCESS)
 self.assertEqual(
 results.results,
@@ -66,7 +66,7 @@ class TestBrowser(TestCase):
 )
 
 def test_timeout_error(self):
-results = self.browser.run_tests(self.file_uri, timeout=150)
+results = self.browser.run_tests(self.file_uri, timeout=1500)
 self.assertEqual(results.status, results.Status.TIMEOUT)
 self.assertIsNone(results.results)
 self.assertEqual(
@@ -76,7 +76,7 @@ class TestBrowser(TestCase):
 
 def test_incremental_timeout_success(self):
 results = self.browser.run_tests(
-self.file_uri, timeout=1000, incremental_timeout=300
+self.file_uri, timeout=1, incremental_timeout=3000
 )
 self.assertEqual(results.status, results.Status.SUCCESS)
 self.assertEqual(
@@ -89,7 +89,7 @@ class TestBrowser(TestCase):
 
 def test_incremental_timeout_error(self):
 results = self.browser.run_tests(
-self.file_uri, timeout=1000, incremental_timeout=150
+self.file_uri, timeout=1, incremental_timeout=1500
 )
 self.assertEqual(results.status, results.Status.TIMEOUT)
 self.assertIsNone(results.results)
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:selenium into launchpad:master

2022-07-28 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:selenium into 
launchpad:master.

Commit message:
Ensure the tests run after the document is fully loaded

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427598

Hopefully, this will prevent test flakiness
in different environments
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:selenium into launchpad:master.
diff --git a/lib/lp/testing/tests/test_html5browser.py b/lib/lp/testing/tests/test_html5browser.py
index 15db7b4..5118843 100644
--- a/lib/lp/testing/tests/test_html5browser.py
+++ b/lib/lp/testing/tests/test_html5browser.py
@@ -19,6 +19,7 @@ class TestBrowser(TestCase):
 """
 
 
+window.onload = function() {
 // First test
 setTimeout(function() {
 window.top.test_results = JSON.stringify({
@@ -42,6 +43,7 @@ class TestBrowser(TestCase):
 }, 200);
 }, 200);
 }, 100);
+};
 
 
 """
@@ -64,12 +66,12 @@ class TestBrowser(TestCase):
 )
 
 def test_timeout_error(self):
-results = self.browser.run_tests(self.file_uri, timeout=250)
+results = self.browser.run_tests(self.file_uri, timeout=150)
 self.assertEqual(results.status, results.Status.TIMEOUT)
 self.assertIsNone(results.results)
 self.assertEqual(
-results.last_test_message,
 {"testCase": "first", "testName": "first", "type": "passed"},
+results.last_test_message,
 )
 
 def test_incremental_timeout_success(self):
@@ -78,11 +80,11 @@ class TestBrowser(TestCase):
 )
 self.assertEqual(results.status, results.Status.SUCCESS)
 self.assertEqual(
-results.results,
 {
 "type": "complete",
 "results": {"spam": "ham"},
 },
+results.results,
 )
 
 def test_incremental_timeout_error(self):
@@ -92,6 +94,6 @@ class TestBrowser(TestCase):
 self.assertEqual(results.status, results.Status.TIMEOUT)
 self.assertIsNone(results.results)
 self.assertEqual(
-results.last_test_message,
 {"testCase": "first", "testName": "first", "type": "passed"},
+results.last_test_message,
 )
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] lp:~cjwatson/meta-lp-deps/remove-pyflakes into lp:meta-lp-deps

2022-07-28 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/meta-lp-deps/remove-pyflakes/+merge/427514
Your team Launchpad code reviewers is subscribed to branch lp:meta-lp-deps.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~cjwatson/launchpad:db-name-blocklist into launchpad:db-devel

2022-07-27 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/426843
Your team Launchpad code reviewers is requested to review the proposed merge of 
~cjwatson/launchpad:db-name-blocklist into launchpad:db-devel.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] lp:~cjwatson/lpbuildbot/focal into lp:lpbuildbot

2022-07-27 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/lpbuildbot/focal/+merge/426965
Your team Launchpad code reviewers is subscribed to branch lp:lpbuildbot.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] ~cjwatson/launchpad:db-sync-comments into launchpad:db-devel

2022-07-27 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/427020
Your team Launchpad code reviewers is requested to review the proposed merge of 
~cjwatson/launchpad:db-sync-comments into launchpad:db-devel.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


Re: [Launchpad-reviewers] [Merge] lp:~cjwatson/meta-lp-deps/remove-bzr-lpreview-body into lp:meta-lp-deps

2022-07-27 Thread Andrey Fedoseev
Review: Approve


-- 
https://code.launchpad.net/~cjwatson/meta-lp-deps/remove-bzr-lpreview-body/+merge/427154
Your team Launchpad code reviewers is subscribed to branch lp:meta-lp-deps.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master

2022-07-26 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:uct-import-update-existing 
into launchpad:master has been updated.

Description changed to:

The diff is probably too large to review. Instead, I start the review 
`utcimport.UCTImporter.import_cve_from_file` method and go from there.

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427275
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master

2022-07-26 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/launchpad:uct-import-update-existing 
into launchpad:master has been updated.

Commit message changed to:

Enable updating existing bugs from UCT CVE entries

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427275
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master

2022-07-22 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master.

Commit message:
Refactor the UCT import

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427275

This is an intermediary merge proposal

I refactored the UCT import script in preparation for updating the existing 
bugs and exporting CVEs back to the UCT flat file format
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-update-existing into launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/test_uctimport.py b/lib/lp/bugs/scripts/tests/test_uctimport.py
index 4b52c4d..4fbb17c 100644
--- a/lib/lp/bugs/scripts/tests/test_uctimport.py
+++ b/lib/lp/bugs/scripts/tests/test_uctimport.py
@@ -9,29 +9,21 @@ from lp.app.enums import InformationType
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.bugs.enums import VulnerabilityStatus
 from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus
-from lp.bugs.scripts.uctimport import (
-CVE,
-DistroSeriesPackageStatus,
-Note,
-Package,
-PackageStatus,
-Patch,
-Priority,
-UCTImporter,
-load_cve_from_file,
-)
+from lp.bugs.scripts.uctimport import CVE, UCTImporter, UCTRecord
 from lp.registry.interfaces.series import SeriesStatus
+from lp.registry.model.sourcepackage import SourcePackage
 from lp.testing import TestCase, TestCaseWithFactory
 from lp.testing.layers import ZopelessDatabaseLayer
 
 
-class TestLoadCVEFromFile(TestCase):
-def test_load_cve_from_file(self):
+class TestUCTRecord(TestCase):
+def test_load(self):
 cve_path = Path(__file__).parent / "sampledata" / "CVE-2022-23222"
-cve = load_cve_from_file(cve_path)
+uct_record = UCTRecord.load(cve_path)
 self.assertEqual(
-cve,
-CVE(
+uct_record,
+UCTRecord(
+path=cve_path,
 assigned_to="",
 bugs=[
 "https://github.com/mm2/Little-CMS/issues/29;,
@@ -63,7 +55,7 @@ class TestLoadCVEFromFile(TestCase):
 "seth-arnold> set kernel.unprivileged_bpf_disabled to 1"
 ),
 notes=[
-Note(
+UCTRecord.Note(
 author="sbeattie",
 text=(
 "Ubuntu 21.10 / 5.13+ kernels disable "
@@ -73,7 +65,7 @@ class TestLoadCVEFromFile(TestCase):
 ),
 ),
 ],
-priority=Priority.CRITICAL,
+priority=UCTRecord.Priority.CRITICAL,
 references=["https://ubuntu.com/security/notices/USN-5368-1;],
 ubuntu_description=(
 "It was discovered that the BPF verifier in the Linux "
@@ -83,24 +75,24 @@ class TestLoadCVEFromFile(TestCase):
 "execute arbitrary code."
 ),
 packages=[
-Package(
+UCTRecord.Package(
 name="linux",
 statuses=[
-DistroSeriesPackageStatus(
+UCTRecord.DistroSeriesPackageStatus(
 distroseries="devel",
-status=PackageStatus.NOT_AFFECTED,
+status=UCTRecord.PackageStatus.NOT_AFFECTED,
 reason="5.15.0-25.25",
-priority=Priority.MEDIUM,
+priority=UCTRecord.Priority.MEDIUM,
 ),
-DistroSeriesPackageStatus(
+UCTRecord.DistroSeriesPackageStatus(
 distroseries="impish",
-status=PackageStatus.RELEASED,
+status=UCTRecord.PackageStatus.RELEASED,
 reason="5.13.0-37.42",
-priority=Priority.MEDIUM,
+priority=UCTRecord.Priority.MEDIUM,
 ),
-DistroSeriesPackageStatus(
+UCTRecord.DistroSeriesPackageStatus(
 distroseries="upstream",
-status=PackageStatus.RELEASED,
+status=UCTRecord.PackageStatus.RELEASED,
 reason="5.17~rc1",
 priority=None,

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import-vulnerability-status into launchpad:master

2022-07-20 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:uct-import-vulnerability-status into 
launchpad:master.

Commit message:
Infer vulnerability status based on the parent folder of the CVE file.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427152
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import-vulnerability-status into 
launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/test_uctimport.py b/lib/lp/bugs/scripts/tests/test_uctimport.py
index 4b52c4d..cec212f 100644
--- a/lib/lp/bugs/scripts/tests/test_uctimport.py
+++ b/lib/lp/bugs/scripts/tests/test_uctimport.py
@@ -32,6 +32,7 @@ class TestLoadCVEFromFile(TestCase):
 self.assertEqual(
 cve,
 CVE(
+path=cve_path,
 assigned_to="",
 bugs=[
 "https://github.com/mm2/Little-CMS/issues/29;,
@@ -187,6 +188,7 @@ class TestUCTImporter(TestCaseWithFactory):
 
 now = datetime.datetime.now(datetime.timezone.utc)
 cve = CVE(
+path=Path("./ubuntu-cve-tracker/active/CVE-2022-23222"),
 assigned_to=assignee.name,
 bugs=[
 "https://github.com/mm2/Little-CMS/issues/29;,
@@ -351,9 +353,7 @@ class TestUCTImporter(TestCaseWithFactory):
 self.assertEqual(vulnerability.distribution, ubuntu)
 self.assertEqual(vulnerability.creator, owner)
 self.assertEqual(vulnerability.cve, lp_cve)
-self.assertEqual(
-vulnerability.status, VulnerabilityStatus.NEEDS_TRIAGE
-)
+self.assertEqual(vulnerability.status, VulnerabilityStatus.ACTIVE)
 self.assertEqual(vulnerability.description, "description")
 self.assertEqual(vulnerability.notes, "author> text")
 self.assertEqual(vulnerability.mitigation, "mitigation")
diff --git a/lib/lp/bugs/scripts/uctimport.py b/lib/lp/bugs/scripts/uctimport.py
index a625c3d..b84da62 100644
--- a/lib/lp/bugs/scripts/uctimport.py
+++ b/lib/lp/bugs/scripts/uctimport.py
@@ -133,6 +133,7 @@ Note = NamedTuple(
 CVE = NamedTuple(
 "CVE",
 [
+("path", Path),
 ("assigned_to", str),
 ("bugs", List[str]),
 ("cvss", List[Dict[str, Any]]),
@@ -161,7 +162,7 @@ class UCTImporter:
 Priority.NEGLIGIBLE: BugTaskImportance.WISHLIST,
 }
 
-STATUS_MAP = {
+BUG_TASK_STATUS_MAP = {
 PackageStatus.IGNORED: BugTaskStatus.WONTFIX,
 PackageStatus.NEEDS_TRIAGE: BugTaskStatus.UNKNOWN,
 PackageStatus.DOES_NOT_EXIST: BugTaskStatus.DOESNOTEXIST,
@@ -173,6 +174,12 @@ class UCTImporter:
 PackageStatus.PENDING: BugTaskStatus.FIXCOMMITTED,
 }
 
+VULNERABILITY_STATUS_MAP = {
+"active": VulnerabilityStatus.ACTIVE,
+"ignored": VulnerabilityStatus.IGNORED,
+"retired": VulnerabilityStatus.RETIRED,
+}
+
 def __init__(self, logger: Optional[logging.Logger] = None) -> None:
 self.logger = logger or DEFAULT_LOGGER
 
@@ -231,7 +238,7 @@ class UCTImporter:
 )
 if distro_series is None:
 continue
-if cve_package_status.status not in self.STATUS_MAP:
+if cve_package_status.status not in self.BUG_TASK_STATUS_MAP:
 self.logger.warning(
 "Can't find a suitable bug task status for %s",
 cve_package_status.status,
@@ -263,7 +270,7 @@ class UCTImporter:
 else None
 )
 statuses_with_explanations[series_package] = (
-self.STATUS_MAP[cve_package_status.status],
+self.BUG_TASK_STATUS_MAP[cve_package_status.status],
 cve_package_status.reason,
 )
 
@@ -422,7 +429,7 @@ class UCTImporter:
 distribution=distribution,
 creator=bug.owner,
 cve=lp_cve,
-status=VulnerabilityStatus.NEEDS_TRIAGE,
+status=self.infer_vulnerability_status(cve),
 description=cve.description,
 notes=format_cve_notes(cve.notes),
 mitigation=cve.mitigation,
@@ -437,6 +444,15 @@ class UCTImporter:
 
 return vulnerability
 
+def infer_vulnerability_status(self, cve: CVE) -> VulnerabilityStatus:
+"""
+Infer vulnerability status based on the parent folder of the CVE file.
+"""
+cve_folder_name = cve.path.absolute().parent.name
+return self.VULNERABILITY_STATUS_MAP.get(
+cve_folder_name, VulnerabilityStatus.NEEDS_TRIAGE
+)
+
 
 def load_

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:uct-import into launchpad:master

2022-07-20 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:uct-import into 
launchpad:master.

Commit message:
Fix the test for the import bug activity

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/427146
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:uct-import into launchpad:master.
diff --git a/lib/lp/bugs/scripts/tests/test_uctimport.py b/lib/lp/bugs/scripts/tests/test_uctimport.py
index fc66d82..4b52c4d 100644
--- a/lib/lp/bugs/scripts/tests/test_uctimport.py
+++ b/lib/lp/bugs/scripts/tests/test_uctimport.py
@@ -336,12 +336,14 @@ class TestUCTImporter(TestCaseWithFactory):
 
 self.assertEqual(bug.cves, [lp_cve])
 
-activities = bug.activity
-self.assertEqual(len(activities), 1)
-activity = activities[0]
-self.assertEqual(activity.person, owner)
-self.assertEqual(activity.whatchanged, "bug")
-self.assertEqual(activity.message, "UCT CVE entry CVE-2022-23222")
+activities = list(bug.activity)
+self.assertEqual(len(activities), 16)
+import_bug_activity = activities[-1]
+self.assertEqual(import_bug_activity.person, owner)
+self.assertEqual(import_bug_activity.whatchanged, "bug")
+self.assertEqual(
+import_bug_activity.message, "UCT CVE entry CVE-2022-23222"
+)
 
 self.assertEqual(len(vulnerabilities), 1)
 
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:update-twisted into launchpad:master

2022-07-15 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:update-twisted 
into launchpad:master.

Commit message:
Update Twisted to 20.3.0+lp9

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/426947
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:update-twisted into launchpad:master.
diff --git a/requirements/launchpad.txt b/requirements/launchpad.txt
index 984e30f..f884e1a 100644
--- a/requirements/launchpad.txt
+++ b/requirements/launchpad.txt
@@ -168,7 +168,7 @@ testtools==2.5.0
 timeline==0.0.7
 treq==18.6.0
 # lp:~launchpad/twisted:lp-backport
-Twisted==20.3.0+lp8
+Twisted==20.3.0+lp9
 txfixtures==0.4.3
 txpkgupload==0.4
 urllib3==1.25.11
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:ci-build-email into launchpad:master

2022-07-14 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/launchpad:ci-build-email 
into launchpad:master.

Commit message:
Add email notification for failed CI builds

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/426866

The code is mostly based on email notifications for Snap builds
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:ci-build-email into launchpad:master.
diff --git a/lib/lp/code/emailtemplates/cibuild-notification.txt b/lib/lp/code/emailtemplates/cibuild-notification.txt
new file mode 100644
index 000..a1fe129
--- /dev/null
+++ b/lib/lp/code/emailtemplates/cibuild-notification.txt
@@ -0,0 +1,9 @@
+ * Git Repository: %(git_repository)s
+ * Commit: %(commit_sha1)s
+ * Distroseries: %(distroseries)s
+ * Architecture: %(architecturetag)s
+ * State: %(build_state)s
+ * Duration: %(build_duration)s
+ * Build Log: %(log_url)s
+ * Upload Log: %(upload_log_url)s
+ * Builder: %(builder_url)s
diff --git a/lib/lp/code/mail/cibuild.py b/lib/lp/code/mail/cibuild.py
new file mode 100644
index 000..1183db8
--- /dev/null
+++ b/lib/lp/code/mail/cibuild.py
@@ -0,0 +1,86 @@
+#  Copyright 2022 Canonical Ltd.  This software is licensed under the
+#  GNU Affero General Public License version 3 (see the file LICENSE).
+
+__all__ = [
+"CIBuildMailer",
+]
+
+from lp.app.browser.tales import DurationFormatterAPI
+from lp.code.model.cibuild import CIBuild
+from lp.services.config import config
+from lp.services.mail.basemailer import (
+BaseMailer,
+RecipientReason,
+)
+from lp.services.webapp import canonical_url
+
+
+class CIBuildMailer(BaseMailer):
+
+app = "code"
+
+@classmethod
+def forStatus(cls, build: CIBuild):
+"""Create a mailer for notifying about snap package build status.
+
+:param build: The relevant build.
+"""
+repository_owner = build.git_repository.owner
+recipients = {
+repository_owner: RecipientReason.forBuildRequester(
+repository_owner
+)
+}
+return cls(
+build,
+"[CI build #%(build_id)d] %(build_title)s",
+"cibuild-notification.txt",
+recipients,
+config.canonical.noreply_from_address,
+notification_type="ci-build-status",
+)
+
+def __init__(self, build: CIBuild, *args, **kwargs):
+self.build = build
+super().__init__(*args, **kwargs)
+
+def _getHeaders(self, email, recipient):
+"""See `BaseMailer`."""
+headers = super()._getHeaders(email, recipient)
+headers["X-Launchpad-Build-State"] = self.build.status.name
+return headers
+
+def _getTemplateParams(self, email, recipient):
+"""See `BaseMailer`."""
+build = self.build
+params = super()._getTemplateParams(email, recipient)
+params.update(
+{
+"build_id": build.id,
+"build_title": build.title,
+"git_repository": build.git_repository.unique_name,
+"commit_sha1": build.commit_sha1,
+"distroseries": build.distro_series,
+"architecturetag": build.arch_tag,
+"build_state": build.status.title,
+"build_duration": "",
+"log_url": "",
+"upload_log_url": "",
+"builder_url": "",
+"build_url": canonical_url(build),
+}
+)
+if build.duration is not None:
+duration_formatter = DurationFormatterAPI(build.duration)
+params["build_duration"] = duration_formatter.approximateduration()
+if build.log is not None:
+params["log_url"] = build.log_url
+if build.upload_log is not None:
+params["upload_log_url"] = build.upload_log_url
+if build.builder is not None:
+params["builder_url"] = canonical_url(build.builder)
+return params
+
+def _getFooter(self, email, recipient, params):
+"""See `BaseMailer`."""
+return "{build_url}\n{reason}\n".format(**params)
diff --git a/lib/lp/code/model/cibuild.py b/lib/lp/code/model/cibuild.py
index 281c3a1..0ec5581 100644
--- a/lib/lp/code/model/cibuild.py
+++ b/lib/lp/code/model/cibuild.py
@@ -69,6 +69,7 @@ from lp.registry.interfaces.sourcepackage import SourcePackageType
 from lp.registry.model.distribution import Distribution
 

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/turnip:update-twisted into turnip:master

2022-07-13 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging ~andrey-fedoseev/turnip:update-twisted 
into turnip:master.

Commit message:
Upgrade Twisted to 20.3.0+lp9

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/turnip/+git/turnip/+merge/426821
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/turnip:update-twisted into turnip:master.
diff --git a/requirements.txt b/requirements.txt
index 3eff0f0..8d5734d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -66,7 +66,7 @@ traceback2==1.4.0
 translationstring==1.3
 # Assorted backports of upstream Twisted PRs.  See
 # https://code.launchpad.net/~launchpad/twisted/+git/twisted/+ref/lp-backport.
-Twisted[conch_nacl]==20.3.0+lp8
+Twisted[conch_nacl]==20.3.0+lp9
 unittest2==1.1.0
 vine==1.3.0
 venusian==2.1.0
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/turnip/+git/dependencies:update-twisted into ~canonical-launchpad-branches/turnip/+git/dependencies:master

2022-07-13 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/turnip/+git/dependencies:update-twisted into 
~canonical-launchpad-branches/turnip/+git/dependencies:master.

Commit message:
Upgrade Twisted to 20.3.0+lp9

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/turnip/+git/dependencies/+merge/426820
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/turnip/+git/dependencies:update-twisted into 
~canonical-launchpad-branches/turnip/+git/dependencies:master.
diff --git a/Twisted-20.3.0+lp9.tar.gz b/Twisted-20.3.0+lp9.tar.gz
new file mode 100644
index 000..4cf21b2
Binary files /dev/null and b/Twisted-20.3.0+lp9.tar.gz differ
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master

2022-07-13 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/turnip/+git/dependencies:update-twisted 
into turnip:master has been updated.

Status: Work in progress => Superseded

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/turnip/+git/dependencies/+merge/426818
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master

2022-07-13 Thread Andrey Fedoseev
The proposal to merge ~andrey-fedoseev/turnip/+git/dependencies:update-twisted 
into turnip:master has been updated.

Status: Needs review => Work in progress

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/turnip/+git/dependencies/+merge/426818
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master.


___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master

2022-07-13 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master.

Commit message:
Upgrade Twisted to 20.3.0+lp9

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #907675 in turnip: "Add support for Ed25519 SSH keys"
  https://bugs.launchpad.net/turnip/+bug/907675
  Bug #1933722 in turnip: "Launchpad doesn't support secure SSH parameters"
  https://bugs.launchpad.net/turnip/+bug/1933722

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/turnip/+git/dependencies/+merge/426818
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/turnip/+git/dependencies:update-twisted into turnip:master.
diff --git a/Automat-0.6.0.tar.gz b/Automat-0.6.0.tar.gz
new file mode 100644
index 000..6bdeb92
Binary files /dev/null and b/Automat-0.6.0.tar.gz differ
diff --git a/Automat-20.2.0.tar.gz b/Automat-20.2.0.tar.gz
new file mode 100644
index 000..4b39472
Binary files /dev/null and b/Automat-20.2.0.tar.gz differ
diff --git a/Jinja2-2.10.tar.gz b/Jinja2-2.10.tar.gz
new file mode 100644
index 000..c311087
Binary files /dev/null and b/Jinja2-2.10.tar.gz differ
diff --git a/Mako-1.0.1.tar.gz b/Mako-1.0.1.tar.gz
new file mode 100644
index 000..0052984
Binary files /dev/null and b/Mako-1.0.1.tar.gz differ
diff --git a/MarkupSafe-0.23.tar.gz b/MarkupSafe-0.23.tar.gz
new file mode 100644
index 000..6b19006
Binary files /dev/null and b/MarkupSafe-0.23.tar.gz differ
diff --git a/Paste-2.0.2.tar.gz b/Paste-2.0.2.tar.gz
new file mode 100644
index 000..1ebbce7
Binary files /dev/null and b/Paste-2.0.2.tar.gz differ
diff --git a/Paste-3.5.0.tar.gz b/Paste-3.5.0.tar.gz
new file mode 100644
index 000..153724e
Binary files /dev/null and b/Paste-3.5.0.tar.gz differ
diff --git a/PasteDeploy-1.5.2.tar.gz b/PasteDeploy-1.5.2.tar.gz
new file mode 100644
index 000..fd4f9e1
Binary files /dev/null and b/PasteDeploy-1.5.2.tar.gz differ
diff --git a/PasteDeploy-2.1.0.tar.gz b/PasteDeploy-2.1.0.tar.gz
new file mode 100644
index 000..fa4588a
Binary files /dev/null and b/PasteDeploy-2.1.0.tar.gz differ
diff --git a/PyHamcrest-1.10.1.tar.gz b/PyHamcrest-1.10.1.tar.gz
new file mode 100644
index 000..2732ba2
Binary files /dev/null and b/PyHamcrest-1.10.1.tar.gz differ
diff --git a/PyNaCl-1.3.0.tar.gz b/PyNaCl-1.3.0.tar.gz
new file mode 100644
index 000..c50c491
Binary files /dev/null and b/PyNaCl-1.3.0.tar.gz differ
diff --git a/PyYAML-3.11.zip b/PyYAML-3.11.zip
new file mode 100644
index 000..c361e86
Binary files /dev/null and b/PyYAML-3.11.zip differ
diff --git a/PyYAML-5.3.tar.gz b/PyYAML-5.3.tar.gz
new file mode 100644
index 000..1ac6859
Binary files /dev/null and b/PyYAML-5.3.tar.gz differ
diff --git a/SQLAlchemy-0.9.9.tar.gz b/SQLAlchemy-0.9.9.tar.gz
new file mode 100644
index 000..3323458
Binary files /dev/null and b/SQLAlchemy-0.9.9.tar.gz differ
diff --git a/Tempita-0.5.2.tar.gz b/Tempita-0.5.2.tar.gz
new file mode 100644
index 000..755befc
Binary files /dev/null and b/Tempita-0.5.2.tar.gz differ
diff --git a/Twisted-15.0.0.tar.bz2 b/Twisted-15.0.0.tar.bz2
new file mode 100644
index 000..56247f0
Binary files /dev/null and b/Twisted-15.0.0.tar.bz2 differ
diff --git a/Twisted-15.4.0.tar.bz2 b/Twisted-15.4.0.tar.bz2
new file mode 100644
index 000..91a28de
Binary files /dev/null and b/Twisted-15.4.0.tar.bz2 differ
diff --git a/Twisted-15.5.0.tar.bz2 b/Twisted-15.5.0.tar.bz2
new file mode 100644
index 000..bfc6f92
Binary files /dev/null and b/Twisted-15.5.0.tar.bz2 differ
diff --git a/Twisted-16.5.0.tar.bz2 b/Twisted-16.5.0.tar.bz2
new file mode 100644
index 000..52cf7a0
Binary files /dev/null and b/Twisted-16.5.0.tar.bz2 differ
diff --git a/Twisted-17.9.0.tar.bz2 b/Twisted-17.9.0.tar.bz2
new file mode 100644
index 000..9a8cfc9
Binary files /dev/null and b/Twisted-17.9.0.tar.bz2 differ
diff --git a/Twisted-18.4.0.tar.bz2 b/Twisted-18.4.0.tar.bz2
new file mode 100644
index 000..d0319eb
Binary files /dev/null and b/Twisted-18.4.0.tar.bz2 differ
diff --git a/Twisted-18.9.0.tar.bz2 b/Twisted-18.9.0.tar.bz2
new file mode 100644
index 000..e76adf1
Binary files /dev/null and b/Twisted-18.9.0.tar.bz2 differ
diff --git a/Twisted-20.3.0+lp1.tar.bz2 b/Twisted-20.3.0+lp1.tar.bz2
new file mode 100644
index 000..ade154c
Binary files /dev/null and b/Twisted-20.3.0+lp1.tar.bz2 differ
diff --git a/Twisted-20.3.0+lp2.tar.bz2 b/Twisted-20.3.0+lp2.tar.bz2
new file mode 100644
index 000..21d1548
Binary files /dev/null and b/Twisted-20.3.0+lp2.tar.bz2 differ
diff --git a/Twisted-20.3.0+lp3.tar.bz2 b/Twisted-20.3.0+lp3.tar.bz2
new file mode 100644
index 000..ddb610c
Binary files /dev/null and b/Twisted-20.3.0+lp3.tar.bz2 differ
diff --git a/Twisted-20.3.0+lp4.tar.bz2 b/Twisted-20.3.0+lp4.tar.bz2
new file mode 100644
index 000..ddcaa44
Binary files /dev/null and b/Twisted-20.3.0+lp4.tar.bz2 differ
diff --

[Launchpad-reviewers] [Merge] ~andrey-fedoseev/lp-source-dependencies:update-twisted into lp-source-dependencies:master

2022-07-13 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/lp-source-dependencies:update-twisted into 
lp-source-dependencies:master.

Commit message:
Upgrade Twisted to 20.3.0+lp9

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/lp-source-dependencies/+git/lp-source-dependencies/+merge/426809
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/lp-source-dependencies:update-twisted into 
lp-source-dependencies:master.
diff --git a/dist/Twisted-20.3.0+lp9.tar.gz b/dist/Twisted-20.3.0+lp9.tar.gz
new file mode 100644
index 000..4cf21b2
Binary files /dev/null and b/dist/Twisted-20.3.0+lp9.tar.gz differ
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad:remove-launchpad-object-factory into launchpad:master

2022-07-12 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad:remove-launchpad-object-factory into 
launchpad:master.

Commit message:
Remove `LaunchpadObjectFactory` wrapper


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad/+git/launchpad/+merge/426693

This wrapper is supposed to be used to produce warning message
whenever a factory method creates an object which isn't wrapped
in security proxy. However, this is enabled only when
LP_PROXY_WARNINGS=1 is set, and no one seems to be using it.

The wrapper implementation hides the list of available methods
of the underlying factory class which prevents code analysis,
so we decided to remove the wrapper.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad:remove-launchpad-object-factory into 
launchpad:master.
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 61c3b2d..b6e7442 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -535,7 +535,7 @@ class ObjectFactory(metaclass=AutoDecorate(default_master_store)):
 return epoch + timedelta(minutes=self.getUniqueInteger())
 
 
-class BareLaunchpadObjectFactory(ObjectFactory):
+class LaunchpadObjectFactory(ObjectFactory):
 """Factory methods for creating Launchpad objects.
 
 All the factory methods should be callable with no parameters.
@@ -5521,15 +5521,6 @@ def is_security_proxied_or_harmless(obj):
 return False
 
 
-class UnproxiedFactoryMethodWarning(UserWarning):
-"""Raised when someone calls an unproxied factory method."""
-
-def __init__(self, method_name):
-super().__init__(
-"PLEASE FIX: LaunchpadObjectFactory.%s returns an "
-"unproxied object." % (method_name, ))
-
-
 class ShouldThisBeUsingRemoveSecurityProxy(UserWarning):
 """Raised when there is a potentially bad call to removeSecurityProxy."""
 
@@ -5540,42 +5531,6 @@ class ShouldThisBeUsingRemoveSecurityProxy(UserWarning):
 super().__init__(message)
 
 
-class LaunchpadObjectFactory:
-"""A wrapper around `BareLaunchpadObjectFactory`.
-
-Ensure that each object created by a `BareLaunchpadObjectFactory` method
-is either of a simple Python type or is security proxied.
-
-A warning message is printed to stderr if a factory method creates
-an object without a security proxy.
-
-Whereever you see such a warning: fix it!
-"""
-
-def __init__(self):
-self._factory = BareLaunchpadObjectFactory()
-
-def __getattr__(self, name):
-attr = getattr(self._factory, name)
-if os.environ.get('LP_PROXY_WARNINGS') == '1' and callable(attr):
-
-def guarded_method(*args, **kw):
-result = attr(*args, **kw)
-if not is_security_proxied_or_harmless(result):
-warnings.warn(
-UnproxiedFactoryMethodWarning(name), stacklevel=1)
-return result
-return guarded_method
-else:
-return attr
-
-def __dir__(self):
-"""Enumerate the attributes and methods of the wrapped object factory.
-
-This is especially useful for interactive users."""
-return dir(self._factory)
-
-
 def remove_security_proxy_and_shout_at_engineer(obj):
 """Remove an object's security proxy and print a warning.
 
diff --git a/lib/lp/testing/tests/test_factory.py b/lib/lp/testing/tests/test_factory.py
index 4953455..1256e7b 100644
--- a/lib/lp/testing/tests/test_factory.py
+++ b/lib/lp/testing/tests/test_factory.py
@@ -644,14 +644,6 @@ class TestFactory(TestCaseWithFactory):
 sequence='2000-1234', cvestate=CveStatus.DEPRECATED)
 self.assertEqual(CveStatus.DEPRECATED, cve.status)
 
-# dir() support.
-def test_dir(self):
-# LaunchpadObjectFactory supports dir() even though all of its
-# attributes are pseudo-attributes.
-self.assertEqual(
-dir(self.factory._factory),
-dir(self.factory))
-
 def test_getUniqueString_with_prefix(self):
 s = self.factory.getUniqueString("with-my-prefix")
 self.assertTrue(s.startswith("with-my-prefix"))
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] lp:~andrey-fedoseev/meta-lp-deps/firefox-geckodriver into lp:meta-lp-deps

2022-07-11 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
lp:~andrey-fedoseev/meta-lp-deps/firefox-geckodriver into lp:meta-lp-deps.

Commit message:
Add firefox-geckodriver to launchpad-developer-dependencies;

this is required for Selenium-based test browser


Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/meta-lp-deps/firefox-geckodriver/+merge/426609
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~andrey-fedoseev/meta-lp-deps/firefox-geckodriver into lp:meta-lp-deps.
=== modified file 'debian/changelog'
--- debian/changelog	2022-06-23 10:25:04 +
+++ debian/changelog	2022-07-11 08:27:21 +
@@ -1,10 +1,15 @@
 launchpad-dependencies (0.142) UNRELEASED; urgency=medium
 
+  [ Colin Watson ]
   * Remove pointless Recommends from launchpad-dependencies to
 launchpad-database-dependencies.
   * Remove Recommends on postgresql-doc-9.3; wasn't up to date, and can
 easily be viewed online.
 
+  [ Andrey Fedoseev ]
+  * Add firefox-geckodriver to launchpad-developer-dependencies;
+this is required for Selenium-based test browser
+
  -- Colin Watson   Fri, 06 May 2022 12:26:43 +0200
 
 launchpad-dependencies (0.141) xenial; urgency=medium

=== modified file 'debian/control'
--- debian/control	2022-06-23 10:25:04 +
+++ debian/control	2022-07-11 08:27:21 +
@@ -56,7 +56,7 @@
   pgbouncer (>= 1.6) | pgbouncer-with-disconnect, postgresql-autodoc, tidy,
   mhonarc,
   fakeroot, rsync, memcached,
-  xvfb, firefox, intltool,
+  xvfb, firefox, firefox-geckodriver, intltool,
   gir1.2-glib-2.0,
   gir1.2-gtk-3.0,
   gir1.2-webkit-3.0,

___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


[Launchpad-reviewers] [Merge] ~andrey-fedoseev/launchpad-buildd:snap-target-architectures into launchpad-buildd:master

2022-07-08 Thread Andrey Fedoseev
Andrey Fedoseev has proposed merging 
~andrey-fedoseev/launchpad-buildd:snap-target-architectures into 
launchpad-buildd:master.

Commit message:
Replace SNAPCRAFT_BUILD_TO with SNAPCRAFT_BUILD_FOR

according to the updated snapcraft specification

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~andrey-fedoseev/launchpad-buildd/+git/launchpad-buildd/+merge/426571
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of 
~andrey-fedoseev/launchpad-buildd:snap-target-architectures into 
launchpad-buildd:master.
diff --git a/debian/changelog b/debian/changelog
index 8b90a45..7a37ee9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ launchpad-buildd (216) UNRELEASED; urgency=medium
 
   [ Andrey Fedoseev ]
   * Allow specifying target architecture for snaps via
-SNAPCRAFT_BUILD_TO environment variable
+SNAPCRAFT_BUILD_FOR environment variable
 
   [ Colin Watson ]
   * Add a timeout when revoking proxy tokens.
diff --git a/lpbuildd/target/build_snap.py b/lpbuildd/target/build_snap.py
index 751bb61..9a8efec 100644
--- a/lpbuildd/target/build_snap.py
+++ b/lpbuildd/target/build_snap.py
@@ -186,7 +186,7 @@ class BuildSnap(BuilderProxyOperationMixin, VCSOperationMixin,
 env["SNAPCRAFT_IMAGE_INFO"] = self.image_info
 env["SNAPCRAFT_BUILD_ENVIRONMENT"] = "host"
 if self.args.target_architectures:
-env["SNAPCRAFT_BUILD_TO"] = self.args.target_architectures[0]
+env["SNAPCRAFT_BUILD_FOR"] = self.args.target_architectures[0]
 output_path = os.path.join("/build", self.args.name)
 self.run_build_command(["snapcraft"], cwd=output_path, env=env)
 for entry in sorted(self.backend.listdir(output_path)):
diff --git a/lpbuildd/target/tests/test_build_snap.py b/lpbuildd/target/tests/test_build_snap.py
index 644a2c2..5d94d8d 100644
--- a/lpbuildd/target/tests/test_build_snap.py
+++ b/lpbuildd/target/tests/test_build_snap.py
@@ -521,7 +521,7 @@ class TestBuildSnap(TestCase):
 RanBuildCommand(
 ["snapcraft"], cwd="/build/test-snap",
 SNAPCRAFT_BUILD_INFO="1", SNAPCRAFT_IMAGE_INFO="{}",
-SNAPCRAFT_BUILD_ENVIRONMENT="host", SNAPCRAFT_BUILD_TO="i386"),
+SNAPCRAFT_BUILD_ENVIRONMENT="host", SNAPCRAFT_BUILD_FOR="i386"),
 ]))
 
 # XXX cjwatson 2017-08-07: Test revoke_token.  It may be easiest to
___
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to : launchpad-reviewers@lists.launchpad.net
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp


  1   2   >