1
1
#! /usr/bin/env bash
2
2
set -euo pipefail
3
- PROJECT=' test'
4
3
4
+ export PS4=' +($LINENO): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
5
+ trap ' handle_error ${LINENO}' ERR
5
6
6
- # === Configurable inputs ===
7
- BUILD_INFO_REPO=" ${BUILD_INFO_REPO:- test-build-info} " # project-scoped build-info repo
8
- PARENT_BUILD_NAME=" ${PARENT_BUILD_NAME:- test-build} " # base name, e.g. foo
9
- PARENT_BUILD_ID=" ${PARENT_BUILD_ID:- 129} " # run number, e.g. 1234
10
- PROJECT=" ${PROJECT:- test} " # project key
11
- LOOKBACK=" ${LOOKBACK:- 90d} " # optional: only consider recent runs
7
+ # shellcheck disable=SC2317
8
+ handle_error () {
9
+ local exit_code=$?
10
+ local line_number=$1
11
+ echo " Error: Command failed with exit code $exit_code at line $line_number " >&2
12
+ exit 1
13
+ }
14
+
15
+ error () {
16
+ local reason=" ${1:- } "
17
+ if [[ -n " $reason " ]]; then
18
+ echo " Error: $reason " >&2
19
+ else
20
+ echo " Error" >&2
21
+ fi
22
+ exit 1
23
+ }
24
+
25
+ # Default values
26
+ DRY_RUN=" false"
27
+ PROJECT=" "
28
+ PARENT_BUILD_NAME=" "
29
+ PARENT_BUILD_ID=" "
30
+ BUILD_NAME_PATTERN=" "
31
+ BUILD_INFO_REPO=" "
32
+ LOOKBACK=" 90d"
33
+
34
+ show_help () {
35
+ echo " Usage: $0 --project <project> --parent-build-name <name> --parent-build-id <id> --build-name-pattern <pattern> [OPTIONS]" >&2
36
+ echo " " >&2
37
+ echo " Aggregates multiple JFrog build-infos into a single parent build using jf rt build-append" >&2
38
+ echo " " >&2
39
+ echo " Required Arguments:" >&2
40
+ echo " --project <project> JFrog Artifactory project name" >&2
41
+ echo " --parent-build-name <name> Name for the parent aggregated build" >&2
42
+ echo " --parent-build-id <id> Build ID for the parent aggregated build" >&2
43
+ echo " --build-name-pattern <pattern> Pattern to match matrix build names (e.g., 'test-build-*')" >&2
44
+ echo " " >&2
45
+ echo " Options:" >&2
46
+ echo " --build-info-repo <repo> Project-scoped build-info repo (default: <project>-build-info)" >&2
47
+ echo " --lookback <days> Only consider builds from last N days (default: 90d)" >&2
48
+ echo " --dry-run Show what would be done without actually doing it" >&2
49
+ echo " --help, -h Show this help message" >&2
50
+ echo " " >&2
51
+ echo " Examples:" >&2
52
+ echo " $0 --project test --parent-build-name myapp --parent-build-id 123 --build-name-pattern 'myapp-*'" >&2
53
+ echo " $0 --project test --parent-build-name myapp --parent-build-id 123 --build-name-pattern 'myapp-*' --dry-run" >&2
54
+ }
55
+
56
+ # Parse command line arguments
57
+ echo " Command line: $0 $* " >&2
58
+ while [[ $# -gt 0 ]]; do
59
+ case $1 in
60
+ --project)
61
+ PROJECT=" $2 "
62
+ shift 2
63
+ ;;
64
+ --parent-build-name)
65
+ PARENT_BUILD_NAME=" $2 "
66
+ shift 2
67
+ ;;
68
+ --parent-build-id)
69
+ PARENT_BUILD_ID=" $2 "
70
+ shift 2
71
+ ;;
72
+ --build-name-pattern)
73
+ BUILD_NAME_PATTERN=" $2 "
74
+ shift 2
75
+ ;;
76
+ --build-info-repo)
77
+ BUILD_INFO_REPO=" $2 "
78
+ shift 2
79
+ ;;
80
+ --lookback)
81
+ LOOKBACK=" $2 "
82
+ shift 2
83
+ ;;
84
+ --dry-run)
85
+ DRY_RUN=" true"
86
+ shift
87
+ ;;
88
+ --help|-h)
89
+ show_help
90
+ exit 0
91
+ ;;
92
+ -* )
93
+ echo " Unknown option: $1 " >&2
94
+ echo " Use --help for usage information" >&2
95
+ exit 1
96
+ ;;
97
+ * )
98
+ echo " Unexpected argument: $1 " >&2
99
+ echo " Use --help for usage information" >&2
100
+ exit 1
101
+ ;;
102
+ esac
103
+ done
104
+
105
+ # Validate required arguments
106
+ if [[ -z " ${PROJECT:- } " ]]; then
107
+ error " --project is required"
108
+ fi
109
+ if [[ -z " ${PARENT_BUILD_NAME:- } " ]]; then
110
+ error " --parent-build-name is required"
111
+ fi
112
+ if [[ -z " ${PARENT_BUILD_ID:- } " ]]; then
113
+ error " --parent-build-id is required"
114
+ fi
115
+ if [[ -z " ${BUILD_NAME_PATTERN:- } " ]]; then
116
+ error " --build-name-pattern is required"
117
+ fi
118
+
119
+ # Set defaults
120
+ if [[ -z " ${BUILD_INFO_REPO:- } " ]]; then
121
+ BUILD_INFO_REPO=" ${PROJECT} -build-info"
122
+ fi
12
123
13
124
# === Derived ===
14
125
SUFFIX_PREFIX=" ${PARENT_BUILD_NAME} -"
15
126
127
+ # Run function for dry-run support
128
+ run () {
129
+ if [[ " $DRY_RUN " == " true" ]]; then
130
+ echo " Would run: $* " >&2
131
+ else
132
+ echo " Running: $* " >&2
133
+ " $@ "
134
+ fi
135
+ }
136
+
16
137
echo " Build-info repo: $BUILD_INFO_REPO "
17
138
echo " Parent build: $PARENT_BUILD_NAME /$PARENT_BUILD_ID "
18
139
echo " Suffix prefix: $SUFFIX_PREFIX "
@@ -27,7 +148,7 @@ read -r -d '' AQL <<AQL || true
27
148
items.find({
28
149
"\$ and":[
29
150
{"repo":{"\$ eq":"$BUILD_INFO_REPO "}},
30
- {"path":{"\$ match ":"$SUFFIX_PREFIX * "}},
151
+ {"path":{"\$ eq ":"$PARENT_BUILD_NAME "}},
31
152
{"name":{"\$ match":"$PARENT_BUILD_ID -*.json"}},
32
153
{"created":{"\$ gte":"$LOOKBACK_DATE "}}
33
154
]
@@ -39,26 +160,34 @@ RESP=$(jf rt curl -XPOST api/search/aql \
39
160
-H ' Content-Type: text/plain' \
40
161
-d " $AQL " )
41
162
42
- # === Extract child names and build numbers ===
163
+ # === Extract child names from file names ===
43
164
if echo " $RESP " | jq -e ' .results' > /dev/null 2>&1 ; then
44
165
echo " Raw AQL results:"
45
166
echo " $RESP " | jq ' .results[] | {path: .path, name: .name}'
46
167
echo " ---"
47
168
48
- # Extract build numbers from the file names
49
- echo " Extracting build numbers from file names:"
50
- echo " $RESP " | jq -r ' .results[] | .name' | while read -r filename; do
51
- # Extract build number from filename like "129-amzn2023-x86_64-1758049781295.json"
52
- build_num=$( echo " $filename " | cut -d' -' -f1)
53
- echo " File: $filename -> Build number: $build_num "
169
+ # Extract child build IDs from file names like "132-amzn2023-x86_64-1758073733638.json"
170
+ # The pattern is: ${MATRIX_BUILD_ID}-${TIMESTAMP}.json
171
+ # We want to extract the matrix build ID (which includes the parent build ID + matrix suffix)
172
+ # Filter out the parent build ID itself (e.g., "132" without matrix suffix)
173
+ mapfile -t CHILD_BUILD_IDS < <( echo " $RESP " | jq -r ' .results[] | .name' | sed ' s/-[0-9]*\.json$//' | grep -v " ^${PARENT_BUILD_ID} $" | sort -u)
174
+
175
+ # All matrix builds have the same build name (the parent build name)
176
+ # Create array of build names (all the same) corresponding to each build ID
177
+ CHILD_NAMES=()
178
+ for _ in " ${CHILD_BUILD_IDS[@]} " ; do
179
+ CHILD_NAMES+=(" $PARENT_BUILD_NAME " )
54
180
done
55
- echo " ---"
56
-
57
- mapfile -t CHILD_NAMES < <( echo " $RESP " | jq -r ' .results[].path' | sort -u)
181
+
182
+ echo " Extracted build IDs:"
183
+ for i in " ${! CHILD_BUILD_IDS[@]} " ; do
184
+ echo " - ${CHILD_BUILD_IDS[$i]} "
185
+ done
186
+
58
187
echo " Found ${# CHILD_NAMES[@]} child builds"
59
188
echo " Child builds found:"
60
- for child in " ${CHILD_NAMES[@]} " ; do
61
- echo " - $child "
189
+ for i in " ${! CHILD_NAMES[@]} " ; do
190
+ echo " - ${CHILD_NAMES[$i]} / ${CHILD_BUILD_IDS[$i]} "
62
191
done
63
192
else
64
193
echo " Invalid JSON response or no results field"
@@ -70,19 +199,33 @@ if (( ${#CHILD_NAMES[@]} == 0 )); then
70
199
exit 0
71
200
fi
72
201
202
+ # === First, let's see what builds actually exist ===
203
+ echo " Listing all builds for build name: ${PARENT_BUILD_NAME} "
204
+ LIST_BUILDS=$( run jf rt curl " api/build?buildName=${PARENT_BUILD_NAME} &project=${PROJECT} " 2> /dev/null)
205
+ echo " Available builds for ${PARENT_BUILD_NAME} : $LIST_BUILDS "
206
+
73
207
# === Append each child build to the parent ===
74
- for child in " ${CHILD_NAMES[@]} " ; do
75
- [[ " $child " == " $PARENT_BUILD_NAME " ]] && continue
208
+ for i in " ${! CHILD_NAMES[@]} " ; do
209
+ child_name=" ${CHILD_NAMES[$i]} "
210
+ child_build_id=" ${CHILD_BUILD_IDS[$i]} "
211
+
212
+ echo " $child_name is a child build with ID $child_build_id "
76
213
77
214
# Check if the child build exists in Artifactory
78
- echo " Checking if build ${child} /${PARENT_BUILD_ID} exists..."
79
- BUILD_CHECK=$( jf rt curl " api/build/${child} /${PARENT_BUILD_ID} ?projectKey=${PROJECT} " 2> /dev/null)
215
+ echo " Checking if build ${child_name} /${child_build_id} exists..."
216
+ echo " API URL: api/build/${child_name} /${child_build_id} ?project=${PROJECT} "
217
+ BUILD_CHECK=$( run jf rt curl " api/build/${child_name} /${child_build_id} ?project=${PROJECT} " 2> /dev/null)
218
+ echo " Build check response: $BUILD_CHECK "
219
+
80
220
if echo " $BUILD_CHECK " | jq -e ' .errors' > /dev/null 2>&1 ; then
81
- echo " Build ${child } /${PARENT_BUILD_ID } not found in Artifactory, skipping..."
221
+ echo " Build ${child_name } /${child_build_id } not found in Artifactory, skipping..."
82
222
else
83
- echo " Appending ${child} /${PARENT_BUILD_ID} -> ${PARENT_BUILD_NAME} /${PARENT_BUILD_ID} "
84
- jf rt build-append " $PARENT_BUILD_NAME " " $PARENT_BUILD_ID " \
85
- " $child " " $PARENT_BUILD_ID " \
86
- --project=" $PROJECT " || true
223
+ echo " Build ${child_name} /${child_build_id} found! Appending to parent..."
224
+ echo " Appending ${child_name} /${child_build_id} -> ${PARENT_BUILD_NAME} /${PARENT_BUILD_ID} "
225
+ run jf rt build-append " $PARENT_BUILD_NAME " " $PARENT_BUILD_ID " \
226
+ " $child_name " " $child_build_id " \
227
+ --project=" $PROJECT "
228
+ echo " Append command completed for ${child_name} /${child_build_id} "
87
229
fi
88
230
done
231
+ run jf rt build-publish " $PARENT_BUILD_NAME " " $PARENT_BUILD_ID " --project=" $PROJECT "
0 commit comments