|
46 | 46 | TITLE=$(echo "$RESPONSE" | jq -r '.data.issue.title // "Unknown"') |
47 | 47 | URL=$(echo "$RESPONSE" | jq -r '.data.issue.url // ""') |
48 | 48 |
|
| 49 | + # Remove newlines from title (jq will handle other escaping) |
| 50 | + TITLE=$(echo "$TITLE" | tr -d '\n\r') |
| 51 | + |
49 | 52 | if [ "$TITLE" != "Unknown" ]; then |
50 | 53 | if [ -n "$URL" ]; then |
51 | 54 | TICKET_LINES+=("• <${URL}|${TITLE}> (${TICKET_ID})") |
@@ -85,97 +88,109 @@ for msg_num in $(seq 1 $TOTAL_MESSAGES); do |
85 | 88 | END_IDX=$((TICKET_COUNT - 1)) |
86 | 89 | fi |
87 | 90 |
|
88 | | - # Build ticket list for this message |
| 91 | + # Build ticket list for this message (join with newlines) |
89 | 92 | TICKET_DETAILS="" |
90 | 93 | for i in $(seq $START_IDX $END_IDX); do |
91 | | - TICKET_DETAILS="${TICKET_DETAILS}\n${TICKET_LINES[$i]}" |
| 94 | + if [ -n "$TICKET_DETAILS" ]; then |
| 95 | + TICKET_DETAILS="${TICKET_DETAILS} |
| 96 | +${TICKET_LINES[$i]}" |
| 97 | + else |
| 98 | + TICKET_DETAILS="${TICKET_LINES[$i]}" |
| 99 | + fi |
92 | 100 | done |
93 | 101 |
|
94 | | - # Create header block (only for first message) |
| 102 | + # Build JSON payload using jq for proper escaping |
95 | 103 | if [ $msg_num -eq 1 ]; then |
96 | | - HEADER_BLOCKS=$(cat <<EOF |
97 | | - { |
98 | | - "type": "header", |
99 | | - "text": { |
100 | | - "type": "plain_text", |
101 | | - "text": "${EMOJI} ${TITLE_TEXT}", |
102 | | - "emoji": true |
103 | | - } |
104 | | - }, |
105 | | - { |
106 | | - "type": "section", |
107 | | - "fields": [ |
108 | | - { |
109 | | - "type": "mrkdwn", |
110 | | - "text": "*Application:*\n\`${REPOSITORY_NAME}\`" |
111 | | - }, |
112 | | - { |
113 | | - "type": "mrkdwn", |
114 | | - "text": "*Environment:*\n\`${ENVIRONMENT}\`" |
115 | | - } |
116 | | - ] |
117 | | - }, |
118 | | - { |
119 | | - "type": "divider" |
120 | | - }, |
121 | | - { |
122 | | - "type": "section", |
123 | | - "text": { |
124 | | - "type": "mrkdwn", |
125 | | - "text": "${MESSAGE_TEXT}" |
126 | | - } |
127 | | - }, |
128 | | -EOF |
129 | | -) |
| 104 | + # First message with full header |
| 105 | + SLACK_PAYLOAD=$(jq -n \ |
| 106 | + --arg emoji "$EMOJI" \ |
| 107 | + --arg title "$TITLE_TEXT" \ |
| 108 | + --arg app "$REPOSITORY_NAME" \ |
| 109 | + --arg env "$ENVIRONMENT" \ |
| 110 | + --arg msg "$MESSAGE_TEXT" \ |
| 111 | + --arg tickets "$TICKET_DETAILS" \ |
| 112 | + --arg pr_url "${PR_URL:-}" \ |
| 113 | + '{ |
| 114 | + blocks: [ |
| 115 | + { |
| 116 | + type: "header", |
| 117 | + text: { |
| 118 | + type: "plain_text", |
| 119 | + text: ($emoji + " " + $title), |
| 120 | + emoji: true |
| 121 | + } |
| 122 | + }, |
| 123 | + { |
| 124 | + type: "section", |
| 125 | + fields: [ |
| 126 | + { |
| 127 | + type: "mrkdwn", |
| 128 | + text: ("*Application:*\n`" + $app + "`") |
| 129 | + }, |
| 130 | + { |
| 131 | + type: "mrkdwn", |
| 132 | + text: ("*Environment:*\n`" + $env + "`") |
| 133 | + } |
| 134 | + ] |
| 135 | + }, |
| 136 | + { |
| 137 | + type: "divider" |
| 138 | + }, |
| 139 | + { |
| 140 | + type: "section", |
| 141 | + text: { |
| 142 | + type: "mrkdwn", |
| 143 | + text: $msg |
| 144 | + } |
| 145 | + }, |
| 146 | + { |
| 147 | + type: "section", |
| 148 | + text: { |
| 149 | + type: "mrkdwn", |
| 150 | + text: $tickets |
| 151 | + } |
| 152 | + } |
| 153 | + ] + (if $pr_url != "" then [{ |
| 154 | + type: "section", |
| 155 | + text: { |
| 156 | + type: "mrkdwn", |
| 157 | + text: ("<" + $pr_url + "|View Pull Request>") |
| 158 | + } |
| 159 | + }] else [] end) |
| 160 | + }') |
130 | 161 | else |
131 | | - # Subsequent messages show part number |
132 | | - HEADER_BLOCKS=$(cat <<EOF |
133 | | - { |
134 | | - "type": "section", |
135 | | - "text": { |
136 | | - "type": "mrkdwn", |
137 | | - "text": "*Part ${msg_num}/${TOTAL_MESSAGES}*" |
138 | | - } |
139 | | - }, |
140 | | -EOF |
141 | | -) |
142 | | - fi |
143 | | - |
144 | | - # Create Slack message payload |
145 | | - SLACK_PAYLOAD=$(cat <<EOF |
146 | | -{ |
147 | | - "blocks": [ |
148 | | - ${HEADER_BLOCKS} |
149 | | - { |
150 | | - "type": "section", |
151 | | - "text": { |
152 | | - "type": "mrkdwn", |
153 | | - "text": "${TICKET_DETAILS}" |
154 | | - } |
155 | | - } |
156 | | -EOF |
157 | | -) |
158 | | - |
159 | | - # Add PR URL if available (on all messages) |
160 | | - if [ -n "$PR_URL" ]; then |
161 | | - SLACK_PAYLOAD=$(cat <<EOF |
162 | | -${SLACK_PAYLOAD}, |
163 | | - { |
164 | | - "type": "section", |
165 | | - "text": { |
166 | | - "type": "mrkdwn", |
167 | | - "text": "<${PR_URL}|View Pull Request>" |
168 | | - } |
169 | | - } |
170 | | -EOF |
171 | | -) |
| 162 | + # Subsequent messages with part number |
| 163 | + PART_TEXT="*Part ${msg_num}/${TOTAL_MESSAGES}*" |
| 164 | + SLACK_PAYLOAD=$(jq -n \ |
| 165 | + --arg part "$PART_TEXT" \ |
| 166 | + --arg tickets "$TICKET_DETAILS" \ |
| 167 | + --arg pr_url "${PR_URL:-}" \ |
| 168 | + '{ |
| 169 | + blocks: [ |
| 170 | + { |
| 171 | + type: "section", |
| 172 | + text: { |
| 173 | + type: "mrkdwn", |
| 174 | + text: $part |
| 175 | + } |
| 176 | + }, |
| 177 | + { |
| 178 | + type: "section", |
| 179 | + text: { |
| 180 | + type: "mrkdwn", |
| 181 | + text: $tickets |
| 182 | + } |
| 183 | + } |
| 184 | + ] + (if $pr_url != "" then [{ |
| 185 | + type: "section", |
| 186 | + text: { |
| 187 | + type: "mrkdwn", |
| 188 | + text: ("<" + $pr_url + "|View Pull Request>") |
| 189 | + } |
| 190 | + }] else [] end) |
| 191 | + }') |
172 | 192 | fi |
173 | 193 |
|
174 | | - # Close the JSON |
175 | | - SLACK_PAYLOAD="${SLACK_PAYLOAD} |
176 | | - ] |
177 | | -}" |
178 | | - |
179 | 194 | # Send to Slack |
180 | 195 | RESPONSE=$(curl -s -X POST \ |
181 | 196 | -H "Content-Type: application/json" \ |
|
0 commit comments