Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions scripts/lib/jira-triage-ops.lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,27 @@
[[ -n "${JIRA_TRIAGE_OPS_SH_LOADED:-}" ]] && return 0
JIRA_TRIAGE_OPS_SH_LOADED=1

# Validate credentials at source time — fails once, early, on unredirected
# stderr, before any call site can swallow the diagnostic with 2>/dev/null.
# Matches the idiom pre-triage.src.sh / post-triage.src.sh already use for
# ISSUE_URL and FULLSEND_TRACKER.
: "${JIRA_USER_EMAIL:?JIRA_USER_EMAIL must be set}"
Comment thread
ralphbean marked this conversation as resolved.
: "${JIRA_TOKEN:?JIRA_TOKEN must be set}"

# JIRA_BASE_URL is derived at runtime by tracker_parse_issue_url, so it
# cannot be validated at source time — keep a per-call guard for it.
_jira_require_vars() {
if [[ -z "${JIRA_BASE_URL:-}" ]]; then echo "ERROR: JIRA_BASE_URL is not set" >&2; return 1; fi
}

_jira_api() {
local method="$1"
shift
local endpoint="$1"
shift

_jira_require_vars || return 1

curl --fail --silent --show-error \
--connect-timeout 10 --max-time 30 \
--user "${JIRA_USER_EMAIL}:${JIRA_TOKEN}" \
Expand All @@ -58,6 +74,9 @@ _jira_api_with_status() {
shift
local endpoint="$1"
shift

_jira_require_vars || return 1

local err_file
err_file=$(mktemp)
local raw
Expand Down Expand Up @@ -215,6 +234,7 @@ tracker_create_label() {

tracker_post_comment() {
local body="$1"
_jira_require_vars || return 1
# `fullsend issues post-comment` always does marker-based find-and-update;
# there is no "always create new" mode. A marker unique to this invocation
# guarantees no prior comment matches it, so this always creates a new
Expand All @@ -238,6 +258,7 @@ tracker_post_comment() {
tracker_post_sticky_comment() {
local body="$1"
local marker="$2"
_jira_require_vars || return 1
printf '%s' "${body}" | fullsend issues post-comment --tracker jira \
--project "${REPO}" --number "${JIRA_ISSUE_NUM}" \
--jira-url "${JIRA_BASE_URL}" --jira-email "${JIRA_USER_EMAIL}" --token "${JIRA_TOKEN}" \
Expand Down
32 changes: 32 additions & 0 deletions scripts/post-triage-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2097,6 +2097,38 @@ exit 0
CURLMOCK
chmod +x "${MOCK_BIN}/curl"

# --- Jira credential guard tests (#876) ---
Comment thread
ralphbean marked this conversation as resolved.
# Verify that source-time :? guards reject unset/empty JIRA_TOKEN and
# JIRA_USER_EMAIL before any API call is made.

unset JIRA_TOKEN
run_jira_test "jira-missing-token-fails" \
'{"action":"insufficient","reasoning":"missing repro","clarity_scores":{"symptom":0.6,"cause":0.3,"reproduction":0.1,"impact":0.5,"overall":0.39},"comment":"Could you share the exact steps to reproduce this?"}' \
"" \
"true"
export JIRA_TOKEN="fake-jira-token"

export JIRA_TOKEN=""
run_jira_test "jira-empty-token-fails" \
'{"action":"insufficient","reasoning":"missing repro","clarity_scores":{"symptom":0.6,"cause":0.3,"reproduction":0.1,"impact":0.5,"overall":0.39},"comment":"Could you share the exact steps to reproduce this?"}' \
"" \
"true"
export JIRA_TOKEN="fake-jira-token"

unset JIRA_USER_EMAIL
run_jira_test "jira-missing-email-fails" \
'{"action":"insufficient","reasoning":"missing repro","clarity_scores":{"symptom":0.6,"cause":0.3,"reproduction":0.1,"impact":0.5,"overall":0.39},"comment":"Could you share the exact steps to reproduce this?"}' \
"" \
"true"
export JIRA_USER_EMAIL="triage@example.com"

export JIRA_USER_EMAIL=""
run_jira_test "jira-empty-email-fails" \
'{"action":"insufficient","reasoning":"missing repro","clarity_scores":{"symptom":0.6,"cause":0.3,"reproduction":0.1,"impact":0.5,"overall":0.39},"comment":"Could you share the exact steps to reproduce this?"}' \
"" \
"true"
export JIRA_USER_EMAIL="triage@example.com"

# Restore GitHub tracker for any subsequent tests.
export FULLSEND_TRACKER="github"
export ISSUE_URL="https://github.com/test-org/test-repo/issues/42"
Expand Down
21 changes: 21 additions & 0 deletions scripts/post-triage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -506,11 +506,27 @@ tracker_create_issue() {
[[ -n "${JIRA_TRIAGE_OPS_SH_LOADED:-}" ]] && return 0
JIRA_TRIAGE_OPS_SH_LOADED=1

# Validate credentials at source time — fails once, early, on unredirected
# stderr, before any call site can swallow the diagnostic with 2>/dev/null.
# Matches the idiom pre-triage.src.sh / post-triage.src.sh already use for
# ISSUE_URL and FULLSEND_TRACKER.
: "${JIRA_USER_EMAIL:?JIRA_USER_EMAIL must be set}"
: "${JIRA_TOKEN:?JIRA_TOKEN must be set}"

# JIRA_BASE_URL is derived at runtime by tracker_parse_issue_url, so it
# cannot be validated at source time — keep a per-call guard for it.
_jira_require_vars() {
if [[ -z "${JIRA_BASE_URL:-}" ]]; then echo "ERROR: JIRA_BASE_URL is not set" >&2; return 1; fi
}

_jira_api() {
local method="$1"
shift
local endpoint="$1"
shift

_jira_require_vars || return 1

curl --fail --silent --show-error \
--connect-timeout 10 --max-time 30 \
--user "${JIRA_USER_EMAIL}:${JIRA_TOKEN}" \
Expand All @@ -525,6 +541,9 @@ _jira_api_with_status() {
shift
local endpoint="$1"
shift

_jira_require_vars || return 1

local err_file
err_file=$(mktemp)
local raw
Expand Down Expand Up @@ -682,6 +701,7 @@ tracker_create_label() {

tracker_post_comment() {
local body="$1"
_jira_require_vars || return 1
# `fullsend issues post-comment` always does marker-based find-and-update;
# there is no "always create new" mode. A marker unique to this invocation
# guarantees no prior comment matches it, so this always creates a new
Expand All @@ -705,6 +725,7 @@ tracker_post_comment() {
tracker_post_sticky_comment() {
local body="$1"
local marker="$2"
_jira_require_vars || return 1
printf '%s' "${body}" | fullsend issues post-comment --tracker jira \
--project "${REPO}" --number "${JIRA_ISSUE_NUM}" \
--jira-url "${JIRA_BASE_URL}" --jira-email "${JIRA_USER_EMAIL}" --token "${JIRA_TOKEN}" \
Expand Down
32 changes: 32 additions & 0 deletions scripts/pre-triage-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,38 @@ run_test "jira-base-url-multiple-trailing-slashes-ok" \
'"remove":"needs-info"'
unset JIRA_BASE_URL

# --- Jira credential guard tests (#876) ---
# Verify that source-time :? guards on JIRA_USER_EMAIL and JIRA_TOKEN reject
# unset and empty values before any API call is made.

unset JIRA_TOKEN
run_test "jira-missing-token-fails" \
"https://test.atlassian.net/browse/TESTPROJ-42" \
"JIRA_TOKEN must be set" \
"true" "true"
export JIRA_TOKEN="fake-jira-token"

export JIRA_TOKEN=""
run_test "jira-empty-token-fails" \
"https://test.atlassian.net/browse/TESTPROJ-42" \
"JIRA_TOKEN must be set" \
"true" "true"
export JIRA_TOKEN="fake-jira-token"

unset JIRA_USER_EMAIL
run_test "jira-missing-email-fails" \
"https://test.atlassian.net/browse/TESTPROJ-42" \
"JIRA_USER_EMAIL must be set" \
"true" "true"
export JIRA_USER_EMAIL="triage@example.com"

export JIRA_USER_EMAIL=""
run_test "jira-empty-email-fails" \
"https://test.atlassian.net/browse/TESTPROJ-42" \
"JIRA_USER_EMAIL must be set" \
"true" "true"
export JIRA_USER_EMAIL="triage@example.com"

# --- Summary ---

echo ""
Expand Down
21 changes: 21 additions & 0 deletions scripts/pre-triage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,27 @@ tracker_create_issue() {
[[ -n "${JIRA_TRIAGE_OPS_SH_LOADED:-}" ]] && return 0
JIRA_TRIAGE_OPS_SH_LOADED=1

# Validate credentials at source time — fails once, early, on unredirected
# stderr, before any call site can swallow the diagnostic with 2>/dev/null.
# Matches the idiom pre-triage.src.sh / post-triage.src.sh already use for
# ISSUE_URL and FULLSEND_TRACKER.
: "${JIRA_USER_EMAIL:?JIRA_USER_EMAIL must be set}"
: "${JIRA_TOKEN:?JIRA_TOKEN must be set}"

# JIRA_BASE_URL is derived at runtime by tracker_parse_issue_url, so it
# cannot be validated at source time — keep a per-call guard for it.
_jira_require_vars() {
if [[ -z "${JIRA_BASE_URL:-}" ]]; then echo "ERROR: JIRA_BASE_URL is not set" >&2; return 1; fi
}

_jira_api() {
local method="$1"
shift
local endpoint="$1"
shift

_jira_require_vars || return 1

curl --fail --silent --show-error \
--connect-timeout 10 --max-time 30 \
--user "${JIRA_USER_EMAIL}:${JIRA_TOKEN}" \
Expand All @@ -521,6 +537,9 @@ _jira_api_with_status() {
shift
local endpoint="$1"
shift

_jira_require_vars || return 1

local err_file
err_file=$(mktemp)
local raw
Expand Down Expand Up @@ -678,6 +697,7 @@ tracker_create_label() {

tracker_post_comment() {
local body="$1"
_jira_require_vars || return 1
# `fullsend issues post-comment` always does marker-based find-and-update;
# there is no "always create new" mode. A marker unique to this invocation
# guarantees no prior comment matches it, so this always creates a new
Expand All @@ -701,6 +721,7 @@ tracker_post_comment() {
tracker_post_sticky_comment() {
local body="$1"
local marker="$2"
_jira_require_vars || return 1
printf '%s' "${body}" | fullsend issues post-comment --tracker jira \
--project "${REPO}" --number "${JIRA_ISSUE_NUM}" \
--jira-url "${JIRA_BASE_URL}" --jira-email "${JIRA_USER_EMAIL}" --token "${JIRA_TOKEN}" \
Expand Down
Loading