跳到主要内容

Gitlab Issues

Create, triage, label, assign GitLab issues via glab or REST.

Skill metadata​

SourceBundled (installed by default)
Pathskills/gitlab/gitlab-issues
Version1.1.0
AuthorAlice Agent
LicenseMIT
Platformslinux, macos, windows
TagsGitLab, Issues, Project-Management, Bug-Tracking, Triage
Related skillsgitlab-auth, gitlab-mr-workflow

Reference: full SKILL.md​

信息

The following is the complete skill definition that Alice loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.

GitHub Issues Management

Create, search, triage, and manage GitHub issues. Each section shows glab first, then the curl fallback.

Prerequisites​

  • Authenticated with GitLab (see gitlab-auth skill)
  • Inside a git repo with a GitHub remote, or specify the repo explicitly

Setup​

if command -v glab &>/dev/null && glab auth status &>/dev/null; then
AUTH="glab"
else
AUTH="git"
if [ -z "$GITLAB_TOKEN" ]; then
if _alice_env="${ALICE_HOME:-$HOME/.alice}/.env"; [ -f "$_alice_env" ] && grep -q "^GITLAB_TOKEN=" "$_alice_env"; then
GITLAB_TOKEN=$(grep "^GITLAB_TOKEN=" "$_alice_env" | head -1 | cut -d= -f2 | tr -d '\n\r')
elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then
GITLAB_TOKEN=$(grep "${GITLAB_HOST:-gitlab\.com}" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\([^@]*\)@.*|\1|')
fi
fi
fi

REMOTE_URL=$(git remote get-url origin)
OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*${GITLAB_HOST:-gitlab\.com}[:/]||; s|\.git$||')
OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1)
REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)

1. Viewing Issues​

With glab:

glab issue list
glab issue list --state open --label "bug"
glab issue list --assignee @me
glab issue list --search "authentication error" --state all
glab issue view 42

With curl:

# List open issues
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues?state=open&per_page=20" \
| python3 -c "
import sys, json
for i in json.load(sys.stdin):
if 'pull_request' not in i: # GitHub API returns PRs in /issues too
labels = ', '.join(l['name'] for l in i['labels'])
print(f\"#{i['number']:5} {i['state']:6} {labels:30} {i['title']}\")"

# Filter by label
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues?state=open&labels=bug&per_page=20" \
| python3 -c "
import sys, json
for i in json.load(sys.stdin):
if 'pull_request' not in i:
print(f\"#{i['number']} {i['title']}\")"

# View a specific issue
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42 \
| python3 -c "
import sys, json
i = json.load(sys.stdin)
labels = ', '.join(l['name'] for l in i['labels'])
assignees = ', '.join(a['login'] for a in i['assignees'])
print(f\"#{i['number']}: {i['title']}\")
print(f\"State: {i['state']} Labels: {labels} Assignees: {assignees}\")
print(f\"Author: {i['user']['login']} Created: {i['created_at']}\")
print(f\"\n{i['body']}\")"

# Search issues
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://\${GITLAB_HOST:-gitlab.com}/api/v4/search/issues?q=authentication+error+repo:$OWNER/$REPO" \
| python3 -c "
import sys, json
for i in json.load(sys.stdin)['items']:
print(f\"#{i['number']} {i['state']:6} {i['title']}\")"

2. Creating Issues​

With glab:

glab issue create \
--title "Login redirect ignores ?next= parameter" \
--body "## Description
After logging in, users always land on /dashboard.

## Steps to Reproduce
1. Navigate to /settings while logged out
2. Get redirected to /login?next=/settings
3. Log in
4. Actual: redirected to /dashboard (should go to /settings)

## Expected Behavior
Respect the ?next= query parameter." \
--label "bug,backend" \
--assignee "username"

With curl:

curl -s -X POST \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues \
-d '{
"title": "Login redirect ignores ?next= parameter",
"body": "## Description\nAfter logging in, users always land on /dashboard.\n\n## Steps to Reproduce\n1. Navigate to /settings while logged out\n2. Get redirected to /login?next=/settings\n3. Log in\n4. Actual: redirected to /dashboard\n\n## Expected Behavior\nRespect the ?next= query parameter.",
"labels": ["bug", "backend"],
"assignees": ["username"]
}'

Bug Report Template​

## Bug Description
<What's happening>

## Steps to Reproduce
1. <step>
2. <step>

## Expected Behavior
<What should happen>

## Actual Behavior
<What actually happens>

## Environment
- OS: <os>
- Version: <version>

Feature Request Template​

## Feature Description
<What you want>

## Motivation
<Why this would be useful>

## Proposed Solution
<How it could work>

## Alternatives Considered
<Other approaches>

3. Managing Issues​

Add/Remove Labels​

With glab:

glab issue edit 42 --add-label "priority:high,bug"
glab issue edit 42 --remove-label "needs-triage"

With curl:

# Add labels
curl -s -X POST \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42/labels \
-d '{"labels": ["priority:high", "bug"]}'

# Remove a label
curl -s -X DELETE \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42/labels/needs-triage

# List available labels in the repo
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/labels \
| python3 -c "
import sys, json
for l in json.load(sys.stdin):
print(f\" {l['name']:30} {l.get('description', '')}\")"

Assignment​

With glab:

glab issue edit 42 --add-assignee username
glab issue edit 42 --add-assignee @me

With curl:

curl -s -X POST \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42/assignees \
-d '{"assignees": ["username"]}'

Commenting​

With glab:

glab issue comment 42 --body "Investigated — root cause is in auth middleware. Working on a fix."

With curl:

curl -s -X POST \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42/comments \
-d '{"body": "Investigated — root cause is in auth middleware. Working on a fix."}'

Closing and Reopening​

With glab:

glab issue close 42
glab issue close 42 --reason "not planned"
glab issue reopen 42

With curl:

# Close
curl -s -X PATCH \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42 \
-d '{"state": "closed", "state_reason": "completed"}'

# Reopen
curl -s -X PATCH \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/42 \
-d '{"state": "open"}'

Linking Issues to PRs​

Issues are automatically closed when an MR merges with the right keywords in the body:

Closes #42
Fixes #42
Resolves #42

To create a branch from an issue:

With glab:

glab issue develop 42 --checkout

With git (manual equivalent):

git checkout main && git pull origin main
git checkout -b fix/issue-42-login-redirect

4. Issue Triage Workflow​

When asked to triage issues:

  1. List untriaged issues:
# With glab
glab issue list --label "needs-triage" --state open

# With curl
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues?labels=needs-triage&state=open" \
| python3 -c "
import sys, json
for i in json.load(sys.stdin):
if 'pull_request' not in i:
print(f\"#{i['number']} {i['title']}\")"
  1. Read and categorize each issue (view details, understand the bug/feature)

  2. Apply labels and priority (see Managing Issues above)

  3. Assign if the owner is clear

  4. Comment with triage notes if needed

5. Bulk Operations​

For batch operations, combine API calls with shell scripting:

With glab:

# Close all issues with a specific label
glab issue list --label "wontfix" --json number --jq '.[].number' | \
xargs -I {} glab issue close {} --reason "not planned"

With curl:

# List issue numbers with a label, then close each
curl -s \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues?labels=wontfix&state=open" \
| python3 -c "import sys,json; [print(i['number']) for i in json.load(sys.stdin)]" \
| while read num; do
curl -s -X PATCH \
-H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
https://\${GITLAB_HOST:-gitlab.com}/api/v4/projects/$OWNER/$REPO/issues/$num \
-d '{"state": "closed", "state_reason": "not_planned"}'
echo "Closed #$num"
done

Quick Reference Table​

Actionglabcurl endpoint
List issuesglab issue listGET /projects/{o}/{r}/issues
View issueglab issue view NGET /projects/{o}/{r}/issues/N
Create issueglab issue create ...POST /projects/{o}/{r}/issues
Add labelsglab issue edit N --add-label ...POST /projects/{o}/{r}/issues/N/labels
Assignglab issue edit N --add-assignee ...POST /projects/{o}/{r}/issues/N/assignees
Commentglab issue comment N --body ...POST /projects/{o}/{r}/issues/N/comments
Closeglab issue close NPATCH /projects/{o}/{r}/issues/N
Searchglab issue list --search "..."GET /search/issues?q=...