Publishes a Final Cut Pro audio export as an episode of the Epic Church podcast: names it, encodes it, attaches it to the waiting Feeder entry, publishes, and then confirms the episode is actually live before reporting success.
Runs unattended. There is no on-screen output; a run reports by pinging a BetterStack heartbeat, and reports failure by not pinging it.
- Create the episode entry in Feeder and save it to the feed (not as a draft). Leave the enclosure empty — an entry with no enclosure is how the toolchain identifies the episode awaiting audio.
- Share from Final Cut using the audio-only destination, which is configured to
open
Podcast Toolchain.appwith the exported file.
Everything else is automatic. See RUNBOOK.md for what to do when a run fails.
Nothing is written until every guard has passed.
- Check the input is a readable WAV, the destination volume is mounted, and
that
lame,curl,xmllintandosascripteach actually run - Find the one Feeder item with no enclosure; its publication date becomes the episode date and the filename
- Require the export's creation date to equal that date
- Refuse to continue if any other feed item already claims
<DATE>.mp3 - Archive the source to
<DATE>.wav, encode<DATE>.mp3at 96 kbps mono, and check the result is neither the wrong length nor truncated - Attach the enclosure and publish
- Wait for the upload to finish — Feeder's
publishis asynchronous and reports only that it started - Confirm the episode appears in the feed at the S3 origin, then at
podcast.epicsf.com, with the enclosure byte count matching the local file - Ping the heartbeat
| Path | Purpose |
|---|---|
Podcast Toolchain.app |
The droplet Final Cut opens; hands the file to bin/publish-episode. Generated from src/handoff.applescript, but committed so a clone is usable and Final Cut finds it at the expected path — regenerate with bin/build-droplet, do not edit in Automator |
src/handoff.applescript |
Source for that droplet |
bin/publish-episode |
The pipeline |
bin/build-droplet |
Builds and installs the droplet |
lib/ |
Pipeline libraries, and the AppleScripts that drive Feeder |
test/run-tests.sh |
Test suite |
docs/superpowers/ |
Design spec and implementation plan |
- macOS with Feeder 3 installed and configured to publish the feed
- LAME, at
/usr/local/bin/lameby default - A writable
/Volumes/Data/Podcast podcast-toolchain.confin the project folder, containingHEARTBEAT_URL
Everything else the toolchain uses ships with macOS. Copy
podcast-toolchain.conf.example to create the config; the heartbeat URL is a
credential and is deliberately kept out of this repository.
./test/run-tests.sh # 54 tests
./bin/build-droplet --script-path "$PWD/bin/publish-episode" # test build
./bin/build-droplet --install # build and installOn a machine without Feeder installed, the four Feeder AppleScripts cannot be compiled and are reported as skipped rather than passed.
Installing replaces the app bundle, which resets its macOS permissions. Run it once with a person present to approve the Feeder Automation and external-volume prompts; an unattended run cannot approve them and is silently denied.
The feed is served by CloudFront from an S3 bucket. A dedicated cache behaviour
disables caching for epic-church-messages.xml so the feed is always fresh,
while episode MP3s keep a long cache. No invalidation step is needed.