A repository for handling the updates and versioning of my apple shortcuts, and also draft versions.
NEXT SHORTCUT ID:
26
versioning/
for the shortcut, e.g. myshortcut
updates.json
and history.json
in the versioning/myshortcut
(see Configuring Versioning System For Shortcut).updates.json
, and prepend it to the list in history.json
.updates.json
version
should match the new shortcut version\\n
)updates.json
If the shortcut does not pass this test, fix the bugs and update the icloud link in the versioning, then re-run the test
The version system works with two files under versioning/myshortcut
. updates.json
contains the latest version of the shortcut, while history.json
contains the previous versions of the shortcut.
updates.json
The format for updates.json
varies based on the shortcut type: Independent and Framework. Independent shortcuts are shortcuts that only run and manage themselves. This means that they do not have any helper or inner shortcuts that they use and that need to be tracked.
Framework shortcuts have inner shortcuts and helper shortcuts. For framework shortcuts, there will always be an updater shortcut which will contain the updating system for the shortcuts in the framework. The updater shortcut handles versioning for all shortcuts in the framework.
Independent shortcuts use the format:
{
// Remember to remove the comment and update the fields when copy pasting!
// These never change
"id": "<id>",
"name": "My Shortcut",
"type": "independent",
"rhub": "https://routinehub.co/shortcut/15515",
"updateLink": "https://iffy-pi.github.io/apple-shortcuts/versioning/myshortcut/updates.json",
// These will change for every update
"version": 3.24,
"link": "<icloud link>",
"releaseNotes": "...",
"releaseTime": "2023-06-09"
}
id
: The versioning ID of the shortcut, which is pulled from the ID counter above.version
: The version number for the shortcut and is at most a double e.g. 1.11
.name
: The actual shortcut name.type
: The shortcut type, which is set to independent.link
: The icloud link for the shortcut.rhub
: The RoutineHub link (without the ending forward slash).updateLink
: The link to updates for the shortcut.releaseNotes
: The notes for the current release, these can be multiple lines separated by an escaped newline character \\n
.releaseTime
: The date for the release, using ISO 8601 formatting (YYYY-MM-DD
).Update Links are always of the format:
https://iffy-pi.github.io/apple-shortcuts/versioning/<SHORTCUT FOLDER NAME>/updates.json
Framework shortcuts have a similar format but introduces new fields:
{
// Remember to remove the comment and update the fields when copy pasting!
"id": "<id>",
"name": "<framework name>",
"type": "framework",
"rhub": "https://routinehub.co/shortcut/15515",
"updateLink": "https://iffy-pi.github.io/apple-shortcuts/versioning/myshortcut/updates.json",
"version": 3.24,
"link": "<updater shortcut icloud link>",
"releaseNotes": "...",
"releaseTime": "2023-06-09",
"children": [
{
"id": "<id>",
"name": "name",
"type": "child",
"version": 1.24,
"link": "<icloud link>",
},
// ...
// can have multiple children for shortcut frameworks
// compare ids of children if major version has changed
]
}
The key differences are:
framework
instead of independent.link
is now the updater shortcut's icloud link.children
, which contains the other shortcuts in the framework.children
is a list of dictionaries, where each dictionary contains the information for a shortcut in the framework:
id
: The shortcuts ID from the ID counter.version
: The shortcuts current version.name
: The shortcut name.link
: The shortcut link.type
: Set to child
to indicate the shortcut is a part of a framework.The idea in this case is that the updater shortcut will use the information contained in children
to determine what shortcuts need updating. For children, the id
is essential, as it allows for efficient storing of data in dictionaries and such.
history.json
This is used to maintain version history, and is simply just a JSON list of previous updates.json
dictionaries. This helps track changes overtime.
[
// Most recent updates first
{
// updates.json object
// ...
},
// ...
]
Shortcuts will store their current version and a link to their updates page in a simple dictionary. At the end of execution, the shortcut queries the updates page and compares its version to the posted version. If it is less than the posted version, then the update process can begin.
Independent shortcuts only need to do this with themselves. Framework shortcuts will have the updater shortcut query the versions for each child shortcut to determine which shortcuts needs to change.
The pseudocode for the process can be experessed in shortcut-ish python.
# done at the beginning or end of the shortcut, which ever is preferred
updateInfo = {
'updateLink' : '<updateLink from updates.json>',
'version' : 1.02
}
updateRes = GetContentsOfURL(updateInfo['updateLink'])
if Number(UpdateRes['version']) > updateInfo['version']:
date = Date(updateRes['releaseTime'])
splitText = SplitText(updateRes['releaseNotes'], '\\n')
text = f"""
{updateRes['name']} Shortcut Update
An update is available for this shortcut:
{updateInfo['version']} β‘οΈ {updateRes['version']}
π¦ Released:
{date.format(date="long", time=None)}
β
Install:
{updateRes['link']}
π Release Notes:
{splitText}
π¬ Developer:
Reddit: iffythegreat (https://www.reddit.com/user/iffythegreat)
RoutineHub: iffy-pi (https://routinehub.co/user/iffy-pi)
π Full Update History:
{updateRes['rhub']}/changelog
"""
note = CreateNote(text)
OpenNote(note)
# Put in updater
'''
Suppose we have two shortcuts in the framework
ShortcutA at v1.8, id=41
ShortcutB at v2.6, id=42
'''
updateInfo = {
'updateLink' : '<updateLink from updates.json>',
'version' : 1.02
}
# also now includes information about the children
childVers = {
# just map ids to their versions
'41': 1.8,
'42': 2.6,
}
updateRes = GetContentsOfURL(updateInfo['updateLink'])
if Number(UpdateRes['version']) > updateInfo['version']:
# collate information about the changed children
newChildren = UpdateRes['children']
updateText = []
updateLinks = []
# updater shorcut needs to be updated
updateText.append(f"Updater Shortcut: {updateInfo['version']} β‘οΈ {updateRes['version']}")
updateLinks.append(f"Updater Shortcut: {updateRes['link']}\n")
for child in newChildren:
curVer = childVers[ child['id'] ]
if Number(child['version']) > curVer:
updateText.append(f"{child['name']}: {curVer} β‘οΈ {child['version']}")
updateLinks.append(f"{child['name']}: {child['link']}\n")
date = Date(updateRes['releaseTime'])
splitText = SplitText(updateRes['releaseNotes'], '\\n')
text = f"""
{updateRes['name']} Shortcut Update
Updates are available for shortcuts:
{updateText}
π¦ Released:
{date.format(date="long", time=None)}
β
Install:
{updateLinks}
π Release Notes:
{splitText}
π¬ Developer:
Reddit: iffythegreat
π Full Update History:
{updateRes['rhub']}/changelog
"""
note = CreateNote(text)
OpenNote(note)