Description¶
Posts a comment to a Jira issue using the Jira API. Supports Jira wiki markup formatting in comments. Designed to run in automated pipelines and in SLURM batch jobs, and fails gracefully if credentials are not available.
With --partb, the comment is redirected from the main ticket to the ticket’s “Part B ...” sub-task, so that a caller only ever needs to know the main ticket.
Usage¶
python3 tools/jira_add_comment.py [options] <issue-key|auto> [comment]Arguments¶
issue-key (required) - Jira issue key (e.g., AEAREP-8885 or aearep-8885, case-insensitive). Use the literal string
autoto have the script resolve the ticket itself (see Ticket resolution).comment (optional) - Comment text (Jira wiki markup supported). Required unless
--statusis given.
Options¶
| Option | Effect |
|---|---|
--partb | Post to the “Part B ...” sub-task of the issue instead of the issue itself (see Part B resolution) |
--status STATUS | Prepend a standard status line. started → 🚀, completed → ✅, failed → ❌; any other value is used verbatim with ℹ️ |
--exit-code N | Use with --status: a non-zero N turns completed into failed and appends the exit code. Lets one call report both success and failure from a shell trap |
--label TEXT | What --status is talking about (default: Job), e.g. SLURM job main.do. Ignored in favour of SLURM job <id> <name> when --slurm is given inside a real job |
--slurm | Fold the SLURM job ID, job name and submit directory into the status line, e.g. ✅ SLURM job 590340 main.do completed (directory: /path/to/submit/dir). Without --status, the same context is added as a line of its own. Silently omitted when not running inside a SLURM job |
--env-file PATH | Read credentials from PATH in addition to the default locations. May be repeated |
--dry-run | Resolve the target issue and print the comment that would be posted, without posting it |
-- | End of options; everything after it is positional |
-h, --help | Show usage |
Examples¶
# Simple comment on the main ticket
python3 tools/jira_add_comment.py AEAREP-8885 "Pipeline completed successfully"
# With Jira markup
python3 tools/jira_add_comment.py aearep-1234 "*Pipeline Status:* ✅ Complete"
# Comment on the Part B sub-task of AEAREP-8885, whatever its key is
python3 tools/jira_add_comment.py --partb AEAREP-8885 "Started the Stata run"
# Start/stop notification from a SLURM job, ticket read from config.yml.
# --slurm supplies the "SLURM job <id> <name>" label itself, so --label is
# not needed inside a real job.
python3 tools/jira_add_comment.py --partb --slurm --status started -- auto
python3 tools/jira_add_comment.py --partb --slurm --status completed \
--exit-code "$rc" -- auto
# Check what would be posted, and where, without posting
python3 tools/jira_add_comment.py --partb --dry-run AEAREP-8885 "test"Requirements¶
Python >= 3.6
jira(optional): the Python Jira library. When it is not importable, the script falls back to the Jira REST API using only the standard library, so it also runs on machines where nothing has been pip-installed (for example HPC compute nodes).
Credentials¶
JIRA_USERNAME- Your Jira email addressJIRA_API_KEY- API token from https://id .atlassian .com /manage -profile /security /api -tokens
These are looked up in the following order; the process environment always wins, and each file may supply whatever is still missing:
the process environment
any
--env-file PATHgiven, in order./.env./.envvars~/.envvars~/envvars.txt~/.env
Files are parsed as simple KEY=value lines. A leading export and surrounding quotes are stripped; # comments and blank lines are ignored. This is the same format used by source ~/.envvars, so one file can serve both purposes.
Ticket resolution¶
When the issue key is the literal string auto, the script resolves the ticket from, in order:
the
$jiraticket(or$JIRATICKET) environment variablethe
jiraticket:line of the nearestconfig.yml, searched from$SLURM_SUBMIT_DIR(or the current directory) upward through four parent directories
If nothing resolves, a warning is printed and no comment is posted.
Part B resolution¶
With --partb, the script looks for the sub-task that tracks Part B work:
If the given issue is already a Part B sub-task (its issue type starts with “Part B”), it is used as-is.
If the given issue is some other sub-task, its parent is read and the parent’s Part B sub-task is used.
Otherwise the given issue’s own sub-tasks are searched.
A sub-task matches when its issue type starts with “Part B” - in AEAREP that is Part B processing: run code or complete report. Only if no sub-task matches by issue type does the script fall back to matching sub-tasks whose summary contains “Part B”, which catches the SIVACOR-style sub-tasks that carry a different issue type (e.g. Author-generated reproducibility check with summary Prepare Part B (SIVACOR)). If several sub-tasks match, the highest-numbered one is used.
If no Part B sub-task can be found, the script prints a warning and comments on the main ticket instead, so a job never loses its notification.
Behavior¶
On success: Prints
Jira comment posted to <KEY>to stdoutOn failure: Prints a warning to stderr (non-fatal; always exits with code 0)
Missing credentials: Prints a warning and exits gracefully (with
--dry-run, still prints the comment it would have posted)
This design allows the script to be used in pipelines and batch jobs where Jira access may not always be available without causing failures.
See Also¶
sbatch-shell.sh - SLURM template that uses this tool for start/stop notifications
jira_get_info.py - Retrieve Jira issue information
jira_find_task_by_icpsr.py - Find Jira tasks by openICPSR ID
70
_publish _comment .sh - Uses this tool to post pipeline results