Jump to content

Best way to Develop, Build and Update a Github-based Workflow?

Recommended Posts

Hi, if I want to develop a workflow that by default is stored in my Alfred preferences (which I keep on Dropbox), but I want to share it on Github, what would people recommend as the best setup? I could clone the github repo within the alfred workflow folder, but normally I prefer to keep all my projects in ~/Code/  — so I could maintain the github version in ~/Code/workflow-name, but develop in Alfred-prefs workflow folder, then sync the files to ~/Code/workflow everytime I'm ready to release. This seems a bit tedious. Could I symlink ~/Code/workflow-name to the Alfred-prefs-workflow folder (does the UUID name for the folder always stay the same)? Any thoughts on the best practice here?


Also is there some way to "automate" building the .alfredworkflow file or is this always done manually from Alfred? Some kind of Applescript command where you would pass a bundle-ID and path to auto-build would be great.


Finally, is there a downside to keeping the .alfredworkflow file in the Github directory? It seems the easiest way to do this, with the workflow source in /src/ and the workflow in / on Github?

Edited by iandol
Link to comment

Looks like what you’re looking for is similar to my setup. See my Workflows repository for an idea of how I keep it organised. Every Workflow directory consists of:

└─ README.md
└─ WorkflowName.alfredworkflow (the file used to install a Workflow)
└─ source (a directory containing the unpacked source)

Locally, I keep the installed Workflow (unpacked in Alfred’s preferences) from the repo where I develop them. What I then do is work on the installed Workflow. When I’m ready to release a new one, I open its directory in a terminal and run a simple script whose only argument is a commit message. The script takes care of copying everything in the installed Workflow and packaging it for distribution, updating it on the local repo and pushing it to Github.

In theory, a .alfredworkflow file is simply a renamed .zip file. In practice, there’re some slight changes when packaging, namely not keeping Workflow Environment Variables that have “Don’t Export” checked. I do it (also in the script) by leveraging PlistBuddy to delete values from keys with variablesdontexport in the Workflow’s info.plist.


See also a similar post:


Link to comment
3 hours ago, iandol said:

Could I symlink ~/Code/workflow-name to the Alfred-prefs-workflow folder (does the UUID name for the folder always stay the same)?


Yes. This is the best way, imo. Alfred doesn't care about the name of the directory your workflow is in (AFAIK, the UUID is just a simple way to create a random name). Alfred identifies workflows by their bundle IDs.


Dropbox also does the right thing when syncing. If the target of the symlink exists on the other machine, it re-creates the symlink. If it doesn't, it copies over the actual directory.


The only gotcha with symlinks is that Alfred is a lot slower to pick up changes to info.plist if they weren't made via Alfred's own GUI.


I have a couple of script to help with developing workflows. This one installs your workflow by copying/symlinking it to Alfred's workflow directory, and this one builds an .alfredworkflow file from a directory containing the source. The latter is primarily aimed at Python workflows, so it may not be optimal for workflows written in other languages.


Link to comment

Thank you both for the excellent detailed answers. It seems that keeping the workflow files in a /source folder in a git project, the compile workflow in root and symlinking just the source/ folder to dropbox is the best route.


@deanishe: I don't use python (I have a minimal miniconda setup with V3.6.2), but did try to use your workflow-install.py and got an error:


File "/Users/ian/bin/workflow-install.py", line 140, in read_plist
    return plistlib.readPlistFromString(xml)
AttributeError: module 'plistlib' has no attribute 'readPlistFromString'

No major issue, will manually symlink...

Link to comment
1 hour ago, iandol said:

have a minimal miniconda setup with V3.6.2


That's likely the cause of the problem. The script is built for the default Python 2.7 that's a part of macOS (/usr/bin/python). It works on any normal macOS install. It's almost certainly not compatible with Python 3.


If you have other Pythons, changing the shebang to /usr/bin/python should make the script run properly. 


If the "python" command resolves to a Python 3 on your system, you should really fix that. "python", if present, should always be Python 2. Python 3 versions should be named (or symlinked to) "python3".


The two are not very compatible, so having "python" resolve to Python 3 will break most Python 2 code.


Link to comment

Everything else I use Python for works "better" with 3, so I'll just change the shebang for your scripts. I keep meaning to switch from Ruby to Python for my own helper tools, but never get round to it and so my Python requirements are driven only by scientific tools that recommend 3 over 2. Conda does make it easy to switch between different Python version, which is a more elegant solution (I use rbenv exactly for this in Ruby).


Thanks again!!!

Link to comment

Anaconda (a popular scientific computing distribution of Python) installs Python this way, and for my use for scientific computing all works fine. All it really does is use user path order, so it was easy to revert back to system python in .zshrc.


Back to the development workflow, one slight wrinkle in the Github + Dropbox symlink model — this is optimal for single machine use, but if you use two or more machines, then there is probably some circular mess you could get yourself into. My solution is that only machineA symlinks from the github repo to Dropboxed-AlfredPrefs, my others do not. In this case I need to remember if I edit something in Alfred on machineB, it will not be visible in the local github folder of machineB, only machineA. I can manually copy to machineB local github folder, but I'd rather just have a rule to only push from machineA. 

Link to comment
9 hours ago, iandol said:

all works fine


Everything installed by Anaconda works fine. As you've seen, Scripts that expect a properly-configured system, and aren't installed via Anaconda, don't work.


9 hours ago, iandol said:

probably some circular mess you could get yourself into


See my earlier post. It works fine. You'll only have problems if you're on different branches on the different machines.


If you're only going to symlink the workflows on one machine, there's little point even having the code on the other machine: you can't really work on the workflow because if it isn't linked, it isn't installed in Alfred.


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...