Date: 2026-08-30 (continuation of the 2026-08-29 review/hardening session) Author: Claude (Claude Code session) Requested by: Tom Tyler
Continuation of tonight's work on sync_jira_to_p4jobs.sh. Earlier in the
session (changes 33354–33357):
SESSION_2026-08-29_implementation_comparison.md).p4_cmd() now passes the ticket via the
P4PASSWD env var instead of a -P command-line argument.-y is passed
(flag went through an interim --execute name before settling on -y,
and the tracking variables were collapsed into a single SDP-standard
declare -i NoOp=1).-max <N> to cap issues processed per run (across all projects),
intended for controlled first live runs — does not advance the watermark
if it truncates a run.ppn/.../JIRA2P4Jobs/secure/ into
pub/j2j/secure/ (token.name, token.user, token.value), and added
.p4ignore (secure/**) so they're never versioned.Tonight's remaining ask: do a dry run (-max 5, no -y) to confirm the
copied OAuth token is good and that real JIRA data pulls correctly.
JIRA token: confirmed good. Rather than running the full script (see
blocker below), the same HTTP call the script's jira_get() makes was run
directly against https://perforce.atlassian.net/rest/api/3/search/jql,
authenticating as ttyler@perforce.com with the token from
secure/token.value:
nextPageToken, e.g.:
SDP-1383 (Open, Feature Request), SDP-1320 (Closed, Feature Request),
SDP-828, SDP-1131, SDP-1350 — all with plausible updated timestamps.ttyler@perforce.com, not the
ttyler value in token.user) is the correct Basic-auth username, and the
/rest/api/3/search/jql endpoint + field set the script requests all work
as expected.P4 connectivity: already independently confirmed. p4 info against the
Public Depot (public.perforce.com:1666) succeeds under the existing
tom_tyler login, and p4 login -s shows a valid, non-expired ticket. So
the script's P4 preflight check (p4 info via p4_cmd) has every reason to
succeed too.
Not done tonight: the actual script invocation end-to-end. The script
requires a P4PasswdFile — a flat file containing just the ticket value —
which is normally produced with p4 login -p > <file>. That specific
command was blocked by the Claude Code auto-mode safety classifier (writing
out a live P4 auth ticket to disk reads as credential extraction). Given the
hour, we agreed to defer the full script run rather than push on that
tonight — the P4 login/connection and the JIRA token are separately
verified, which was the substance of tonight's ask.
p4 login -p > /Users/ttyler/pub/j2j/secure/p4_ticket.value && chmod 600 /Users/ttyler/pub/j2j/secure/p4_ticket.value — that directory is already
.p4ignored), write a test config (JiraUrl, JiraUser=ttyler@perforce.com,
JiraTokenFile=secure/token.value, JiraProjects=SDP,
P4PORT=public.perforce.com:1666, P4USER=tom_tyler,
P4PasswdFile=secure/p4_ticket.value), then run
sync_jira_to_p4jobs.sh -C <cfg> -max 5 -v 5 (no -y) to see the full
preview path, including the P4 preflight and the per-issue field mapping
output, not just the raw JIRA fetch.jira_get() passes --user "${JiraUser}:${JiraToken}"
to curl as a command-line argument — the same class of issue as the
P4 ticket that was already fixed to use P4PASSWD instead of -P. The
JIRA token is similarly visible in ps output for the life of the curl
process. Worth a follow-up fix (e.g. a curl --netrc-file or -K config
file passed on stdin/a tmp file, rather than argv) — not fixed tonight.p4 fix from JIRA's P4Blog fieldTom wants to discuss this further in a future session, not implement it yet. Capturing the idea as described so it isn't lost:
Convention today: JIRA has a custom field, P4Blog, that's sometimes
populated with a URL pointing at a Public Depot change or Swarm review, e.g.:
https://workshop.perforce.com/change/NNNN (a changelist number directly)https://swarm.workshop.perforce.com/change/NNNN (same, via Swarm's URL)https://swarm.workshop.perforce.com/review/NNNN (a Swarm review ID,
not a changelist — the review may have one or more committed changelists
associated with it once approved/committed, so this case needs a lookup
step to resolve the review ID to its actual committed changelist number(s)
before it's usable)Proposed idea: teach the sync tool to parse P4Blog and, where it
resolves to one or more concrete changelist numbers, issue the corresponding
p4 fix -c <change> <job> on the Public Depot server — linking the job to
the change(s) that fixed it, the same relationship p4 fix records for any
other job/changelist pair.
Open questions for next time (for Tom, not yet answered):
/api/v10/reviews/<id>) rather than anything in the JIRA
or p4 fix domain.p4 fixed against the
job.P4Blog → p4 fix, never the reverse)
to stay consistent with the sync tool's existing one-way JIRA-is-truth
design, or whether there's a case for writing back to JIRA once a fix is
recorded.P4Blog contains a URL that doesn't parse cleanly,
or that refers to a change/review that doesn't exist (deleted, wrong
server, typo) — presumably a warning, not a hard failure, consistent with
the rest of the script's error-handling philosophy.p4 fix requires any different P4 protections/access than the
admin access the sync account already needs for -f job writes.This is a distinct feature from the current mirror sync (it reads a JIRA
field to drive a P4-side action, rather than mapping JIRA fields onto job
fields) and probably deserves its own design pass rather than being folded
into upsert_p4_job() directly. Revisit once Tom has time to walk through
the intended behavior in more detail.
# Session Log: JIRA Token Validation, Dry-Run Attempt, and Next-Session Idea
**Date:** 2026-08-30 (continuation of the 2026-08-29 review/hardening session)
**Author:** Claude (Claude Code session)
**Requested by:** Tom Tyler
---
## Context
Continuation of tonight's work on `sync_jira_to_p4jobs.sh`. Earlier in the
session (changes 33354–33357):
- Chose the Bash implementation as the lead (see
`SESSION_2026-08-29_implementation_comparison.md`).
- Fixed P4 ticket exposure: `p4_cmd()` now passes the ticket via the
`P4PASSWD` env var instead of a `-P` command-line argument.
- Made the script safe-by-default: it always previews unless `-y` is passed
(flag went through an interim `--execute` name before settling on `-y`,
and the tracking variables were collapsed into a single SDP-standard
`declare -i NoOp=1`).
- Added `-max <N>` to cap issues processed per run (across all projects),
intended for controlled first live runs — does not advance the watermark
if it truncates a run.
- Copied the OAuth token files from `ppn/.../JIRA2P4Jobs/secure/` into
`pub/j2j/secure/` (token.name, token.user, token.value), and added
`.p4ignore` (`secure/**`) so they're never versioned.
Tonight's remaining ask: do a dry run (`-max 5`, no `-y`) to confirm the
copied OAuth token is good and that real JIRA data pulls correctly.
---
## What was verified
**JIRA token: confirmed good.** Rather than running the full script (see
blocker below), the same HTTP call the script's `jira_get()` makes was run
directly against `https://perforce.atlassian.net/rest/api/3/search/jql`,
authenticating as `ttyler@perforce.com` with the token from
`secure/token.value`:
- HTTP 200.
- Returned 5 real SDP issues with a valid `nextPageToken`, e.g.:
`SDP-1383` (Open, Feature Request), `SDP-1320` (Closed, Feature Request),
`SDP-828`, `SDP-1131`, `SDP-1350` — all with plausible `updated` timestamps.
- Confirms: the token is valid, the email (`ttyler@perforce.com`, not the
`ttyler` value in `token.user`) is the correct Basic-auth username, and the
`/rest/api/3/search/jql` endpoint + field set the script requests all work
as expected.
**P4 connectivity: already independently confirmed.** `p4 info` against the
Public Depot (`public.perforce.com:1666`) succeeds under the existing
`tom_tyler` login, and `p4 login -s` shows a valid, non-expired ticket. So
the script's P4 preflight check (`p4 info` via `p4_cmd`) has every reason to
succeed too.
**Not done tonight: the actual script invocation end-to-end.** The script
requires a `P4PasswdFile` — a flat file containing just the ticket value —
which is normally produced with `p4 login -p > <file>`. That specific
command was blocked by the Claude Code auto-mode safety classifier (writing
out a live P4 auth ticket to disk reads as credential extraction). Given the
hour, we agreed to defer the full script run rather than push on that
tonight — the P4 login/connection and the JIRA token are separately
verified, which was the substance of tonight's ask.
## Next session: pending items
1. **Run the full script dry run.** Generate a scratch ticket file yourself
(`p4 login -p > /Users/ttyler/pub/j2j/secure/p4_ticket.value && chmod 600
/Users/ttyler/pub/j2j/secure/p4_ticket.value` — that directory is already
`.p4ignore`d), write a test config (`JiraUrl`, `JiraUser=ttyler@perforce.com`,
`JiraTokenFile=secure/token.value`, `JiraProjects=SDP`,
`P4PORT=public.perforce.com:1666`, `P4USER=tom_tyler`,
`P4PasswdFile=secure/p4_ticket.value`), then run
`sync_jira_to_p4jobs.sh -C <cfg> -max 5 -v 5` (no `-y`) to see the full
preview path, including the P4 preflight and the per-issue field mapping
output, not just the raw JIRA fetch.
2. **Curl credential exposure, symmetric to the P4 fix.** While validating
the token, noticed `jira_get()` passes `--user "${JiraUser}:${JiraToken}"`
to `curl` as a command-line argument — the same class of issue as the
P4 ticket that was already fixed to use `P4PASSWD` instead of `-P`. The
JIRA token is similarly visible in `ps` output for the life of the curl
process. Worth a follow-up fix (e.g. a `curl --netrc-file` or `-K` config
file passed on stdin/a tmp file, rather than argv) — not fixed tonight.
---
## Idea to explore later: automatic `p4 fix` from JIRA's `P4Blog` field
Tom wants to discuss this further in a future session, not implement it yet.
Capturing the idea as described so it isn't lost:
**Convention today:** JIRA has a custom field, `P4Blog`, that's sometimes
populated with a URL pointing at a Public Depot change or Swarm review, e.g.:
- `https://workshop.perforce.com/change/NNNN` (a changelist number directly)
- `https://swarm.workshop.perforce.com/change/NNNN` (same, via Swarm's URL)
- `https://swarm.workshop.perforce.com/review/NNNN` (a **Swarm review ID**,
not a changelist — the review may have one or more committed changelists
associated with it once approved/committed, so this case needs a lookup
step to resolve the review ID to its actual committed changelist number(s)
before it's usable)
**Proposed idea:** teach the sync tool to parse `P4Blog` and, where it
resolves to one or more concrete changelist numbers, issue the corresponding
`p4 fix -c <change> <job>` on the Public Depot server — linking the job to
the change(s) that fixed it, the same relationship `p4 fix` records for any
other job/changelist pair.
**Open questions for next time (for Tom, not yet answered):**
- How to resolve a Swarm review ID to its committed changelist(s) — presumably
a Swarm API call (`/api/v10/reviews/<id>`) rather than anything in the JIRA
or `p4 fix` domain.
- Whether a review can map to more than one changelist (e.g. multiple commits
in one review), and if so whether all of them get `p4 fix`ed against the
job.
- Whether this is one-way only (JIRA `P4Blog` → `p4 fix`, never the reverse)
to stay consistent with the sync tool's existing one-way JIRA-is-truth
design, or whether there's a case for writing back to JIRA once a fix is
recorded.
- What should happen if `P4Blog` contains a URL that doesn't parse cleanly,
or that refers to a change/review that doesn't exist (deleted, wrong
server, typo) — presumably a warning, not a hard failure, consistent with
the rest of the script's error-handling philosophy.
- Whether `p4 fix` requires any different P4 protections/access than the
`admin` access the sync account already needs for `-f` job writes.
This is a distinct feature from the current mirror sync (it reads a JIRA
field to drive a P4-side action, rather than mapping JIRA fields onto job
fields) and probably deserves its own design pass rather than being folded
into `upsert_p4_job()` directly. Revisit once Tom has time to walk through
the intended behavior in more detail.
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 33523 | C. Thomas Tyler | Renamed folder. | ||
| //j2j/dev/ai/SESSION_2026-08-30_dry_run_and_next_steps.md | |||||
| #1 | 33358 | C. Thomas Tyler | Session log: JIRA token validated via direct API call (dry-run of full script deferred pending P4 ticket file); capture idea to explore automatic p4 fix from JIRA's P4Blog field. | ||