Break long lines to comply with 80-character limit and remove trailing
whitespace across agent.py, control.py, database.py, gitlab_api.py, and
__main__.py
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Fix two issues with push-branch:
1. Handle missing remote branch: When pushing a new branch for the
first time, the fetch to update tracking refs fails because the
branch doesn't exist on the remote yet. Handle this by catching
the fetch failure and using regular --force instead of
--force-with-lease for new branches.
2. Detect aborted cherry-picks: When the agent aborts a cherry-pick
(e.g., because commits are already applied), it may delete the
branch. Verify the branch exists after the agent runs to avoid
attempting to push a non-existent branch.
Cover-letter:
pickman and CI improvements
This series contains pickman enhancements and a CI fix:
- Process MRs oldest first to handle rebases chronologically
- Add --run-ci option for push-branch to trigger pipelines after rebase
- Fix force-push tracking ref issues by fetching before push
- Handle edge cases: new branches and agent-aborted cherry-picks
- Push master to GitHub for ReadTheDocs documentation rebuilds
END
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
When using --force-with-lease with an HTTPS URL (instead of a remote
name), git cannot find the tracking refs automatically. This causes
"stale info" errors when the local tracking ref is out of date.
Fix by fetching the branch first to update the tracking ref before
pushing.
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Add a --run-ci flag to push-branch that triggers the CI pipeline instead
of skipping it. This is needed when pushing rebased branches where the
MR pipeline should run to verify the changes.
Update the review agent prompt to use --run-ci when pushing after
rebase operations.
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Sort merge requests by created_at ascending so older MRs are processed
before newer ones. This ensures that MRs needing rebase are handled in
chronological order.
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Add support for pushing branches using the GitLab API token, so commits
appear as coming from the token owner (e.g., a bot account) rather than
the user's configured git credentials.
Add get_push_url() function that creates a token-authenticated URL in
the format https://oauth2:TOKEN@host/project.git. Update push_branch()
to use this URL when available.
Add a new 'push-branch' command that the agent can use for pushing:
./tools/pickman/pickman push-branch <branch> -r <remote> [-f]
Update the review agent prompt to use this command instead of direct
git push, ensuring all pickman commits come from the same account.
Series-to: concept
Cover-letter:
pickman: Improvements for robustness and automation
These changes improve pickman's robustness when interrupted, add the
ability to skip problematic MRs during review, support multiple
concurrent MRs, and ensure all commits come from the pickman bot
account.
This series adds several improvements to pickman:
- Fix rebase-detection for open MRs
- Add skip/unskip support via review comments (pickman: skip/unskip)
- Skip already-processed commits to handle interruptions gracefully
- Handle 409 errors when MR already exists
- Document the commit-selection algorithm and skip feature
- Add --max-mrs option for parallel MR creation
- Run a CI pipeline after review-comment changes
- Use GitLab API token for push authentication (bot-account support)
END
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
If pickman crashes or is interrupted after pushing a branch but before
recording the MR, the next run would try to create an MR for the same
branch and receive a 409 Conflict error. Handle this gracefully by
finding the existing MR and returning its URL.
Add MrCreateError exception class to allow testing without importing
the gitlab module.
Co-developed-by: Claude <noreply@anthropic.com>
Allow reviewers to skip an MR by commenting "pickman skip" (or
"pickman: skip", "@pickman skip"). When skipped, the MR title is
updated to include "[skipped]" and pickman continues creating new
MRs for subsequent cherry-picks.
To resume processing a skipped MR, comment "pickman unskip" which
removes the [skipped] tag from the title.
Skipped MRs are ignored for rebase processing and don't block
creation of new MRs.
Fix some double-quotes while here.
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
The GitLab list() API returns inaccurate detailed_merge_status values.
Fetch the full MR details for open MRs to get accurate rebase status.
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Check GitLab merge request status to detect when a rebase is needed,
even if there are no review comments. This handles the case where
GitLab shows "Merge request must be rebased" or "Merge conflicts must
be resolved".
Add has_conflicts and needs_rebase fields to PickmanMr namedtuple,
populated from GitLab's detailed_merge_status and diverged_commits_count
fields.
Update process_mr_reviews() to trigger the agent for rebase when needed,
even without review comments. The agent prompt is adjusted based on
whether it needs to handle comments, rebase, or both.
Also:
- Pass MR description to agent for context from previous work
- After processing reviews, restore the original branch
- Use -o ci.skip when pushing to avoid duplicate pipelines
Series-to: concept
Series-links: 2:81 1:80
Cover-letter:
pickman: Improve handling of rebasing
This little series includes a few patches to ensure that rebases are
made against -master and detection for needing a rebase without the user
having explicitly request it.
It also passes the previous context to the agent when handling reviews,
which should improve its response.
END
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Series-version: 2
Remove SJG_LAB CI variable from push since lab tests are now
triggered automatically for MR pipelines via .gitlab-ci.yml rules.
Keep ci.skip to avoid running a pipeline on push; the MR pipeline
will run when the merge request is created.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Add check-gitlab command to verify GitLab permissions for the
configured token. This helps diagnose issues like 403 Forbidden
errors when trying to create merge requests.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Add support for storing a GitLab API token in ~/.config/pickman.conf
instead of an environment variable. This allows using a dedicated bot
account for pickman without affecting the user's personal GitLab
credentials.
Config file format:
[gitlab]
token = glpat-xxxxxxxxxxxxxxxxxxxx
This falls back to GITLAB_TOKEN environment variable if config file is
not present.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
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 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Change get_pickman_mrs() and get_mr_comments() to return lists of named
tuples instead of dicts. This provides cleaner attribute access (e.g.
merge_req.iid instead of merge_req['iid']) and better code documentation.
Add PickmanMr and MrComment named tuples to gitlab_api.py.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Add automatic database updates when pickman MRs are merged. The step
command now:
1. Checks for merged pickman MRs via GitLab API
2. Parses the MR description to find the source branch and last commit
3. Updates the database's last_commit for the source branch
4. Then proceeds to check for open MRs and create new ones as before
This removes the need to manually run commit-source after each MR is
merged, enabling fully automated cherry-pick workflows with poll.
Add get_merged_pickman_mrs() and refactor get_open_pickman_mrs() to use
a common get_pickman_mrs() function with a state parameter.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Add do_review() command that lists open pickman MRs and checks each for
human comments. Uses a Claude agent to address actionable comments.
Also add supporting infrastructure:
- gitlab_api: get_open_pickman_mrs(), get_mr_comments(), reply_to_mr()
- agent: run_review_agent(), handle_mr_comments()
- History file support for recording cherry-pick conversations
- Return conversation_log from cherry_pick agent for MR descriptions
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
Add gitlab_api module with functions for interacting with GitLab:
- check_available(): Check if python-gitlab is installed
- get_token(): Get GitLab API token from environment
- get_remote_url(): Get URL for a git remote
- parse_url(): Parse GitLab URLs (SSH and HTTPS formats)
- push_branch(): Push a branch to a remote
- create_mr(): Create a merge request via GitLab API
- push_and_create_mr(): Combined push and MR creation
Requires python-gitlab library and GITLAB_TOKEN environment variable.
Name the module gitlab_api.py to avoid shadowing the python-gitlab
library.
Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>