From patchwork Wed Dec 17 02:28:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 959 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765938595; bh=ymn+vsJG8h0ShD6SQ19qqdKlwPTWX5AsDNbRxSVKCKo=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=d8gaPNGyzOQLqg/6bH0CKIoI1DQPEgAnGmbHa4vKuSKkibHKDW2uZQriqweFpmviX nWzqgxjosgSiw42/UzlTeRepwS/WqNFylWuG6Mx2iY18nFTvb/f3ct51XWT9ktRfAo tdqeCf0ty5Ks749XOA2KSqBDXaHTBEpjuTlT144ni9CbGQm4VF6pheyfX+K6vStEk7 cuUFTYzLO/XeSft9NZglyHph0ewES8r5ksBsS5tP2w+5KW+00Q5h04zOi8OzzIwRzf NH8zYio34Xhb9ceyOniPI/u94Mxt475a2B65AeABuXNwyKdhSKeR9f3L3N7R7Di/gW lWNOMpGCWo9GA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 480DA68BC7 for ; Tue, 16 Dec 2025 19:29:55 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id nt0__LUzLa1x for ; Tue, 16 Dec 2025 19:29:55 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765938595; bh=ymn+vsJG8h0ShD6SQ19qqdKlwPTWX5AsDNbRxSVKCKo=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=d8gaPNGyzOQLqg/6bH0CKIoI1DQPEgAnGmbHa4vKuSKkibHKDW2uZQriqweFpmviX nWzqgxjosgSiw42/UzlTeRepwS/WqNFylWuG6Mx2iY18nFTvb/f3ct51XWT9ktRfAo tdqeCf0ty5Ks749XOA2KSqBDXaHTBEpjuTlT144ni9CbGQm4VF6pheyfX+K6vStEk7 cuUFTYzLO/XeSft9NZglyHph0ewES8r5ksBsS5tP2w+5KW+00Q5h04zOi8OzzIwRzf NH8zYio34Xhb9ceyOniPI/u94Mxt475a2B65AeABuXNwyKdhSKeR9f3L3N7R7Di/gW lWNOMpGCWo9GA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3867A68BBD for ; Tue, 16 Dec 2025 19:29:55 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765938593; bh=2EXqJQgOhPPmNx8IUBLKw1pQg/CbLhRfQVmVU4mv8Pc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EskOPdM7HAPesMP1/e8PCIez3n7r6QfTh16Huimhgcfpda/Ak98S/IP6XDKuXc6cg hwLQuejuRQNE0DiiPlf6FRqWnCGV1ntQsDFTpGqfqPX4/pBNhcLvl+t23Pc2vXhAUW Hq5NcbZ/k6zSQ+KmwOsIaf5W7ByrNdrtHjodsTnIvdR6Nq2S5MtJpKU9CkM/uLXSId QC+7wakPALfXykrtXmoG6IJmaNM8VybMRDqkrWXrOiXIUbZbEdkt7HCQ6MIK/2Ssuq RpFncwR9r9IXbUJvXgiUZLm6pWvDGDtYGS09WbBXNNNcx64KvEXvYyiwPxhuN/jzuz ts2vKCKp1l+4Q== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 4F7C968AFD; Tue, 16 Dec 2025 19:29:53 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id Aa_mtwPpVGzs; Tue, 16 Dec 2025 19:29:53 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1765938589; bh=FU3m76pmNVDU7O5thuzqCEO689t593OUy1p1ERZBMg0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LUv+099rrH174Yaefs326/D1U/JFdS1FgDr5ZiHZZKemSejEouP0/hLKMrZEYmdta lCb9XNeeNMgNbheAK5cxcF2SRVx6bbKDXrQy0JCi9pIxwaO0ppHPcxFR2sB1Kzud4R pUjRpJ7T6XnGcwExhDVbNrnhuZDI75e7amt0mr6AatRGlBYBOXdbMM23YR8XceLQ/y WwyzyLtPV2OzggJIHIomeUn0OXP6E8wt/Nhqjgbtu6Q3vEJnjDnEybwdTs3tWuM0uh WBUqIKJx3Q68ml26hcBBx80BWep1Pzi4xedqhqJAkrmnbl7oS2xpt7ag/LwE0QlG0w wi/lNImpmAkLA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 2B26B6884F; Tue, 16 Dec 2025 19:29:49 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Tue, 16 Dec 2025 19:28:05 -0700 Message-ID: <20251217022823.392557-17-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251217022823.392557-1-sjg@u-boot.org> References: <20251217022823.392557-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 2QER7L7JN7WWKV4H3KU7PETLHS2EIA52 X-Message-ID-Hash: 2QER7L7JN7WWKV4H3KU7PETLHS2EIA52 X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 16/24] pickman: Add a way to update a gitlab merge-request List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Add function to update a merge request's description via the GitLab API. This is used to update the MR with the agent's conversation log after processing review comments. Co-developed-by: Claude Opus 4.5 Signed-off-by: Simon Glass --- tools/pickman/ftest.py | 42 +++++++++++++++++++++++++++++++++++++ tools/pickman/gitlab_api.py | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/tools/pickman/ftest.py b/tools/pickman/ftest.py index ae4ceaceaaa..ec9e7e91d65 100644 --- a/tools/pickman/ftest.py +++ b/tools/pickman/ftest.py @@ -1345,6 +1345,48 @@ class TestCheckAvailable(unittest.TestCase): self.assertTrue(result) +class TestUpdateMrDescription(unittest.TestCase): + """Tests for update_mr_description function.""" + + @mock.patch.object(gitlab_api, 'get_remote_url') + @mock.patch.object(gitlab_api, 'get_token') + @mock.patch.object(gitlab_api, 'AVAILABLE', True) + def test_update_mr_description_success(self, mock_token, mock_url): + """Test successful MR description update.""" + mock_token.return_value = 'test-token' + mock_url.return_value = 'git@gitlab.com:group/project.git' + + mock_mr = mock.MagicMock() + mock_project = mock.MagicMock() + mock_project.mergerequests.get.return_value = mock_mr + + with mock.patch('gitlab.Gitlab') as mock_gitlab: + mock_gitlab.return_value.projects.get.return_value = mock_project + + result = gitlab_api.update_mr_description('origin', 123, + 'New description') + + self.assertTrue(result) + self.assertEqual(mock_mr.description, 'New description') + mock_mr.save.assert_called_once() + + @mock.patch.object(gitlab_api, 'AVAILABLE', False) + def test_update_mr_description_not_available(self): + """Test update_mr_description when gitlab not available.""" + with terminal.capture(): + result = gitlab_api.update_mr_description('origin', 123, 'desc') + self.assertFalse(result) + + @mock.patch.object(gitlab_api, 'get_token') + @mock.patch.object(gitlab_api, 'AVAILABLE', True) + def test_update_mr_description_no_token(self, mock_token): + """Test update_mr_description when no token set.""" + mock_token.return_value = None + with terminal.capture(): + result = gitlab_api.update_mr_description('origin', 123, 'desc') + self.assertFalse(result) + + class TestParseApplyWithPush(unittest.TestCase): """Tests for apply command with push options.""" diff --git a/tools/pickman/gitlab_api.py b/tools/pickman/gitlab_api.py index d0128e13f80..508168aa75c 100644 --- a/tools/pickman/gitlab_api.py +++ b/tools/pickman/gitlab_api.py @@ -320,6 +320,43 @@ def reply_to_mr(remote, mr_iid, message): return False +def update_mr_description(remote, mr_iid, desc): + """Update a merge request's description + + Args: + remote (str): Remote name + mr_iid (int): Merge request IID + desc (str): New description + + Returns: + bool: True on success + """ + if not check_available(): + return False + + token = get_token() + if not token: + tout.error('GITLAB_TOKEN environment variable not set') + return False + + remote_url = get_remote_url(remote) + host, proj_path = parse_url(remote_url) + + if not host or not proj_path: + return False + + try: + glab = gitlab.Gitlab(f'https://{host}', private_token=token) + project = glab.projects.get(proj_path) + merge_req = project.mergerequests.get(mr_iid) + merge_req.description = desc + merge_req.save() + return True + except gitlab.exceptions.GitlabError as exc: + tout.error(f'GitLab API error: {exc}') + return False + + def push_and_create_mr(remote, branch, target, title, desc=''): """Push a branch and create a merge request