Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.3.2 merge to main #209

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file. This projec

Nothing yet.

## [2.3.2] - TBD

### Fixed

- Resolved an issue with Sparkle feed parsing that could cause Recipe Robot to insert a static download URL in URLDownloader if the feed provided a version at the item level instead of the enclosure level (#206).

## [2.3.1] - 2023-10-19

### Fixed
Expand Down Expand Up @@ -410,7 +416,8 @@ Nothing yet.

- Initial public release of Recipe Robot (beta).

[Unreleased]: https://github.com/homebysix/recipe-robot/compare/v2.3.1...HEAD
[Unreleased]: https://github.com/homebysix/recipe-robot/compare/v2.3.2...HEAD
[2.3.2]: https://github.com/homebysix/recipe-robot/compare/v2.3.1...v2.3.2
[2.3.1]: https://github.com/homebysix/recipe-robot/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/homebysix/recipe-robot/compare/v2.2.0...v2.3.0
[2.2.0]: https://github.com/homebysix/recipe-robot/compare/v2.1.0...v2.2.0
Expand Down
89 changes: 70 additions & 19 deletions DEVNOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ Some scattered notes to assist in the design and development of Recipe Robot.

<!-- MarkdownTOC -->

- [Facts](#facts)
- [Interesting examples and edge cases to use for testing:](#interesting-examples-and-edge-cases-to-use-for-testing)
- [Content Types](#content-types)
- [Recipe Robot Development Notes](#recipe-robot-development-notes)
- [Facts](#facts)
- [Interesting examples and edge cases to use for testing:](#interesting-examples-and-edge-cases-to-use-for-testing)
- [Content Types](#content-types)
- [Sparkle feeds](#sparkle-feeds)

<!-- /MarkdownTOC -->

Expand Down Expand Up @@ -227,21 +229,70 @@ recipe-robot --verbose https://bahoom.com/hyperdock/HyperDock.dmg

To get an grasp of the typical content types that Recipe Robot will be dealing with, I ran `curl -sIL` on every SPARKLE_FEED_URL and DOWNLOAD_URL in the homebysix-recipes repo. Here are the content types that were returned:

| Type | Count |
| ----------------------------------- | ----- |
| text/html | 101 |
| application/xml | 62 |
| application/zip | 33 |
| application/x-apple-diskimage | 24 |
| text/xml | 24 |
| application/octet-stream | 22 |
| text/plain | 7 |
| application/xhtml+xml | 5 |
| application/rss+xml | 3 |
| binary/octet-stream | 3 |
| application/vnd.apple.installer+xml | 1 |
| application/x-bzip2 | 1 |
| application/x-rss+xml | 1 |
| plain/text | 1 |
| Type | Count |
| ----------------------------------- | ----- |
| text/html | 101 |
| application/xml | 62 |
| application/zip | 33 |
| application/x-apple-diskimage | 24 |
| text/xml | 24 |
| application/octet-stream | 22 |
| text/plain | 7 |
| application/xhtml+xml | 5 |
| application/rss+xml | 3 |
| binary/octet-stream | 3 |
| application/vnd.apple.installer+xml | 1 |
| application/x-bzip2 | 1 |
| application/x-rss+xml | 1 |
| plain/text | 1 |

("text/html" also includes error messages caused by input variables in URL.)

## Sparkle feeds

Sparkle feed that has item versions but not enclosure versions:

```xml
<?xml version="1.0"?>
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>Caffeine</title>
<description>Most recent changes with links to updates.</description>
<language>en</language>
<item>
<title>Version 1.4.3</title>
<sparkle:version>21</sparkle:version>
<sparkle:shortVersionString>1.4.3</sparkle:shortVersionString>
<pubDate>Sun, 14 April 2024 8:00:00 +0000</pubDate>
<enclosure url="https://dr-caffeine-mac.s3.amazonaws.com/Caffeine_1.4.3.zip" length="5961295" type="application/octet-stream" sparkle:edSignature="985QTq5gW2CIAWdBTJqg1n8+5KTVGln5fIumSyCY+YI1CGSUx2InGSBdUWWih0j9XowDeXIIbyDyHqzdeDYNDw=="/>
<sparkle:minimumSystemVersion>11.0</sparkle:minimumSystemVersion>
<description><![CDATA[ <ul> <li>Added Sparkle updater</li> </ul> ]]></description>
</item>
</channel>
</rss>
```

Sparkle feed that has enclosure versions but not item versions:

```xml
<?xml version="1.0"?>
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>coconutBattery changelog</title>
<link>https://www.coconut-flavour.com/updates/coconutBattery.xml</link>
<description>coconutBattery changelog</description>
<language>en</language>
<item>
<title>Version 4.0.1</title>
<description><![CDATA[ <body style="font: 12px '-apple-system', system-ui, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, sans-serif; line-height: 1.3; margin: 0; padding: 0; background: #fff; color: #000;"> <div style="background-color: #4c84b3; color: white; width: 80%; margin: 0 auto; padding: 10px; padding-left:20px; padding-right:20px; margin-top: 15px; text-align: center; border-radius: 8px;"> <b>All coconutBattery 3 Plus licenses were upgraded to coconutBattery 4 Plus Lifetime licenses.</b><br> <span style="display: block; margin-top: 10px;"> <b><a style="color: white; text-decoration: underline;" href="https://www.coconut-flavour.com/coconutBattery/#plus">- coconutBattery 4 Plus -</a></b> </span> </div> <div class="release" style="padding-left: 30px;padding-top:10px;"> <h2 style="font-size: 18px; font-weight: 600; margin-bottom: 10px;"><b>coconutBattery 4.0.1</b> <span style="opacity: 0.5;font-size:12px">| Dec 20, 2024</span></h2> <ul style="padding-left: 16px; margin: 0; list-style: disc;"> <li style="margin-bottom: 5px;">Fixed a bug that could cause displaying "NaN" in the history viewer for history that was imported from version 3</li> <li style="margin-bottom: 5px;">Info text if battery is not supported by lifetime viewer</li> <li style="margin-bottom: 5px;">If multiple adapters are connected, the one with the highest wattage is displayed</li> <li style="margin-bottom: 5px;">Print template selection now recognize Plus license correctly</li> <li style="margin-bottom: 5px;">Fixed display issues on iMac M3</li> <li style="margin-bottom: 5px;">The History Viewer "Save now" option shows matching icons for the device that will be saved </li> <li style="margin-bottom: 5px;">Fixed a bug where some coconutBattery 3 Plus licenses were not recognized correctly in coconutBattery 4</li> <li style="margin-bottom: 5px;">Added an option in the app settings to manually enable the coconutBattery menu bar</li> <li style="margin-bottom: 5px;">History Viewer now automatically selects first device when opened</li> <li style="margin-bottom: 5px;">History elements can be deleted using the context menu in the History Viewer</li> <li style="margin-bottom: 5px;">Toolbar state is now saved</li> <li style="margin-bottom: 5px;">Fixed battery manufacturer reading on some Macs</li> <li style="margin-bottom: 5px;">Battery health >100% is now displayed as 100% in non raw data mode</li> <li style="margin-bottom: 5px;">Fixed a bug that could cause the app displaying incorrectlry the charging state on Intel Macs </li> </ul> </div> <div class="release" style="padding-left: 30px;padding-top:10px;"> <h2 style="font-size: 18px; font-weight: 600; margin-bottom: 10px;"><b>coconutBattery 4.0.0</b> <span style="opacity: 0.5;font-size:12px">| Nov 30, 2024</span></h2> <ul style="padding-left: 16px; margin: 0; list-style: disc;"> <li style="margin-bottom: 5px;">Refined UI for improved usability</li> <li style="margin-bottom: 5px;">New App Icon</li> <li style="margin-bottom: 5px;">Realtime battery usage metrics for Macs</li> <li style="margin-bottom: 5px;">Improved device details viewer</li> <li style="margin-bottom: 5px;">Battery lifetime viewer now available for Macs</li> <li style="margin-bottom: 5px;">Re-engineered menu bar interface</li> <li style="margin-bottom: 5px;">Implemented low battery notifications for iPhones and iPads</li> </ul> </div> </body> ]]></description>
<enclosure url="https://www.coconut-flavour.com/downloads/coconutBattery_401_130.zip" sparkle:version="4.0.1" sparkle:dsaSignature="MC0CFDiiAP1h+TJLfE+bDSe39osBfD5hAhUAlk2Iefd0mx6zTFPrqChwYai1dbE=" length="5457536" type="application/octet-stream"/>
<sparkle:minimumSystemVersion>12.4</sparkle:minimumSystemVersion>
</item>
<item>
<title>Version 3.9.18</title>
<enclosure url="https://www.coconut-flavour.com/downloads/coconutBattery_3918_8BC5B481.zip" sparkle:version="3.9.18" sparkle:dsaSignature="MC4CFQCsOPpjH69d6Z2fVKWhDhlu2CgyywIVAKx5LGVSX9r6t6vUAY70wHS1DceW" length="14058872" type="application/octet-stream"/>
<sparkle:minimumSystemVersion>10.11.0</sparkle:minimumSystemVersion>
</item>
</channel>
</rss>
```
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Recipe Robot is the easiest way to create new [AutoPkg](https://github.com/autop

[Download the latest release](https://github.com/homebysix/recipe-robot/releases/latest), or see detailed [requirements and installation steps](https://github.com/homebysix/recipe-robot/wiki/Installation-and-Requirements) on the wiki.

> [!TIP]
> As of 2025, over 20% of the publicly available recipes in the [AutoPkg organization](https://github.com/autopkg) were created with the help of Recipe Robot!

For helpful information on using Recipe Robot, including tutorials and troubleshooting information, see the [wiki](https://github.com/homebysix/recipe-robot/wiki).

If you encounter a reproducible problem with Recipe Robot, I encourage you to open an [issue](https://github.com/homebysix/recipe-robot/issues) on GitHub.
Expand Down
7 changes: 1 addition & 6 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,7 @@

11. Create new release on GitHub with title format `Recipe Robot X.X.X`. Set label format to `vX.X.X`. Add notes from change log. Attach built disk image.

12. Trigger a GitHub Pages build, which updates the Sparkle feed ([using @huangyq23's method detailed here](https://www.yiqiu.me/2015/11/19/sparkle-update-on-github/)):

git checkout gh-pages
git commit --allow-empty -m "Trigger gh-pages build"
git push
git checkout main
12. Manually update `appcast.xml` on the `gh-pages` branch.

13. Announce to [autopkg](https://macadmins.slack.com/archives/C056155B4) and other relevant channels, if desired.

Expand Down
2 changes: 1 addition & 1 deletion app/Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1 +1 @@
binary "https://sparkle-project.org/Carthage/Sparkle.json" "2.5.1"
binary "https://sparkle-project.org/Carthage/Sparkle.json" "2.6.4"
8 changes: 4 additions & 4 deletions app/Recipe Robot.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@
CODE_SIGN_ENTITLEMENTS = "Recipe Robot/Recipe Robot.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1038;
CURRENT_PROJECT_VERSION = 1381;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 32SVX952DB;
ENABLE_HARDENED_RUNTIME = YES;
Expand All @@ -543,7 +543,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
MARKETING_VERSION = 2.3.1;
MARKETING_VERSION = 2.3.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.elliotjordan.recipe-robot";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
Expand All @@ -558,7 +558,7 @@
CODE_SIGN_ENTITLEMENTS = "Recipe Robot/Recipe Robot.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1038;
CURRENT_PROJECT_VERSION = 1381;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 32SVX952DB;
ENABLE_HARDENED_RUNTIME = YES;
Expand All @@ -571,7 +571,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)";
MARKETING_VERSION = 2.3.1;
MARKETING_VERSION = 2.3.2;
PRODUCT_BUNDLE_IDENTIFIER = "com.elliotjordan.recipe-robot";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
Expand Down
4 changes: 2 additions & 2 deletions app/Recipe Robot/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="22154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22154"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="23504"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand Down
2 changes: 1 addition & 1 deletion app/Recipe Robot/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>RRBT</string>
<key>CFBundleVersion</key>
<string>1375</string>
<string>1396</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
Expand Down
4 changes: 2 additions & 2 deletions scripts/recipe-robot
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ if sys.version_info.major < 3:
print("ERROR: This version of Recipe Robot requires AutoPkg 2 and Python 3.")
sys.exit(1)

# TODO (Shea): Clean up importing from our library.
# TODO: Clean up importing from our library.
import recipe_robot_lib
from recipe_robot_lib import tools
from recipe_robot_lib.exceptions import RoboError, RoboException
Expand Down Expand Up @@ -88,7 +88,7 @@ def main():
first_timer = prefs.get("RecipeCreateCount", 0) == 0

# Collect facts from the input path, based on the type of path.
# TODO (Shea): Standardize on always returning Facts, even though they
# TODO: Standardize on always returning Facts, even though they
# are passed by reference, to remove ambiguity about what is happening.
process_input_path(facts)

Expand Down
2 changes: 1 addition & 1 deletion scripts/recipe_robot_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@

from __future__ import absolute_import

# TODO (Shea): We can import stuff better here to cut down on length of calls.
# TODO: We can import stuff better here to cut down on length of calls.
from . import tools # noqa: F401
from .recipe_generator import generate_recipes # noqa: F401
2 changes: 1 addition & 1 deletion scripts/recipe_robot_lib/curler.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def parse_curl_error(proc_stderr):
try:
curl_err = proc_stderr.rstrip("\n")
curl_err = curl_err.split(None, 2)[2]
except IndexError:
except (AttributeError, IndexError):
pass

return curl_err
Expand Down
44 changes: 27 additions & 17 deletions scripts/recipe_robot_lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ def inspect_bitbucket_url(input_path, args, facts):
"Getting information from latest BitBucket release...", LogLevel.VERBOSE
)
if "values" in parsed_release:
# TODO (Elliot): Use find_supported_release() instead of these
# TODO: Use find_supported_release() instead of these
# nested loops. May need to flatten the 'asset' dict first.
for this_format in ALL_SUPPORTED_FORMATS:
for asset in parsed_release["values"]:
Expand Down Expand Up @@ -990,7 +990,7 @@ def inspect_disk_image(input_path, args, facts):
for this_file in os.listdir(dmg_mount):
if this_file.lower().endswith(".app"):
# Copy app to cache folder.
# TODO(Elliot): What if .app isn't on root of dmg mount? (#26)
# TODO: What if .app isn't on root of dmg mount? (#26)
attached_app_path = os.path.join(dmg_mount, this_file)
cached_app_path = os.path.join(CACHE_DIR, "unpacked", this_file)
robo_print("Copying %s into cache..." % this_file, LogLevel.VERBOSE, 4)
Expand Down Expand Up @@ -1135,7 +1135,7 @@ def inspect_download_url(input_path, args, facts):
headers = {}

# Download the file for continued inspection.
# TODO(Elliot): Maybe something like this is better for downloading
# TODO: Maybe something like this is better for downloading
# big files? https://gist.github.com/gourneau/1430932 (#24)
robo_print("Downloading file for further inspection...", LogLevel.VERBOSE)

Expand Down Expand Up @@ -1718,7 +1718,7 @@ def inspect_pkg(input_path, args, facts):
facts["warnings"].append(
"Yo dawg, I found a flat package inside this flat package!"
)
# TODO (Elliot): Recursion! Any chance for a loop here?
# TODO: Recursion! Any chance for a loop here?
facts = inspect_pkg(os.path.join(dirpath, filename), args, facts)
elif filename == "PackageInfo":
robo_print(
Expand Down Expand Up @@ -1876,6 +1876,7 @@ def inspect_sourceforge_url(input_path, args, facts):
# Example: http://grandperspectiv.sourceforge.net/screenshots.html
marker = ".sourceforge.net"
proj_str = (
# Requires Python 3.9+
input_path.removeprefix("https://www.")
.removeprefix("http://www.")
.removeprefix("https://")
Expand Down Expand Up @@ -1956,7 +1957,7 @@ def inspect_sourceforge_url(input_path, args, facts):
LogLevel.VERBOSE,
)
for item in doc.iterfind("channel/item"):
# TODO(Elliot): The extra-info tag is not a reliable
# TODO: The extra-info tag is not a reliable
# indicator of which item should actually be downloaded.
# (#21) Example:
# https://sourceforge.net/projects/grandperspectiv/rss
Expand Down Expand Up @@ -2158,18 +2159,27 @@ def inspect_sparkle_feed_url(input_path, args, facts):
sparkle_ns = "{http://www.andymatuschak.org/xml-namespaces/sparkle}"
sparkle_provides_version = False
sparkle_info = []
for item in doc.iterfind("channel/item/enclosure"):
encl_vers = item.get(sparkle_ns + "version")
encl_shortvers = item.get(sparkle_ns + "shortVersionString")
if encl_vers or encl_shortvers:
sparkle_provides_version = True
sparkle_info.append(
{
"url": item.attrib.get("url", ""),
"version": encl_vers,
"shortVersionString": encl_shortvers,
}
)
for item in doc.iterfind("channel/item"):
try:
item_vers = item.find(sparkle_ns + "version").text
except AttributeError:
item_vers = None
try:
item_shortvers = item.find(sparkle_ns + "shortVersionString").text
except AttributeError:
item_shortvers = None
for encl in item.iterfind("enclosure"):
encl_vers = encl.get(sparkle_ns + "version")
encl_shortvers = encl.get(sparkle_ns + "shortVersionString")
if any([item_vers, item_shortvers, encl_vers, encl_shortvers]):
sparkle_provides_version = True
sparkle_info.append(
{
"url": encl.attrib.get("url", ""),
"version": encl_vers or item_vers,
"shortVersionString": encl_shortvers or item_shortvers,
}
)

# Remove items with unusable URLs.
sparkle_nones = (None, "", "null", "n/a", "none")
Expand Down
Loading