diff options
| -rw-r--r-- | meta/classes/buildhistory.bbclass | 18 | ||||
| -rw-r--r-- | meta/lib/oe/buildhistory_analysis.py | 51 |
2 files changed, 47 insertions, 22 deletions
diff --git a/meta/classes/buildhistory.bbclass b/meta/classes/buildhistory.bbclass index 34cc297909..69a9d02a5a 100644 --- a/meta/classes/buildhistory.bbclass +++ b/meta/classes/buildhistory.bbclass | |||
| @@ -312,6 +312,14 @@ buildhistory_get_imageinfo() { | |||
| 312 | # This awk script is somewhat messy, but handles where the size is not printed for device files under pseudo | 312 | # This awk script is somewhat messy, but handles where the size is not printed for device files under pseudo |
| 313 | ( cd ${IMAGE_ROOTFS} && find . -ls | awk '{ if ( $7 ~ /[0-9]/ ) printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, $7, $11, $12, $13 ; else printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, 0, $10, $11, $12 }' > ${BUILDHISTORY_DIR_IMAGE}/files-in-image.txt ) | 313 | ( cd ${IMAGE_ROOTFS} && find . -ls | awk '{ if ( $7 ~ /[0-9]/ ) printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, $7, $11, $12, $13 ; else printf "%s %10-s %10-s %10s %s %s %s\n", $3, $5, $6, 0, $10, $11, $12 }' > ${BUILDHISTORY_DIR_IMAGE}/files-in-image.txt ) |
| 314 | 314 | ||
| 315 | # Record some machine-readable meta-information about the image | ||
| 316 | echo -n > ${BUILDHISTORY_DIR_IMAGE}/image-info.txt | ||
| 317 | cat >> ${BUILDHISTORY_DIR_IMAGE}/image-info.txt <<END | ||
| 318 | ${@buildhistory_get_imagevars(d)} | ||
| 319 | END | ||
| 320 | imagesize=`du -ks ${IMAGE_ROOTFS} | awk '{ print $1 }'` | ||
| 321 | echo "IMAGESIZE = $imagesize" >> ${BUILDHISTORY_DIR_IMAGE}/image-info.txt | ||
| 322 | |||
| 315 | # Add some configuration information | 323 | # Add some configuration information |
| 316 | echo "${MACHINE}: ${IMAGE_BASENAME} configured for ${DISTRO} ${DISTRO_VERSION}" > ${BUILDHISTORY_DIR_IMAGE}/build-id | 324 | echo "${MACHINE}: ${IMAGE_BASENAME} configured for ${DISTRO} ${DISTRO_VERSION}" > ${BUILDHISTORY_DIR_IMAGE}/build-id |
| 317 | 325 | ||
| @@ -330,6 +338,16 @@ def buildhistory_get_layers(d): | |||
| 330 | return layertext | 338 | return layertext |
| 331 | 339 | ||
| 332 | 340 | ||
| 341 | def buildhistory_get_imagevars(d): | ||
| 342 | imagevars = "DISTRO DISTRO_VERSION USER_CLASSES IMAGE_CLASSES IMAGE_FEATURES IMAGE_LINGUAS IMAGE_INSTALL BAD_RECOMMENDATIONS ROOTFS_POSTPROCESS_COMMAND IMAGE_POSTPROCESS_COMMAND" | ||
| 343 | |||
| 344 | ret = "" | ||
| 345 | for var in imagevars.split(): | ||
| 346 | value = d.getVar(var, True) or "" | ||
| 347 | ret += "%s = %s\n" % (var, value) | ||
| 348 | return ret.rstrip('\n') | ||
| 349 | |||
| 350 | |||
| 333 | buildhistory_commit() { | 351 | buildhistory_commit() { |
| 334 | if [ ! -d ${BUILDHISTORY_DIR} ] ; then | 352 | if [ ! -d ${BUILDHISTORY_DIR} ] ; then |
| 335 | # Code above that creates this dir never executed, so there can't be anything to commit | 353 | # Code above that creates this dir never executed, so there can't be anything to commit |
diff --git a/meta/lib/oe/buildhistory_analysis.py b/meta/lib/oe/buildhistory_analysis.py index 9f42fe38ac..d3c0448fd1 100644 --- a/meta/lib/oe/buildhistory_analysis.py +++ b/meta/lib/oe/buildhistory_analysis.py | |||
| @@ -15,16 +15,15 @@ import git | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | # How to display fields | 17 | # How to display fields |
| 18 | pkg_list_fields = ['DEPENDS', 'RDEPENDS', 'RRECOMMENDS', 'PACKAGES', 'FILES', 'FILELIST'] | 18 | list_fields = ['DEPENDS', 'RDEPENDS', 'RRECOMMENDS', 'PACKAGES', 'FILES', 'FILELIST', 'USER_CLASSES', 'IMAGE_CLASSES', 'IMAGE_FEATURES', 'IMAGE_LINGUAS', 'IMAGE_INSTALL', 'BAD_RECOMMENDATIONS'] |
| 19 | pkg_numeric_fields = ['PKGSIZE'] | 19 | numeric_fields = ['PKGSIZE', 'IMAGESIZE'] |
| 20 | # Fields to monitor | 20 | # Fields to monitor |
| 21 | pkg_monitor_fields = ['RDEPENDS', 'RRECOMMENDS', 'PACKAGES', 'FILELIST', 'PKGSIZE'] | 21 | monitor_fields = ['RDEPENDS', 'RRECOMMENDS', 'PACKAGES', 'FILELIST', 'PKGSIZE', 'IMAGESIZE'] |
| 22 | # Percentage change to alert for numeric fields | 22 | # Percentage change to alert for numeric fields |
| 23 | pkg_monitor_numeric_threshold = 20 | 23 | monitor_numeric_threshold = 20 |
| 24 | # Image files to monitor | 24 | # Image files to monitor (note that image-info.txt is handled separately) |
| 25 | img_monitor_files = ['installed-package-names.txt', 'files-in-image.txt'] | 25 | img_monitor_files = ['installed-package-names.txt', 'files-in-image.txt'] |
| 26 | 26 | ||
| 27 | |||
| 28 | class ChangeRecord: | 27 | class ChangeRecord: |
| 29 | def __init__(self, path, fieldname, oldvalue, newvalue): | 28 | def __init__(self, path, fieldname, oldvalue, newvalue): |
| 30 | self.path = path | 29 | self.path = path |
| @@ -34,13 +33,13 @@ class ChangeRecord: | |||
| 34 | self.filechanges = None | 33 | self.filechanges = None |
| 35 | 34 | ||
| 36 | def __str__(self): | 35 | def __str__(self): |
| 37 | if self.fieldname in pkg_list_fields: | 36 | if self.fieldname in list_fields: |
| 38 | aitems = self.oldvalue.split(' ') | 37 | aitems = self.oldvalue.split(' ') |
| 39 | bitems = self.newvalue.split(' ') | 38 | bitems = self.newvalue.split(' ') |
| 40 | removed = list(set(aitems) - set(bitems)) | 39 | removed = list(set(aitems) - set(bitems)) |
| 41 | added = list(set(bitems) - set(aitems)) | 40 | added = list(set(bitems) - set(aitems)) |
| 42 | return '%s: %s:%s%s' % (self.path, self.fieldname, ' removed "%s"' % ' '.join(removed) if removed else '', ' added "%s"' % ' '.join(added) if added else '') | 41 | return '%s: %s:%s%s' % (self.path, self.fieldname, ' removed "%s"' % ' '.join(removed) if removed else '', ' added "%s"' % ' '.join(added) if added else '') |
| 43 | elif self.fieldname in pkg_numeric_fields: | 42 | elif self.fieldname in numeric_fields: |
| 44 | aval = int(self.oldvalue) | 43 | aval = int(self.oldvalue) |
| 45 | bval = int(self.newvalue) | 44 | bval = int(self.newvalue) |
| 46 | percentchg = ((bval - aval) / float(aval)) * 100 | 45 | percentchg = ((bval - aval) / float(aval)) * 100 |
| @@ -190,6 +189,25 @@ def compare_lists(alines, blines): | |||
| 190 | return filechanges | 189 | return filechanges |
| 191 | 190 | ||
| 192 | 191 | ||
| 192 | def compare_dict_blobs(path, ablob, bblob, report_all): | ||
| 193 | adict = blob_to_dict(ablob) | ||
| 194 | bdict = blob_to_dict(bblob) | ||
| 195 | |||
| 196 | changes = [] | ||
| 197 | for key in adict: | ||
| 198 | if report_all or key in monitor_fields: | ||
| 199 | if adict[key] != bdict[key]: | ||
| 200 | if (not report_all) and key in numeric_fields: | ||
| 201 | aval = int(adict[key]) | ||
| 202 | bval = int(bdict[key]) | ||
| 203 | percentchg = ((bval - aval) / float(aval)) * 100 | ||
| 204 | if percentchg < monitor_numeric_threshold: | ||
| 205 | continue | ||
| 206 | chg = ChangeRecord(path, key, adict[key], bdict[key]) | ||
| 207 | changes.append(chg) | ||
| 208 | return changes | ||
| 209 | |||
| 210 | |||
| 193 | def process_changes(repopath, revision1, revision2 = 'HEAD', report_all = False): | 211 | def process_changes(repopath, revision1, revision2 = 'HEAD', report_all = False): |
| 194 | repo = git.Repo(repopath) | 212 | repo = git.Repo(repopath) |
| 195 | assert repo.bare == False | 213 | assert repo.bare == False |
| @@ -200,20 +218,7 @@ def process_changes(repopath, revision1, revision2 = 'HEAD', report_all = False) | |||
| 200 | for d in diff.iter_change_type('M'): | 218 | for d in diff.iter_change_type('M'): |
| 201 | path = os.path.dirname(d.a_blob.path) | 219 | path = os.path.dirname(d.a_blob.path) |
| 202 | if path.startswith('packages/'): | 220 | if path.startswith('packages/'): |
| 203 | adict = blob_to_dict(d.a_blob) | 221 | changes.extend(compare_dict_blobs(path, d.a_blob, d.b_blob, report_all)) |
| 204 | bdict = blob_to_dict(d.b_blob) | ||
| 205 | |||
| 206 | for key in adict: | ||
| 207 | if report_all or key in pkg_monitor_fields: | ||
| 208 | if adict[key] != bdict[key]: | ||
| 209 | if (not report_all) and key in pkg_numeric_fields: | ||
| 210 | aval = int(adict[key]) | ||
| 211 | bval = int(bdict[key]) | ||
| 212 | percentchg = ((bval - aval) / float(aval)) * 100 | ||
| 213 | if percentchg < pkg_monitor_numeric_threshold: | ||
| 214 | continue | ||
| 215 | chg = ChangeRecord(path, key, adict[key], bdict[key]) | ||
| 216 | changes.append(chg) | ||
| 217 | elif path.startswith('images/'): | 222 | elif path.startswith('images/'): |
| 218 | filename = os.path.basename(d.a_blob.path) | 223 | filename = os.path.basename(d.a_blob.path) |
| 219 | if filename in img_monitor_files: | 224 | if filename in img_monitor_files: |
| @@ -236,5 +241,7 @@ def process_changes(repopath, revision1, revision2 = 'HEAD', report_all = False) | |||
| 236 | else: | 241 | else: |
| 237 | chg = ChangeRecord(path, filename, d.a_blob.data_stream.read(), d.b_blob.data_stream.read()) | 242 | chg = ChangeRecord(path, filename, d.a_blob.data_stream.read(), d.b_blob.data_stream.read()) |
| 238 | changes.append(chg) | 243 | changes.append(chg) |
| 244 | elif filename == 'image-info.txt': | ||
| 245 | changes.extend(compare_dict_blobs(path, d.a_blob, d.b_blob, report_all)) | ||
| 239 | 246 | ||
| 240 | return changes | 247 | return changes |
