Jump to content

Alchemists Pennyworth


Recommended Posts

Hello everyone. 👋

 

I wanted to post about my Pennyworth Ruby gem which might be of interest to folks here:

 

https://www.alchemists.io/projects/pennyworth

 

With the gem installed, I use Ruby to power many of the workflows but this project also has a collection of many non-Ruby powered workflows too. The entire project is devoted to supporting Alfred. Please read the project documentation for more info. Let me know if there are any questions. Thanks and enjoy! 🎉

Link to comment

Hey @deanishe. 👋 The short answer is there is no easy way to teach Alfred how to use the correct version of Ruby installed on the system, sadly. So it's critical that one's shell is properly loaded before Alfred runs the Script Filter to pick up the correct version of Ruby AND load the correct version of Pennyworth as well.

 

To illustrate further, here's the main problem with Script Filters:

 

CleanShot-QL4qE4vC.png.13530b2c08c62c883064e930522d6265.png

 

The only way to trick Alfred, so-to-speak, into using the correct version of Ruby is to force Alfred to load your current shell when running the Script Filter. That means, for these two lines of code in a Script Filter:
 

source "$HOME/.bashrc"

pennyworth --http_statuses

 

...the above then ensures, the correct Homebrew installed and managed version of Bash and Ruby is used.

 

Link to comment
2 hours ago, Brooke Kuhlmann said:

The short answer is there is no easy way to teach Alfred how to use the correct version of Ruby installed on the system

 

Why doesn't specifying the full path to the correct Ruby executable work?

 

2 hours ago, Brooke Kuhlmann said:

the above then ensures, the correct Homebrew installed and managed version of Bash and Ruby is used

 

“Ensures” is too strong, imo.

 

.bashrc is not supposed to be loaded in non-interactive shells, and it's fairly common practice to put something like [ -z "$PS1" ] && return right at the top of .bashrc to make sure it isn't (bash will still try to load .bashrc if it detects it's being run by ssh).

 

For other people who load a bunch of stuff in their shell, it will ruin workflow performance.

 

It seems to me, it would be better to spell out the actual requirements. Just sourcing .bashrc or .zshrc is liable to not work at all or to cause problems due to the user's customisations.

Link to comment

> Why doesn't specifying the full path to the correct Ruby executable work?

 

So you might have multiple versions of Ruby installed at once which will be several versions ahead of the system version (i.e. provided by default in macOS). The macOS Ruby version is generally not preferred or used since every Ruby engineer uses a Ruby Version Manager to deal with this. With a Ruby Version Manager (https://www.alchemists.io/articles/ruby_version_managers), you can easily switch between different versions at will. For example, with a Ruby Version Manager, you might have the following installed:

- 2.6.3

- 2.7.2

- 3.0.0

- 3.0.2

 

...and out of those versions, 3.0.2 might be the global version you have the Pennyworth gem installed in which you want Alfred to pick up dynamically in the Script Filter. For example, that full path might look like this:
 

$HOME/.cache/frum/versions/3.0.2/lib/ruby/gems/3.0.0/gems/pennyworth-11.1.0/bin

 

...but let's say a new version of Ruby comes out, like 3.0.3. You'd have to update the path from 3.0.2 to 3.0.3. Same goes if Pennyworth is upgraded in which case you'd have to upgrade from 11.1.0 to 11.1.1, for example. It's much easier to install Ruby 3.0.3 and Pennyworth 11.1.1 -- or any combination of -- without having to adjust the Alfred Script Filter in addition. Alfred, will just pick everything up dynamically via the shell instead which a nice win.

 

> .bashrc is not supposed to be loaded in non-interactive shells, and it's fairly common practice to put something like [ -z "$PS1" ] && return right at the top of .bashrc to make sure it isn't (bash will still try to load .bashrc if it detects it's being run by ssh).

 

> For other people who load a bunch of stuff in their shell, it will ruin workflow performance.

 

Yeah, you have a valid and strong point. I've been using Alfred + Pennyworth this way for years so haven't had any issues logged against this usage yet but I agree, I can do better in this regard. My main goal was to ensure people could use Alfred + Pennyworth with very little scripting necessary within the Script Filter or further maintenance on their part. So ensuring -- or letting anyone dictate -- how their environment should be loaded is key (whether it be Bash, ZSH, Fish, etc). I also don't want to have to figure out which Ruby Version Manger someone is using. I'm using Frum but others could be using RVM, rbenv, chruby, or asdf for example.

 

I will research if there is a better way to do this without using .bashrc. One thing that might help is Alfred could let me select from any of my shells. For example, if `cat /etc/shells`, I get:

 

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/opt/homebrew/bin/bash

 

It'd be really nice to select `/opt/homebrew/bin/bash` within the Alfred Script Filter but Alfred never detects that last line.

 

Anyway, definitely open to any suggestions to make this a smooth experience (beside the .bashrc suggestion you had). 😅

 

 

Edited by Brooke Kuhlmann
Link to comment

 

28 minutes ago, Brooke Kuhlmann said:

So you might have multiple versions of Ruby installed at once which will be several versions ahead of the system version (i.e. provided by default in macOS).

 

Developers might. Normal users don't, nor do they want them.

 

Does this not work with the system Ruby?

 

37 minutes ago, Brooke Kuhlmann said:

but Alfred never detects that last line

 

That's absolutely deliberate. System defaults available on every machine only.

 

41 minutes ago, Brooke Kuhlmann said:

Anyway, definitely open to any suggestions to make this a smooth experience (beside the .bashrc suggestion you had).

 

Use standard system interpreters and tools, and bundle any libraries with your workflow, so it works out of the box. It's never going to be a smooth experience if users need to install developer tools to use your workflow.

Link to comment
Quote

Developers might. Normal users don't, nor do they want them.

 

Ah, OK, I understand where you are coming from now. I'm targeting fellow engineers only. 😅

 

Quote

Does this not work with the system Ruby?

 

Nope, Pennyworth is built using Ruby 3.0.0 syntax and the macOS System Ruby is on Version 2.6.3. Totally not possible to use Pennyworth with the system or Alfred defaults.

 

Quote

That's absolutely deliberate. System defaults available on every machine only.

 

🙇🏻 Yeah, that makes a lot more sense based on your earlier feedback.

 

Quote

Use standard system interpreters and tools, and bundle any libraries with your workflow, so it works out of the box. It's never going to be a smooth experience if users need to install developer tools to use your workflow.

 

Yep, I definitely understand where you are coming from now. Thanks. I'm afraid I can't comply, though, sadly. 😢 The reason is two-fold:

  • Alfred uses the system Ruby (i.e. Version 2.6.3) which is too old.
  • Several years back I started out writing Ruby within the Alfred Script Filter but there's no way to reliable test Ruby code which leads to maintenance nightmares. It's much easier to encapsulates the functionality within a Ruby gem, package, ship, and then write a simple Alfred Script Filter which messages the gem.
Edited by Brooke Kuhlmann
Link to comment
5 hours ago, Brooke Kuhlmann said:

I'm targeting fellow engineers only. 😅

 

Making a library that's only suitable for building workflows that can only be used by developers seems kinda limiting.

 

Or did I misunderstand? Does it generate a workflow with the entire Ruby runtime bundled?

Link to comment
7 hours ago, deanishe said:

Making a library that's only suitable for building workflows that can only be used by developers seems kinda limiting.

 

Correct, I am limiting my audience and reach. There's no doubt about that but I'm also an engineer and want to programmatically leverage Ruby to power Alfred in ways not possible with using out-of-the-box native Alfred Script Filter support.

 

Quote

Or did I misunderstand? Does it generate a workflow with the entire Ruby runtime bundled?

 

Pennyworth does not generate a workflow, bundle the Ruby runtime, or subsequent gem (library). The assumption is that you are a Ruby engineer who will install the Pennyworth gem and then install the supporting Alfred Workflow.

 

I take it, from this conversation, that engineer focused Alfred Workflows and sharing of them here in the Alfred forums is a bit...rare or unusual?

Link to comment
1 hour ago, Brooke Kuhlmann said:

I take it, from this conversation, that engineer focused Alfred Workflows and sharing of them here in the Alfred forums is a bit...rare or unusual?

 

Define "rare". I mean, workflows for Ruby developers isn't exactly a large category, and most people writing any other kind of workflow in Ruby have the sense to stick with the system runtime. Requiring a non-standard runtime is a pretty user-hostile thing to do, and we've all seen what a support nightmare it becomes.

 

The Node crowd – as JS devs are wont to do – have gone in at the deep end in that regard, and 90% of every thread about a Node-based workflow is questions about Homebrew/Node/npm, not the workflow.

 

There's no getting around that if you're going to use Node, but all indications are that the majority of devs writing workflows in Ruby or Python value working out-of-the-box and not having to deal with endless requests for help with dependencies more highly than getting to play with the latest language features.

Link to comment
Quote

Define "rare". I mean, workflows for Ruby developers isn't exactly a large category, and most people writing any other kind of workflow in Ruby have the sense to stick with the system runtime. Requiring a non-standard runtime is a pretty user-hostile thing to do, and we've all seen what a support nightmare it becomes.


Hmm, yeah, that's a real shame. 😢 I also wasn't aware of the support issues. I've never seen issues on GitHub related to the Pennyworth project so assumed fellow Ruby engineers were humming along without issue.

 

Quote

The Node crowd – as JS devs are wont to do – have gone in at the deep end in that regard, and 90% of every thread about a Node-based workflow is questions about Homebrew/Node/npm, not the workflow.

 

 

Hmm, yeah, I can't speak to the JavaScript crowd. I just know that I've been writing and supporting Alfred Workflows -- using Ruby -- like this for 9 years now while always using the latest and greatest version of Ruby. Never had an issue or an issue with my team (if that's any small condolence).

 

 

Link to comment
4 hours ago, Brooke Kuhlmann said:

Never had an issue or an issue with my team


You won't have any issues as long as you're building workflows that are only interesting to other people who have the technical skills needed to install the workflow's dependencies.

 

It can just turn into a support nightmare with workflows that also appeal to non-technical users.

 

It's just a bit of a shame to my mind that you've written such a powerful library, but made it impossible to build workflows that work out-of-the-box with it.

Edited by deanishe
Link to comment
3 hours ago, Brooke Kuhlmann said:

Never had an issue or an issue with my team (if that's any small condolence).


That already proves it was worth. I agree with @deanishe that developers who want to share with a wide audience likely won’t pick this up, but maybe there’s someone else who’ll also use it for Workflows within their team.

Link to comment
23 hours ago, Brooke Kuhlmann said:

Several years back I started out writing Ruby within the Alfred Script Filter but there's no way to reliable test Ruby code which leads to maintenance nightmares.

 

Just to pick up on this point, my workflow libraries have solid test coverage, and so do my workflows where appropriate. I build workflows as command-line programs that happen to emit Alfred JSON and I just call them from Alfred with appropriate flags and arguments (i.e. there’s usually only ./prog $@ or at most ./prog --option "$variable" $@ in Alfred’s Script boxes). That makes it pretty easy to test them just by setting some environment variables and/or command-line options.

Edited by deanishe
Link to comment

@deanishe

 

Quote

It's just a bit of a shame to my mind that you've written such a powerful library, but made it impossible to build workflows that work out-of-the-box with it.

 

Ha, yeah. On the flip side, I also learned something new because I didn't realize their wasn't more of a space for supporting custom Ruby versions like I've been doing. I always assumed it was the norm. So my shock of finding this out -- 9 years later -- is quite surprising. 😅

 

ℹ️ By the way, it would take a significant amount of effort to rewrite Pennyworth to support Ruby 2.6.0 or any version of Ruby older than 3.0.0. This was the entire impetus for creating this post/announcement in the first place because the gem had been entirely written to support the new Ruby 3.0.0 syntax. 🎉

 

@vitor

 

Yeah, definitely for the Ruby engineer who loves working with the latest version of Ruby and wants to leverage those features.

Link to comment
Quote

I build workflows as command-line programs that happen to emit Alfred JSON and I just call them from Alfred with appropriate flags and arguments

 

@deanishe Thanks, yeah, I was looking over your project. That's basically how I test Pennyworth. It emits JSON as well and I just test the output which is quite easy and reliable. I don't actually do a full integration test where the Alfred workflow is triggered. I suppose I could do that as well and worth thinking about more. There is one advantage that I don't have is that you can compile and embed your application within the workflow which is neat. I don't have that capability with Ruby due to being a dynamic language.

Link to comment
8 minutes ago, Brooke Kuhlmann said:

I always assumed it was the norm.

 

Only among people who write Ruby code.

 

Anyone else may have Ruby 3 installed somewhere as a dependency of some Homebrew recipe, but they're unlikely to actively install it. I mean, why would anyone go out of their way to install a newer version of something they don't use (or possibly even know they have)?

Link to comment
On 7/27/2021 at 1:18 AM, Brooke Kuhlmann said:

I don't actually do a full integration test where the Alfred workflow is triggered.

 

I ripped all of that out, tbh, and added test-specific code paths instead, so I can just verify the output without actually calling Alfred. Apart from it being a general PITA to get anything back out of Alfred, I want to be able to use CI on my projects, and you can't use Alfred in your CI pipeline because workflows are a Powerpack-only feature and Alfred will shit bricks if you're activating your licence on lots of ephemeral CI instances.

  

On 7/27/2021 at 1:18 AM, Brooke Kuhlmann said:

There is one advantage that I don't have is that you can compile and embed your application within the workflow which is neat.

 

I'm sorry, I don't really understand what you mean. I write Python workflows exactly the same way, with an executable script instead of an executable binary.

Edited by deanishe
Link to comment
13 hours ago, deanishe said:

why would anyone go out of their way to install a newer version of something they don't use (or possibly even know they have)?

 

Correct. This goes back to my earlier point in that I've been writing Alfred Workflows for the Ruby community because my tooling tends to augment a fellow developers' workflow.

 

12 hours ago, deanishe said:

I write Python workflows exactly the same way, with an executable script instead of an executable binary.

 

Ah, OK. I didn't read closely enough, thanks. Also, that makes sense that Alfred Powerpack licensing would be an issue for CI builds.

Link to comment
  • 11 months later...

Hey Andrei. 👋 You shouldn't need to worry about rbenv, only that your environment is loaded properly. This is all documented, here, in the Workflow section of Pennyworth. Feel free to open an issue if you have troubles.

I wasn't aware of Alfredo. Thanks for pointing this out to me. As a cursory glance, it doesn't look like it is maintained all that well but I'll dig into it further.

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...