|
9 | 9 | # - OR that a #source0 comment is a substring of the cgmanifest URL |
10 | 10 | # - The URL listed in the cgmanifets is valid (can be downloaded) |
11 | 11 |
|
12 | | -# $@ - Paths to spec files to check |
| 12 | +# $1 - Path to worker chroot's archive |
| 13 | +# $2+ - Paths to spec files to check |
13 | 14 |
|
14 | | -# shellcheck source=../../toolkit/scripts/rpmops.sh |
15 | | -source "$(git rev-parse --show-toplevel)"/toolkit/scripts/rpmops.sh |
| 15 | +set -euo pipefail |
16 | 16 |
|
17 | 17 | # Specs, which contain multiple source files and are split into many entries inside 'cgmanifest.json'. |
18 | 18 | ignore_multiple_sources=" \ |
@@ -56,180 +56,172 @@ ignore_no_source_tarball=" \ |
56 | 56 | web-assets \ |
57 | 57 | " |
58 | 58 |
|
59 | | -# Specs where cgmanifest validation has known issues checking URLs. |
60 | | -ignore_known_issues=" \ |
61 | | - virglrenderer \ |
62 | | - libesmtp" |
63 | | - |
64 | 59 | alt_source_tag="Source9999" |
65 | 60 |
|
66 | | -function prepare_lua { |
67 | | - local azl_lua_dir |
68 | | - local azl_srpm_lua_dir |
69 | | - local lua_common_path |
70 | | - local lua_forge_path |
71 | | - local lua_python_path |
72 | | - local rpm_lua_dir |
73 | | - local rpm_macros_dir |
74 | | - |
75 | | - rpm_macros_dir="$1" |
76 | | - |
77 | | - lua_common_path="common.lua" |
78 | | - lua_forge_path="srpm/forge.lua" |
79 | | - lua_python_path="srpm/python.lua" |
80 | | - rpm_lua_dir="$(rpm --eval "%_rpmluadir")" |
81 | | - azl_lua_dir="$rpm_lua_dir/azl" |
82 | | - azl_srpm_lua_dir="$azl_lua_dir/srpm" |
83 | | - |
84 | | - if [[ -z "$rpm_lua_dir" ]] |
85 | | - then |
86 | | - echo "ERROR: no RPM LUA directory set, can't update with Azure Linux's LUA modules!" >&2 |
87 | | - exit 1 |
88 | | - fi |
89 | | - |
90 | | - # We only want to clean-up directories, which were absent from the system. |
91 | | - for dir_path in "$rpm_lua_dir" "$azl_lua_dir" "$azl_srpm_lua_dir" |
92 | | - do |
93 | | - if [[ ! -d "$dir_path" ]] |
94 | | - then |
95 | | - FILES_TO_CLEAN_UP+=("$dir_path") |
96 | | - break |
97 | | - fi |
98 | | - done |
99 | | - sudo mkdir -p "$azl_srpm_lua_dir" |
100 | | - |
101 | | - for file_path in "$lua_common_path" "$lua_forge_path" "$lua_python_path" |
| 61 | +prepare_chroot_environment() { |
| 62 | + local chroot_archive |
| 63 | + local chroot_dir_path |
| 64 | + local chroot_rpm_macros_dir_path |
| 65 | + local dist_name |
| 66 | + local dist_number |
| 67 | + local dist_tag |
| 68 | + local rpm_macros_dir_path |
| 69 | + |
| 70 | + chroot_archive="$1" |
| 71 | + chroot_dir_path="$2" |
| 72 | + |
| 73 | + echo "Creating worker chroot under '$chroot_dir_path'." |
| 74 | + |
| 75 | + sudo tar -xf "$chroot_archive" -C "$chroot_dir_path" |
| 76 | + sudo chown -R "$(id -u):$(id -g)" "$chroot_dir_path" |
| 77 | + |
| 78 | + rpm_macros_dir_path="$(sudo chroot "$chroot_dir_path" rpm --eval '%{_rpmmacrodir}')" |
| 79 | + echo "Creating the RPM macros directory '$rpm_macros_dir_path' in the chroot." |
| 80 | + chroot_rpm_macros_dir_path="$chroot_dir_path/$rpm_macros_dir_path" |
| 81 | + mkdir -vp "$chroot_rpm_macros_dir_path" |
| 82 | + |
| 83 | + echo "Setting RPM's macros for the RPM queries inside the new chroot:" |
| 84 | + dist_tag=$(make -sC toolkit get-dist-tag) |
| 85 | + # Dist name is extracted from the dist tag by removing the leading dot and the number suffix. |
| 86 | + # Example: ".azl3" -> "azl" |
| 87 | + dist_name="$(sed -E 's/^\.(.*)[0-9]+$/\1/' <<<"$dist_tag")" |
| 88 | + # Dist number is the number suffix of the dist tag. |
| 89 | + # Example: ".azl3" -> "3" |
| 90 | + dist_number="$(grep -oP "\d+$" <<<"$dist_tag")" |
| 91 | + echo "%dist $dist_tag" | tee "$chroot_rpm_macros_dir_path/macros.dist" |
| 92 | + echo "%$dist_name $dist_number" | tee -a "$chroot_rpm_macros_dir_path/macros.dist" |
| 93 | + echo "%with_check 1" | tee -a "$chroot_rpm_macros_dir_path/macros.dist" |
| 94 | + for macro_file in SPECS/azurelinux-rpm-macros/macros* SPECS/pyproject-rpm-macros/macros.pyproject SPECS/perl/macros.perl |
102 | 95 | do |
103 | | - system_lua_path="$azl_lua_dir/$file_path" |
104 | | - if [[ ! -f "$system_lua_path" ]] |
105 | | - then |
106 | | - sudo cp "$rpm_macros_dir/$(basename "$file_path")" "$system_lua_path" |
107 | | - FILES_TO_CLEAN_UP+=("$system_lua_path") |
108 | | - fi |
| 96 | + sudo cp -v "$macro_file" "$chroot_rpm_macros_dir_path" |
109 | 97 | done |
110 | | -} |
111 | 98 |
|
112 | | -function specs_dir_from_spec_path { |
113 | | - # Assuming we always check specs inside Azure Linux's core GitHub repository. |
114 | | - # If that's the case, the spec paths will always have the following form: |
115 | | - # [repo_directory_path]/[specs_directory]/[package_name]/[package_spec_files] |
116 | | - echo "$(realpath "$(dirname "$1")/../../SPECS")/azurelinux-rpm-macros" |
| 99 | + echo |
117 | 100 | } |
118 | 101 |
|
119 | | -rm -f bad_registrations.txt |
120 | | -rm -rf ./cgmanifest_test_dir/ |
121 | | - |
122 | | -if [[ $# -eq 0 ]] |
| 102 | +if [[ $# -lt 2 ]] |
123 | 103 | then |
124 | 104 | echo "No specs passed to validate." |
125 | | - exit |
| 105 | + exit 1 |
126 | 106 | fi |
127 | 107 |
|
| 108 | +if [[ ! -f "$1" ]] |
| 109 | +then |
| 110 | + echo "First argument is not a valid file. Please pass the path to the worker chroot's archive." |
| 111 | + exit 1 |
| 112 | +fi |
| 113 | + |
| 114 | +rm -f bad_registrations.txt |
| 115 | + |
128 | 116 | WORK_DIR=$(mktemp -d -t) |
129 | | -FILES_TO_CLEAN_UP=("$WORK_DIR") |
130 | 117 | function clean_up { |
131 | | - echo "Cleaning up..." |
132 | | - for file_path in "${FILES_TO_CLEAN_UP[@]}" |
133 | | - do |
134 | | - echo " Removing ($file_path)." |
135 | | - sudo rm -rf "$file_path" |
136 | | - done |
| 118 | + echo "Removing the temporary directory '$WORK_DIR'." |
| 119 | + rm -rf "$WORK_DIR" |
137 | 120 | } |
138 | 121 | trap clean_up EXIT SIGINT SIGTERM |
139 | 122 |
|
| 123 | +prepare_chroot_environment "$1" "$WORK_DIR" |
140 | 124 |
|
141 | | -azl_macros_dir="$(specs_dir_from_spec_path "$1")" |
142 | | -prepare_lua "$azl_macros_dir" |
143 | | - |
| 125 | +shift # Remove the first argument (the chroot archive) from the list of specs to check. |
144 | 126 | echo "Checking $# specs." |
145 | 127 |
|
146 | 128 | i=0 |
147 | 129 | for original_spec in "$@" |
148 | 130 | do |
149 | 131 | i=$((i+1)) |
150 | | - echo "[$i/$#] Checking $original_spec" |
| 132 | + echo "[$i/$#] Checking $original_spec." |
151 | 133 |
|
152 | 134 | # Using a copy of the spec file, because parsing requires some pre-processing. |
153 | 135 | original_spec_dir_path="$(dirname "$original_spec")" |
154 | 136 | cp -r "$original_spec_dir_path" "$WORK_DIR" |
155 | 137 |
|
156 | 138 | original_spec_dir_name="$(basename "$original_spec_dir_path")" |
157 | | - spec="$WORK_DIR/$original_spec_dir_name/$(basename "$original_spec")" |
| 139 | + chroot_spec="$original_spec_dir_name/$(basename "$original_spec")" |
| 140 | + host_spec="$WORK_DIR/$chroot_spec" |
158 | 141 |
|
159 | 142 | # Skipping specs for signed packages. Their unsigned versions should already be included in the manifest. |
160 | 143 | if echo "$original_spec" | grep -q "SPECS-SIGNED" |
161 | 144 | then |
162 | | - echo " $spec is being ignored (reason: signed package), skipping" |
| 145 | + echo " $host_spec is being ignored (reason: signed package), skipping." |
163 | 146 | continue |
164 | 147 | fi |
165 | 148 |
|
166 | 149 | # Pre-processing alternate sources (commented-out "Source" lines with full URLs), if present. Currently we only care about the first source. |
167 | 150 | # First, we replace "%%" with "%" in the alternate source's line. |
168 | | - sed -Ei "/^#\s*Source0?:.*%%.*/s/%%/%/g" "$spec" |
| 151 | + sed -Ei "/^#\s*Source0?:.*%%.*/s/%%/%/g" "$host_spec" |
169 | 152 | # Then we uncomment it. |
170 | | - sed -Ei "s/^#\s*Source0?:/$alt_source_tag:/" "$spec" |
| 153 | + sed -Ei "s/^#\s*Source0?:/$alt_source_tag:/" "$host_spec" |
171 | 154 |
|
172 | 155 | # Removing trailing comments from "Source" tags. |
173 | | - sed -Ei "s/^(\s*Source[0-9]*:.*)#.*/\1/" "$spec" |
| 156 | + sed -Ei "s/^(\s*Source[0-9]*:.*)#.*/\1/" "$host_spec" |
174 | 157 |
|
175 | | - name=$(mariner_rpmspec --srpm --qf "%{NAME}" -q "$spec" 2>/dev/null) |
| 158 | + name=$(sudo chroot "$WORK_DIR" rpmspec --srpm --qf "%{NAME}" -q "$chroot_spec" 2>/dev/null) |
176 | 159 | if [[ -z $name ]] |
177 | 160 | then |
178 | 161 | echo "Failed to get name from '$original_spec'. Please update the spec or the macros from the 'defines' variable in this script. Error:" >> bad_registrations.txt |
179 | | - mariner_rpmspec --srpm --qf "%{NAME}" -q "$spec" &>> bad_registrations.txt |
| 162 | + sudo chroot "$WORK_DIR" rpmspec --srpm --qf "%{NAME}" -q "$chroot_spec" &>> bad_registrations.txt |
180 | 163 | continue |
181 | 164 | fi |
182 | 165 |
|
183 | 166 | # Skipping specs from the ignore lists. |
184 | | - if echo "$ignore_multiple_sources $ignore_no_source_tarball $ignore_known_issues" | grep -qP "(^|\s)$name($|\s)" |
| 167 | + if echo "$ignore_multiple_sources $ignore_no_source_tarball" | grep -qP "(^|\s)$name($|\s)" |
185 | 168 | then |
186 | | - echo " $name is being ignored (reason: explicitly ignored package), skipping" |
| 169 | + echo " $name is being ignored (reason: explicitly ignored package), skipping." |
187 | 170 | continue |
188 | 171 | fi |
189 | 172 |
|
190 | | - version=$(mariner_rpmspec --srpm --qf "%{VERSION}" -q "$spec" 2>/dev/null ) |
| 173 | + version=$(sudo chroot "$WORK_DIR" rpmspec --srpm --qf "%{VERSION}" -q "$chroot_spec" 2>/dev/null ) |
191 | 174 | if [[ -z $version ]] |
192 | 175 | then |
193 | 176 | echo "Failed to get version from '$original_spec'. Please update the spec or the macros from the 'defines' variable in this script. Error:" >> bad_registrations.txt |
194 | | - mariner_rpmspec --srpm --qf "%{VERSION}" -q "$spec" &>> bad_registrations.txt |
| 177 | + sudo chroot "$WORK_DIR" rpmspec --srpm --qf "%{VERSION}" -q "$chroot_spec" &>> bad_registrations.txt |
195 | 178 | continue |
196 | 179 | fi |
197 | 180 |
|
198 | | - parsed_spec="$(mariner_rpmspec --parse "$spec" 2>/dev/null)" |
| 181 | + parsed_spec="$(sudo chroot "$WORK_DIR" rpmspec --parse "$chroot_spec" 2>/dev/null)" |
199 | 182 |
|
200 | 183 | # Reading the source0 file/URL. |
201 | | - source0=$(echo "$parsed_spec" | grep -P "^\s*Source0?:" | cut -d: -f2- | xargs) |
202 | | - if [[ -z $source0 ]] |
| 184 | + if ! echo "$parsed_spec" | grep -qP "^\s*Source0?:" |
203 | 185 | then |
204 | | - echo " No source file listed for $name:$version, skipping" |
| 186 | + echo " No source file listed for $name:$version, skipping." |
205 | 187 | continue |
206 | 188 | fi |
207 | 189 |
|
| 190 | + source0=$(echo "$parsed_spec" | grep -P "^\s*Source0?:" | cut -d: -f2- | xargs) |
| 191 | + echo " Source0: $source0." |
| 192 | + |
208 | 193 | # Reading the alternate source URL. |
209 | | - source0alt=$(echo "$parsed_spec" | grep -P "^\s*$alt_source_tag:" | cut -d: -f2- | xargs) |
| 194 | + source0_alt="" |
| 195 | + if echo "$parsed_spec" | grep -qP "^\s*$alt_source_tag:" |
| 196 | + then |
| 197 | + source0_alt=$(echo "$parsed_spec" | grep -P "^\s*$alt_source_tag:" | cut -d: -f2- | xargs) |
| 198 | + echo " Source0Alt: $source0_alt." |
| 199 | + fi |
210 | 200 |
|
211 | 201 | # Pull the current registration from the cgmanifest file. Every registration should have a URL, so if we don't find one |
212 | 202 | # that implies the registration is missing. |
213 | | - manifesturl=$(jq --raw-output ".Registrations[].component.other | select(.name==\"$name\" and .version==\"$version\") | .downloadUrl" cgmanifest.json) |
214 | | - if [[ -z $manifesturl ]] |
| 203 | + manifest_url=$(jq --raw-output ".Registrations[].component.other | select(.name==\"$name\" and .version==\"$version\") | .downloadUrl" cgmanifest.json) |
| 204 | + if [[ -z $manifest_url ]] |
215 | 205 | then |
216 | 206 | echo "Registration for $name:$version is missing" >> bad_registrations.txt |
217 | 207 | else |
218 | | - if [[ "$manifesturl" != "$source0" && "$manifesturl" != "$source0alt" ]] |
| 208 | + echo " Registration URL: $manifest_url." |
| 209 | + |
| 210 | + if [[ "$manifest_url" != "$source0" && "$manifest_url" != "$source0_alt" ]] |
219 | 211 | then |
220 | 212 | { |
221 | | - echo "Registration URL for $name:$version ($manifesturl) matches neither the first \"Source\" tag nor the alternate source URL." |
| 213 | + echo "Registration URL for $name:$version ($manifest_url) matches neither the first \"Source\" tag nor the alternate source URL." |
222 | 214 | printf '\tFirst "Source" tag:\t%s\n' "$source0" |
223 | | - printf '\tAlternate source URL:\t%s\n' "$source0alt" |
| 215 | + printf '\tAlternate source URL:\t%s\n' "$source0_alt" |
224 | 216 | } >> bad_registrations.txt |
225 | 217 | else |
226 | 218 | # Try a few times to download the source listed in the manifest |
227 | 219 | # Parsing output instead of using error codes because 'wget' returns code 8 for FTP, even if the file exists. |
228 | 220 | # Sample HTTP(S) output: Remote file exists. |
229 | 221 | # Sample FTP output: File ‘time-1.9.tar.gz’ exists. |
230 | | - if ! wget --secure-protocol=TLSv1_2 --spider --timeout=30 --tries=10 "${manifesturl}" 2>&1 | grep -qP "^(Remote file|File ‘.*’) exists.*" |
| 222 | + if ! wget --secure-protocol=TLSv1_2 --spider --timeout=30 --tries=10 "${manifest_url}" 2>&1 | grep -qP "^(Remote file|File ‘.*’) exists.*" |
231 | 223 | then |
232 | | - echo "Registration for $name:$version has invalid URL '$manifesturl' (could not download)" >> bad_registrations.txt |
| 224 | + echo "Registration for $name:$version has invalid URL '$manifest_url' (could not download)" >> bad_registrations.txt |
233 | 225 | fi |
234 | 226 | fi |
235 | 227 | fi |
|
0 commit comments