A multi-step process to help Jamf Pro admins zero-in on policy failures

Background
We recently executed a single-script Jamf Pro policy on All Computers and observed a 99.4 percent success rate. While this could certainly be viewed as an A+ result, what to do about the remaining 0.6 percent?
On the 10-year anniversary of Ian Weiss’ Jamf Pro feature request to Export Policy Logs to CSV, the following multi-step process may help Jamf Pro administrators zero-in on policy failures.
Procedure
Complete the following steps to create a Static Computer Group from Policy Failure Logs in Jamf Pro.
A. Save Failed Policy Logs as .RTF
- In Jamf Pro, view to the Failed Policy Logs

- Drag-select and copy the displayed information

- Launch TextEdit and paste the selection

- Save as a
.RTFfile in a new, dedicated folder


B. Convert the .RTF file to .TXT
- Launch Script Editor and click New Document
- Copy-pasta the following Extract URL from RTF AppleScript
# https://www.macscripter.net/t/extract-hyperlinks-from-rtf-and-save-as-readable-plaintext/71429/12
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
set theFolder to choose folder -- choose the folder containing the .rtf files
tell application id "com.apple.finder" -- Finder
set theFiles to every file of theFolder as alias list
end tell
repeat with aFile in theFiles
if (theFiles as text) ends with ".rtf" then
set theURL to (current application's NSURL's fileURLWithPath:(POSIX path of aFile))
set {attString, theError} to (current application's NSAttributedString's alloc()'s initWithURL:theURL options:(missing value) documentAttributes:(missing value) |error|:(reference))
-- get elngth so we can start from the end
set start to (attString's |length|()) - 1
-- make plain string copy to work on
set theString to attString's |string|()'s mutableCopy()
repeat
-- find link
set {aURL, theRange} to (attString's attribute:(current application's NSLinkAttributeName) atIndex:start effectiveRange:(reference))
if aURL is not missing value then
-- get linked text
set linkText to (theString's substringWithRange:theRange)
if (aURL's |scheme|()'s isEqualToString:"mailto") then -- email address
set newLink to aURL's resourceSpecifier()
else if (linkText's containsString:"This Site") then -- resource specifier, remove //
set newLink to (aURL's resourceSpecifier()'s substringFromIndex:2)
else -- full URL
set newLink to aURL's absoluteString()
end if
-- replace link
(theString's replaceCharactersInRange:theRange withString:newLink)
end if
set start to (location of theRange) - 2
if start < 0 then exit repeat
end repeat
set newFile to (theURL's URLByDeletingPathExtension()'s URLByAppendingPathExtension:"txt")
(theString's writeToURL:newFile atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value))
end if
end repeat
- Run the script, selecting the dedicated folder created in Step A.4.

C. Convert the .TXT file to .CSV
- Launch Terminal
- In a new Terminal window, enter:
grep "=" - Drag-and-drop the converted
.TXTfile to the open Terminal window - Enter:
| cut -d '=' -f 2 > ~/Desktop/failures.csv - Press Return

- Using Quick Look, confirm the resultant
.CSVfile contains the expected Jamf Pro Computer IDs

D. Create and Populate a Static Computer Group
- In Jamf Pro, create a Static Computer Group, taking note of its ID number

- Use MUT to populate the newly created Static Computer Group

