From patchwork Sun Feb 22 15:42:56 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1937 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=1771775085; bh=FCIWDmOKw8VDJDsHwTbmNkG4A5RQizZWiT1EmroJUMY=; 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=N+2Qw1Ba0wZXnwKcxOotrHf09HQjVUkY/E4O6104FAi5CjiZnDZI2IQDVvMbOe3py QogQEf9NgRxDp+jkBz/PEY+fk9VTNVuVfrp8BR+QmGJ202JZts9hgu6pk1giSRw+FD q5GCiuBJNEmnBSA9Y9o27i+i73Q6anxl9vO7JQkZ1l9oV1FVc+mkMkyKUc7pTeqTkO Fk2Afi0DYbF1az7xdelrPAa4WnzlxQPZZZ+97NbICiS6yFamuiQ7XQa1lca/4jzcmA IHD3ZpDUZSI0T4iUZTuxKduL0I6pLx0jFCJDWch3jz4Ar8E/TJ8UkdBeufvCrYXKkA CnZ2QwF54GfhA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 9278069D57 for ; Sun, 22 Feb 2026 08:44:45 -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 76In1AmibzRW for ; Sun, 22 Feb 2026 08:44:45 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1771775085; bh=FCIWDmOKw8VDJDsHwTbmNkG4A5RQizZWiT1EmroJUMY=; 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=N+2Qw1Ba0wZXnwKcxOotrHf09HQjVUkY/E4O6104FAi5CjiZnDZI2IQDVvMbOe3py QogQEf9NgRxDp+jkBz/PEY+fk9VTNVuVfrp8BR+QmGJ202JZts9hgu6pk1giSRw+FD q5GCiuBJNEmnBSA9Y9o27i+i73Q6anxl9vO7JQkZ1l9oV1FVc+mkMkyKUc7pTeqTkO Fk2Afi0DYbF1az7xdelrPAa4WnzlxQPZZZ+97NbICiS6yFamuiQ7XQa1lca/4jzcmA IHD3ZpDUZSI0T4iUZTuxKduL0I6pLx0jFCJDWch3jz4Ar8E/TJ8UkdBeufvCrYXKkA CnZ2QwF54GfhA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 7AA7769D48 for ; Sun, 22 Feb 2026 08:44:45 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1771775084; bh=IpEmwWewtt0dIG1uAOJ3xXHew+hnBEx1vHmNJI7xn38=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iZQ3X9/rFGoJpj/0Aa63Tg4AtCFhkU1wKjxZDiNm5nECIuoAxLnTEun3F8mXVKBo4 4qqEwTc3iB7hylLKlmcst6cjlBj2HKoQoYeonb+hfQpZgLHFU3VhYKEJrLOjnLLtt2 KAsNg09DRXZPm5CoRtHlIreRV9xC9NL4qJtZeu+e3WKoToJ1KznsCf/ORxtnRJOdJ0 hs9Co0zSZYwih+A2Qk76hQLDmYvq118/lLVvUHVslCZVnlnJa/v0O5KyRFks3CPTvp C/k2qJn9v9URfnzTJWahBeitYxziDFB+3o/jIms/2df4/qmxyZgC0UtknI+9JtDqF1 gi8FBkY72Q5Yg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C365769C5E; Sun, 22 Feb 2026 08:44:44 -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 KZLcbnTDONos; Sun, 22 Feb 2026 08:44:44 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1771775080; bh=ToDJZW985yzpZEH2cu9/fIefk0cHBOWXXfxIgwndUBI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qfhv8TckTZX+Z5JdnH4G8s9vRni1ddj3qnXHrUIaPdCeEqaT2MwXLJ+699+RBYNq2 03evmSMnDz9B1kTblyOSEGodaRtiXM7gTZl7JYXAR5wPZMUGXS94KY9Q8nBngZr3yL m/vU/kotHo7g1aZg22Pt/A0WxNtw7Oi5SxPGuB74oC5ZcMWIIfifz0gG4xxVC6JSlU /NMENywh08Fr38c4ywjEiogM2JWcVmz19ES1J1L84JQbO6WE8vhkZMgUMwjTFR7dBP WVZy+5t0eDWYT/Z4/2DRwn6Yte2GJbm+zxfhnSc8H7YJ/9aqS1OiLvyWahIKZxUWgW QdlLi4x+ZscDA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 4BDB169C5C; Sun, 22 Feb 2026 08:44:40 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Sun, 22 Feb 2026 08:42:56 -0700 Message-ID: <20260222154303.2851319-17-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260222154303.2851319-1-sjg@u-boot.org> References: <20260222154303.2851319-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: C2DFXLCJ7Q2HMDHNN5YBCVEHLCQSRVUT X-Message-ID-Hash: C2DFXLCJ7Q2HMDHNN5YBCVEHLCQSRVUT 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 . 6" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 16/16] pickman: Strip null bytes from CI job logs 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 CI job traces can contain embedded null bytes, which cause a ValueError ("embedded null byte") when the prompt string is passed to the Claude Agent SDK subprocess. Strip null bytes from the trace after decoding. Co-developed-by: Claude Opus 4.6 Signed-off-by: Simon Glass --- tools/pickman/ftest.py | 35 +++++++++++++++++++++++++++++++++++ tools/pickman/gitlab_api.py | 1 + 2 files changed, 36 insertions(+) diff --git a/tools/pickman/ftest.py b/tools/pickman/ftest.py index ced2c79ac87..5a4d0c433dc 100644 --- a/tools/pickman/ftest.py +++ b/tools/pickman/ftest.py @@ -5787,6 +5787,41 @@ class TestGetFailedJobs(unittest.TestCase): self.assertIn('line 499', result[0].log_tail) + @mock.patch.object(gitlab, 'get_remote_url', + return_value=TEST_SSH_URL) + @mock.patch.object(gitlab, 'get_token', return_value='test-token') + @mock.patch.object(gitlab, 'AVAILABLE', True) + def test_null_bytes_stripped(self, _mock_token, _mock_url): + """Test that null bytes in job logs are stripped""" + trace_bytes = b'before\x00after\nline2\x00end\n' + + mock_job = self._make_mock_job( + 1, 'build:sandbox', 'build', 'https://gitlab.com/job/1', + trace_bytes) + + mock_full_job = mock.MagicMock() + mock_full_job.trace.return_value = trace_bytes + + mock_pipeline = mock.MagicMock() + mock_pipeline.jobs.list.return_value = [mock_job] + + mock_project = mock.MagicMock() + mock_project.pipelines.get.return_value = mock_pipeline + mock_project.jobs.get.return_value = mock_full_job + + mock_glab = mock.MagicMock() + mock_glab.projects.get.return_value = mock_project + + with mock.patch('gitlab.Gitlab', return_value=mock_glab): + with terminal.capture(): + result = gitlab.get_failed_jobs('ci', 100) + + self.assertEqual(len(result), 1) + self.assertNotIn('\0', result[0].log_tail) + self.assertIn('beforeafter', result[0].log_tail) + self.assertIn('line2end', result[0].log_tail) + + class TestBuildPipelineFixPrompt(unittest.TestCase): """Tests for build_pipeline_fix_prompt function.""" diff --git a/tools/pickman/gitlab_api.py b/tools/pickman/gitlab_api.py index d9635d392ee..81918c80c3c 100644 --- a/tools/pickman/gitlab_api.py +++ b/tools/pickman/gitlab_api.py @@ -478,6 +478,7 @@ def get_failed_jobs(remote, pipeline_id, max_log_lines=200): full_job = project.jobs.get(job.id) try: trace = full_job.trace().decode('utf-8', errors='replace') + trace = trace.replace('\0', '') lines = trace.splitlines() log_tail = '\n'.join(lines[-max_log_lines:]) except (AttributeError, gitlab.exceptions.GitlabError):