iffy-pi / apple-shortcuts

A repository for handling the updates and versioning of my apple shortcuts
https://iffy-pi.github.io/apple-shortcuts/
2 stars 0 forks source link

apple-shortcuts

A repository for handling the updates and versioning of my apple shortcuts, and also draft versions.

NEXT SHORTCUT ID:

26

Creating a Versioned Shortcut

  1. Create a folder in versioning/ for the shortcut, e.g. myshortcut
  2. Implement versioning system within the shortcut (see Configuring Update System In Shortcut). If new, set initial version to be 1.0.
  3. Copy the shortcut's icloud link.
  4. Create a post on routinehub.co for the shortcut. Publish using version 0.0
  5. Create the updates.json and history.json in the versioning/myshortcut (see Configuring Versioning System For Shortcut).
  6. Push JSON files to remote.
  7. Publish new version of shortcut on routinehub with the version 1.0

Udpating a Version Shortcut

  1. Make changes in shortcut
  2. Update version number in shortcut
  3. Write out the changelog for this new update somewhere (will need it later)
  4. Copy shortcut's icloud link
  5. Copy the current version of the shortcut's updates.json, and prepend it to the list in history.json.
  6. Update the shortcut's updates.json
    • version should match the new shortcut version
    • Update shortcut link
    • Update release notes (use changelog and replace newlines with \\n)
    • Update release time
  7. Verify update is pushed correctly (see below)
  8. Create new version with the new version number on RoutineHub, using the version, icloud link and release notes from updates.json

Verifying an update has been pushed correctly

  1. Within the shortcut, downgrade the version
  2. Run the shortcut to test that it sees there is an update
  3. Download the shortcut packaged with the update and verify its
    • Set up process, has set up configured
    • Version number
    • Update configuration

If the shortcut does not pass this test, fix the bugs and update the icloud link in the versioning, then re-run the test

Configuring Versioning System For Shortcut

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"
}

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:

children is a list of dictionaries, where each dictionary contains the information for a shortcut in the 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
        // ...
    },
    // ...
]

Configuring Update System In Shortcut

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.

Independent Shortcut:

# 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)

Framework Updater Shortcut:

# 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)

Actual Shortcut Examples

Other Information

Action Pipeline