In general it's another way of defining interfaces around processes. Those processes may be manually done or automated. But the interface can remain the same - this is quite powerful when it comes to automating steps.
It's the same as you'd do with another system really.
I've used this before with Google sheets being manually filled in -> automated with a script. And with Jira tickets being raised and then automatically picked up and processed. It lets you get started sooner, automated the most annoying parts and you never have to fully do it.
Side benefit of do nothing scripts is that they can remain up to date more often as they can be more likely to be actually used than reading the docs.
Yes and for me this an another chance to use and share Jupyter notebooks.
Describe the thing. Offer boilerplate, examples, or parameterized executables.
The doc system that uses Notebooks de facto would be awesome. It’s too heavy to add as a layer to a Cloud SaaS like Confluence and offers too many opportunities for escalations as is..
I think the point is that it's a psychological hack to just get started. It's making a point, and the point is that it's even helpful without running the commands. Yeah, sure you can immediately make it run the command as soon as it exists -- the article is not implying that that's wrong
You also get to a point that's functional but not optimal very quickly. Improvements can then be added incrementally by different people as and when it's worthwhile.
And often it doesn’t need to be optimal. If the functional process takes 5 minutes and you do it once a month then you can’t spend more than 5 hours optimizing it before you’re going backwards.
I feel the place where that intuition might have an exception is where you want a culture change, or you want to communicate a culture of "anyone can do this and is encouraged to". Sometimes it makes sense to automate something that doesn't save time, like putting it in a chatbot command that invites others to run it :)
Then automate those points as and when it's worth doing. Nobody is saying you can't do that, in fact it's a very key selling point of a do nothing script - you can very easily upgrade it to a do something script.
The alternatives are "do everything scripts" which get lost in dealing with how to automatically manage 1password, or documentation which is just a do nothing script that doesn't lead you through the checklist.
>Fuck cutting and pasting stuff from one terminal into another terminal.
This is the point of this approach. To offer incentives to turn into scripts maintenance procedures that come around often but for which there isn't enough budget.
I think jupyter notebooks are better suited to fill this role since you can gradually turn a 100% markdown wiki document into a script and offer one-click execution.
My not-so-humble opinion is that this type of incremental encoding of process as scripts results in a system built around process rather than a system that eats process. I'm all for a catalog of scripts automating common tasks. The moment those scripts start getting called by production services you're creating a huge mountain of tech debt for whoever is unfortunate enough to unpick the web of spaghetti.
Further, because your human oriented process has now codified your system, changes to the system that's would be beneficial to a software system (i.e. dividing the system into components) are impossible. So incremental scale is achieved by stuffing more into the process, which then gets grafted onto the script monolith in a self protruding cycle.
> The moment those scripts start getting called by production services
Any of them with manual steps just can't, right?
> Further, because your human oriented process has now codified your system, changes to the system that's would be beneficial to a software system (i.e. dividing the system into components) are impossible.
Absolutely nothing stops you from changing these scripts - it's no different from having scripts in a package.json
The alternatives are full automation, which pushes your issues to the max, or zero automation which is an odd point to be in.
No, the point of the article is that later these can be modified to actually run these commands - obviously to call these scripts. You can assume pretty confidently that when it seems to be a self contained good script, it is going to be called from services. Even if it is a bad investment to implement it, because programmers hate boring tasks. They would even choose to make a web of spaghettis for later generations than do boring stuff.
I absolutely agree you modify and automate parts (and eventually all) of it. It's the leap to having scripts in a repo being called from production services I'm less convinced by. As I said, the alternatives to part/incremental automation is none or total automation and total has the same issue right?
Or do you mean by automating one step in a script, you risk someone using that part in a production service?
> Any of them with manual steps just can't, right?
If you are literally using the kind of scripts used here, they can't be called by a production system though their use can be part of formalized desk procedures.
It is a fairly natural next step (and a not unheard of first step in automation, bypassing these) to instead build something like these scripts but into an actual workflow management system where it can be triggered by either a user or even automatically tied to another system event, can be assigned to an available worker, can have status and artifacts tracked, and can trigger downstream processes.
(Of course, once you have the process in such a system, where the human worker is essentially a component the system calls to complete defined steps—contrary to GPs criticism—what you have is equqivalent to a documented process with the notable different that it is much easier to refactor it to divide work among components, etc., just loke any other software system.)
- use the process repeatedly and by as many people as possible
- adapt the process to any misuse seen in the wild
4) automate the process
Everybody will buy into steps 1&2, and most people will come around to 4, but doing step 3 usually will get you more people pushing for and understanding 4
The limitation of your approach I will say is that if you can automate the beginning of a process or the end it’s fine, but if you have two islands in the middle it doesn’t work better than a CLI tool with prompts.
One of the fun things with SEI Capability Maturity Model is that you reach level 1 just by having your process written down at all, no matter how stupid it sounds.
But the giggle test is just something I borrowed from business, which is, “can I say this with a straight face?” Which eliminates a lot more censorious than you would think. Writing something down is one thing, making eye contact with someone while repeating it is a bit harder.
censorious appears to mean 'severely critical of others'. I expect they meant 'censoriously', with the full intent being that the embarrassment felt by the critical reactions of others when reading the instructions out loud will cause you to eliminate or fix obviously broken, complex or tedious processes that you had, until then, just quietly been putting up with.
> The limitation of your approach I will say is that if you can automate the beginning of a process or the end it’s fine, but if you have two islands in the middle it doesn’t work better than a CLI tool with prompts
I think I may have poorly described my approach then. It's just the same thing, the choice of sheets or Jira or cli or a combo is only about meeting people where their current process is. A dev setup -> cli. A business process between trams -> Jira if that's the current flow. I'm not getting marketing to install my cli tool, and they'd not be the ones doing the manual steps anyway.
The point is just making a process into a series of clearly defined steps that can be manual and can be automated independently.
Your description of what happens alongside 3 and 4 is good, this was really valuable when I've done it. Just like releasing a MVP and finding out key problems with your imagined approach, the issues are usually not what you expect. You also have better test cases and examples.
Massive side benefit when I did this with data was that it also meant a process could be automated 95% of the time, manual 5% without changing the interface anyone worked with. All they saw was the ticket took longer really. That's great when you find absolutely wild stuff in some csv file.
Iteration doesn’t require infinite money and this sort of work more than pays for itself.
The last time I used it, which is probably eight times now, I freed a team up to attack more entrenched tech debt problems by making them no longer afraid of deploying to run trails instead of waiting to do feature toggles once a release cycle.
Every adult programmer should be able to think of four things they can work on when nobody is telling them what to do for the next little while, and Scrum produces a lot of those. This is just one of the things I do. And when you get close to a quantum of useful improvement you can usually get a story or two on the board.
Fixing your processes is an axe sharpening exercise. If you’d rather be dismissive enough to register a complaint then I feel sorry for the teams you work on.
I see the mountain of “Zen and the Art of Motorcycle Maintenance” coming into view.
The approach replaces Confluence instruction pages with semi-interactive walkthroughs (the conscious side).
The other side is test automation: it starts with a big ball of overfitted Xpaths and undocumented steps. Those get re-discovered every time the application changes (the subconscious side).
Hopefully, we reach the summit where we can execute quickly and still know how we got there and why.
It would also be nice if it would show you all the steps beforehand, and then check each item as you progress. Sometimes it's good to actually prepare from a broader perspective.
And it could log into a file as a summary.
So much that could be improved, which is why the simplest solution might be the best.
I think the simplest solution would be to just do what the article says and not do all that extra stuff. And I think that that’s what they meant at the end of that comment too.
Gotcha. I totally agree with the sentiment, or rather I should say: all these thoughts come to mind when thinking about setting up partial automation for a process, and I regularly remind myself to keep to simple, and get something working.
The hardest to resist is when you have a similar framework in place for another process, but getting a new process to use that framework is still going to take 4x longer (or whatever) than starting from scratch and getting the initial consistency that the do-nothing approach gives.
You could do this with a nicer cli library, so you could show the checklist and running output of each stage, which would be nice regardless of what steps are automated.
My main issue with that is that a do nothing shell script is so easy to get started with that it's hard not to complete it, and your efforts may be better used automating one of the steps. You may get lost in a fun but not that productive quagmire of which TUI library and how to structure everything.
I'm glad this is mentioned! This is why instead of a Bash script, I use a Makefile. Each step is a rule with a *.done name, that generates a .done file once it's done. I can interrupt it any time, modify the script to fix something, and `make` to resume.
But writing that Makefile is a PITA. Is there a better solution?
I’ve just switched to using just https://github.com/casey/just for my makefiles that were really just a collection of small snippets and it’s worked wonderfully
When I do this I keep some persistent state so I can interrupt it, e.g. if the thing is a yearly task I run it like `./do-the-thing.sh 2025`, and make a 2025 dir where I keep state on how far I've gotten
So if you OK the first step, I can touch a 2025/first-step file. If the script crashes or is interrupted and rerun, it can check for that file and skip the first step
If something has changed so the automation doesn't work, it's nice to be able to crash out without losing state, fix the script and rerun.
I usually have the script tell me just the next manual step and then exit, because that frees the terminal up for me to do other things. I can use the command history to rerun the script easily
Yea, I've used similar scripts where if you accidentally put in the wrong email address - oops, now what. You gotta restart the whole script? The script lockin can become a pain point.
It’s an interactive slide show, but it also has forced the user into the CLI context, where they are likely to already bring a different type of attention and focus than if they were reading the exact same set of instructions in a markdown file somewhere in the org’s repos. Not necessarily better or worse, just different due to simulating the experience of a CLI tool as a mechanism for prompting the user to take certain actions.
I just threw this together this week for a friend to keep track of medication compliance and I want to test prose-base flagging of journal entries if a user may need medication adjustments or impending mania/depression.
I wanted a HIPAA compliant PWA that was HTML + js + CSS, but I am not a web developer and wasted a lot of time relying on Google and AI that "service workers are totally the way, dude".
Service workers require http[s] "domain" or something so I ditched that idea and implemented a 30 line discord bot in node. It writes JSON for alarms and journal entries.
It isn't what I wanted, but my friend gets a beep to take their medicine and they reply "took it" in the morning and journal at night. I had then make a private channel on their own Discord server and they just journal them there. I figured it would be really easy to export for my experiment.
P. S. Timezones suck I am not dealing with it, so this isn't a product. I actively dislike development, probably because I keep messing with new languages to more efficiently (read faster and less effort on my part) solve specific problems.
Crucially, the presentation constrains the user's progress to a linear sequence of actions, which makes it straightforward to eventually make some steps actually do work automatically or semi-automatically. If you started with a markdown checklist or a powerpoint slide deck for presenting the same information, the form-factor would not provide linearity and would not invite further automation.
> Invoke is a Python library for managing shell-oriented subprocesses and organizing executable Python code into CLI-invokable tasks. It draws inspiration from various sources (make/rake, Fabric 1.x, etc) to arrive at a powerful & clean feature set.
> It lowers the activation energy for automating tasks
Does that mean the "do-nothing script" should eventually have some automated steps that do-something?
As a placeholder for future possible automation, this feels like the right balance between automation and efficiency. It allows you to make the first stab without investing too much and it leaves some low-hanging fruit for another time when the effort might be more obviously worthwhile. Thanks for sharing!
> Each step of the procedure is now encapsulated in a function, which makes it possible to replace the text in any given step with code that performs the action automatically.
Yeah, I started to incorporate this into my own work.
Like, sometimes you can automate 99% of a procedure, except like putting a secret into an so-far not automated secret management solution, or running a terraform apply that requires access to something that's not accessible from the automation just yet.
Instead of giving up there, I now just go ahead and insert e.g. an `ansible.builtin.pause` with clear instructions to the user what to do, and when to continue the play. This might not be gloriously fully automated (yet), but it is so much better than having to do the other 12 things manually.
Similar, we have "standard plays", which are just shell scripts to invoke ansible in some specific way. But those have started to accrue some user guidance and some do-nothing instruction steps as well. The database creation script asks you if you've added the database in the three other places upon startup, since it'd fail otherwise. Or a disk resize standard play asks you if you need to resize the disk on a failover cluster as well now?
I would like to have these things fully automated, but having these simple scripts as guidance for admins is surprisingly valuable.
Yeah, I think if you are the choir, this is just going to be preaching. But, if you're an inexperienced developer and lean towards adding layers of abstraction, this might be useful. In fact, I just recommended this to a team of 2 developers to watch and they found it quite valuable. They are experienced developers, but one of them leans strictly to procedural code, and the other leans toward object oriented, and they were struggling. This worked as a conversation point to talk about where it was appropriate to lean OO.
Don't bother watching the video, it's an extended form blog that can be summarized in a few sentences and I regret wasting 15 minutes watching it at 2x speed. The relevant part for what GP seems to be pointing at:
> Don't use a class that wraps one method (or one method and init).
It's irrelevant to this particular blog article because while the classes start that way, they are expected to grow (if they don't, they probably don't need to be steps in your procedures and you can delete them). The author gives each class the same run method as an interface so the steps can be moved around into other procedures more easily (config with class instantiation, execute with a call to run).
The speaker's point is generally valid, but like all advice should be considered in context and not taken as a thing to do (or not do) all the time.
Is it irrelevant to the code in question? In my career I've run into so much code that is over engineered for a potential future use case, that has just caused so much pain and suffering in the meantime, often that future use case never happens. And to quote another buddy of mine, Raymond, "stop committing atrocities". :-)
It is irrelevant in this particular case because the script is supposed to eventually get more integrated, to become a do-something script - and then you do not want to change the main function (which by then becomes an ordered list) too much, and work within the individual classes.
So why not just use functions directly? Well, sometimes things are too complicated to be put in a Clean-Code-compliant function, and standardisation means less maintenance / and less rewriting if it turns out what you considered function-simple ... isn't.
A lot has changed since 2019. That "do nothing" script can be fed to an LLM and it's going to be a pretty good starting point for automating it. For example, feeding the script to ChatGPT o3-mini-high produced this for one of the steps:
class CreateSSHKeypairStep(object):
def run(self, context):
keyfile = os.path.expanduser("~/{0}_ssh_key".format(context["username"]))
pubkey = keyfile + ".pub"
if os.path.exists(keyfile):
print("Key file {} already exists. Skipping generation.".format(keyfile))
else:
print("Generating SSH key pair (no passphrase) in {} and {}.".format(keyfile, pubkey))
cmd = ["ssh-keygen", "-t", "rsa", "-f", keyfile, "-N", ""]
subprocess.check_call(cmd)
# Save the key filenames in the context for later use.
context["keyfile"] = keyfile
context["pubkey"] = pubkey
wait_for_enter()
Part of the point of do-nothing scripting is letting humans use their judgement in edge cases. For example, if the file already exists, you might not want to reuse a private key, potentially creating a security vulnerability, as chatgpt has done here.
Also it hallucinated (as usual) some extra args to ssh-keygen.
Ok, fair enough, I was thrown by your use of the word hallucination, which to me is used to describe picking things that don't exist, like if it had done "ssh-keygen -t rsa --add-public-keyfile-to-gitrepo-and-commit". In this case I had asked it to automate the do-nothing script, so I'd call this more of a "design decision" than a hallucination.
It seems to me like you are assuming ChatGPT is always going to be wrong (which in itself is not an unreasonable place to start), which is coloring your use of the tool.
I mean, I did say that assuming it was wrong was not an unreasonable place to start, which I think makes my position quite clear. But, I'll clarify: I review all the code that ChatGPT produces before I use it. Sometimes this results in me asking it to revise the code, sometimes it results in me abandoning that code, sometimes it results in me learning something because it has produced better code than I had in my mind thinking about the problem, or it used code or libraries that were a "blind spot" for me. I've been programming in Python since the late 90s, and programming since the early '80s, but I'm not a programmer by day, so I definitely have blind spots. Even if I was a programmer, I'd admit I'd have blind spots.
But: The LLMs can produce rather good code. They can cover a lot of typing and low to mid level design work from a short description. I'm bringing value to my company and my life by using this tool, plain and simple.
This GPT did the thing it was supposed to do: produce an implementation using a previous script's structures and processes. I'd bet explaining the reasoning, discussing potential vulnerabilities, or changing the business processes, wasn't in the prompt. Or that metadata wasn't included in GP for brevity.
But it has succeeded in sparking discussion, similar to rubber-duck debugging. A good org will look at this as a starting point, discuss the details, and iterate.
> Also it hallucinated (as usual) some extra args to ssh-keygen.
I don't see a hallucination here.
I can confirm it works, and is correct on my system with OpenSSH on it.
I assume you mean the slightly strange `["-N", ""]` argument pair?
This tells ssh-keygen to create the file with no passphrase and no prompting for a passphrase.
There’s no reason you can’t do both. As another sibling comment mentions, llms will get you part of the way there, but often have things you still need to work out. This helps you get a framework in place first, so that you can take an iterative approach to the parts that actually require effort from a human to deal with.
Just to be clear, I wasn't advocating against the do-nothing script, I've done that many times myself in the past. In fact, ChatGPT suggested a hybrid approach in the full result, as it didn't have enough information to look up the e-mail address so that step remained largely unchanged.
No idea why this is getting downvoted. This seems like the perfect thing to use LLMs for. Isolated code that is mostly boilerplate, outside your primary domain, and doesn't require much maintenance. In the worst case, you just let the user choose between manual and automated at each step, and if automated, prompt the user to check the results before moving on.
The biggest hold up in automation for me usually are things that need to be done via a gui.
I tried automatizing those with some tools intended for gui testing, but those solutions tend to be brittle and I just don’t feel well if I cannot get a real success report.
I’d be fretful for somthing that solves that problem.
I love this! it encourages you to mentally define the steps. To me, the next step is to define the "inputs" and "outputs" that each step should have. Next after that in many cases would be "what to do or just what to suggest to the user if each of the steps fail." And at that point you have not only a nicely already function-based outline if you want to make it a real automation.
It's a thought technology which I suspect will result in better final scripts than what I have tended to do, which is much more linear and requires a significant refactoring step at the end to avoid having one long function of poor quality.
I like this way of thinking. I’m working on a bunch of automations right now and using GitHub actions.
I find the idea of setting up “do nothing workflows” that I can compose and implement more thoroughly over time helpful. I’ll probably put this into use.
Is this very feasible with Github Actions? Or would you be combining with other approaches? i.e. my impression is there isn't any real "wait for user input to continue" that is part of github actions.
My interpretation is really just having placeholder workflows that still require manual steps and maybe even print them out as text, but don’t necessarily wait.
However the task used as an example just shows how provisionning SSH keys was insecure at that company. In fact the user should generate his private key by himself and just provide the public key to the sysadmin to inject it in the system to grant access. AT NO POINT THE SYSDAMIN SHOULD HAVE A COPY OF THE PRIVATE KEY, even temporary. So the 1Password step shouldn't even be necessary.
By the way, I'm the author of github-keygen, a tool to automate the creation of SSH keys dedicated to GitHub access, and to setup SSH settings for that context.
> In fact the user should generate his private key by himself and just provide the public key to the sysadmin to inject it in the system to grant access.
I always found this such an annoying step to implement. We've switched to certificate based authentication on SSH - no more moving around public keys. Really simplified the whole process!
Certificates have a private key and a public key, and you keep the private key secret and move the public key around, so ... how is that different, technically and organizationally?
There is only one public key that installed on the servers. That key is the same everywhere. You have a self-serve system that generates short-lived certs to users.
What public key is installed where on the servers? What self-serve system where generating certs how and in what form do users get them and what do they do with them?
And how is the user authenticating to the self-serve system - username/password? And why can't they just do that to the SSH server?
The company certificate is put on the server. Manually, the sysadmin generates the user key signed by certificate and sends it to them. Or the self-serve system generates it and they download it.
The user uses the SSH key as normal. The server checks that if key is signed.
The self-serve system uses the single-sign-on system for the company. The SSH server can't do SSO, maybe can do LDAP, but it is giant annoyance to set it up. A lot SSH use assumes that using key and doesn't support username/password.
Is this really the bar? Doesn't IT own every part of the work machine with the private key anyhow? I realize passwords are different but private keys sit at rest in the machine.
Ideally this documentation would also document the expected output, both toward identifying when the process has gone off the rails when doing it manually and making the steps testable once automated.
Otherwise, it'd be trivially easy for an unfamiliar user (or the automated script) to ignore unclear errors or exit codes and march blindly to the next wait_for_enter().
I bet you could adapt this for orchestrators besides a script. For instance if the goal is to eventually have it all running in Airflow, you could have a do-nothing DAG, which would be nice because your co-workers could see that you're already half-way through today's task, whereas separate python scripts don't know about each other. You could just use a `sleep infinity` to keep the task "running" until somebody manually sets it to "success".
This approach always sounds great upon initial consideration but has a fatal flaw. It doesn't scale because people are lazy. Over time, slogs will always revert to their original form.
I'd disagree slightly, insofar as the author would probably be fine with a makefile for the problem at hand. The thing you're solving is runbooks/documentation being high-toil and slightly harder to automate than they should be. If you encode that in programmatic steps (including a makefile), you reduce the toil and also the activation energy for properly automating it later. Makefile vs python vs zig build vs whatever isn't relevant to their poiy.
This is actually brilliant. This is a step above every list of instructions that I've ever made without committing to full-blown all-at-once automation.
164 comments
[ 4.7 ms ] story [ 36.7 ms ] threadIn general it's another way of defining interfaces around processes. Those processes may be manually done or automated. But the interface can remain the same - this is quite powerful when it comes to automating steps.
It's the same as you'd do with another system really.
I've used this before with Google sheets being manually filled in -> automated with a script. And with Jira tickets being raised and then automatically picked up and processed. It lets you get started sooner, automated the most annoying parts and you never have to fully do it.
Side benefit of do nothing scripts is that they can remain up to date more often as they can be more likely to be actually used than reading the docs.
Describe the thing. Offer boilerplate, examples, or parameterized executables.
The doc system that uses Notebooks de facto would be awesome. It’s too heavy to add as a layer to a Cloud SaaS like Confluence and offers too many opportunities for escalations as is..
It can confirm with the user: "Execute command (y/N)?"
Fuck cutting and pasting stuff from one terminal into another terminal. That's also focus-intensive.
Then prompt the user to do the manual stuff when it isn't yet a command:
"Look up the e-mail address for foo. Paste it here:"
"Put that shit in 1Password: Are you done (y/N)?"
https://xkcd.com/1205/
The alternatives are "do everything scripts" which get lost in dealing with how to automatically manage 1password, or documentation which is just a do nothing script that doesn't lead you through the checklist.
I think jupyter notebooks are better suited to fill this role since you can gradually turn a 100% markdown wiki document into a script and offer one-click execution.
Further, because your human oriented process has now codified your system, changes to the system that's would be beneficial to a software system (i.e. dividing the system into components) are impossible. So incremental scale is achieved by stuffing more into the process, which then gets grafted onto the script monolith in a self protruding cycle.
> The moment those scripts start getting called by production services
Any of them with manual steps just can't, right?
> Further, because your human oriented process has now codified your system, changes to the system that's would be beneficial to a software system (i.e. dividing the system into components) are impossible.
Absolutely nothing stops you from changing these scripts - it's no different from having scripts in a package.json
The alternatives are full automation, which pushes your issues to the max, or zero automation which is an odd point to be in.
Or do you mean by automating one step in a script, you risk someone using that part in a production service?
If you are literally using the kind of scripts used here, they can't be called by a production system though their use can be part of formalized desk procedures.
It is a fairly natural next step (and a not unheard of first step in automation, bypassing these) to instead build something like these scripts but into an actual workflow management system where it can be triggered by either a user or even automatically tied to another system event, can be assigned to an available worker, can have status and artifacts tracked, and can trigger downstream processes.
(Of course, once you have the process in such a system, where the human worker is essentially a component the system calls to complete defined steps—contrary to GPs criticism—what you have is equqivalent to a documented process with the notable different that it is much easier to refactor it to divide work among components, etc., just loke any other software system.)
You're basically arguing against the concept of SOPs. OP blog post is basically just a programmer's version of an SOP.
SOPs are great, until they aren't. So then you change them. This is nothing new or strange.
They are more portable, more universal, fewer dependencies.
Whenever you start to install something just put the commands into a bash’s script as you go and run it at each step.
Want to break it apart? Break apart the script how you like and repeat.
Being able to hand someone a scene for Linux or MacOS is a great way to help others begin too.
1) Capture the process as is
2) make the process pass a giggle test
3) make the process automatable
Concurrent with 3 and 4:
- use the process repeatedly and by as many people as possible
- adapt the process to any misuse seen in the wild
4) automate the process
Everybody will buy into steps 1&2, and most people will come around to 4, but doing step 3 usually will get you more people pushing for and understanding 4
The limitation of your approach I will say is that if you can automate the beginning of a process or the end it’s fine, but if you have two islands in the middle it doesn’t work better than a CLI tool with prompts.
But the giggle test is just something I borrowed from business, which is, “can I say this with a straight face?” Which eliminates a lot more censorious than you would think. Writing something down is one thing, making eye contact with someone while repeating it is a bit harder.
I think I may have poorly described my approach then. It's just the same thing, the choice of sheets or Jira or cli or a combo is only about meeting people where their current process is. A dev setup -> cli. A business process between trams -> Jira if that's the current flow. I'm not getting marketing to install my cli tool, and they'd not be the ones doing the manual steps anyway.
The point is just making a process into a series of clearly defined steps that can be manual and can be automated independently.
Your description of what happens alongside 3 and 4 is good, this was really valuable when I've done it. Just like releasing a MVP and finding out key problems with your imagined approach, the issues are usually not what you expect. You also have better test cases and examples.
Massive side benefit when I did this with data was that it also meant a process could be automated 95% of the time, manual 5% without changing the interface anyone worked with. All they saw was the ticket took longer really. That's great when you find absolutely wild stuff in some csv file.
The last time I used it, which is probably eight times now, I freed a team up to attack more entrenched tech debt problems by making them no longer afraid of deploying to run trails instead of waiting to do feature toggles once a release cycle.
Every adult programmer should be able to think of four things they can work on when nobody is telling them what to do for the next little while, and Scrum produces a lot of those. This is just one of the things I do. And when you get close to a quantum of useful improvement you can usually get a story or two on the board.
Fixing your processes is an axe sharpening exercise. If you’d rather be dismissive enough to register a complaint then I feel sorry for the teams you work on.
The approach replaces Confluence instruction pages with semi-interactive walkthroughs (the conscious side).
The other side is test automation: it starts with a big ball of overfitted Xpaths and undocumented steps. Those get re-discovered every time the application changes (the subconscious side).
Hopefully, we reach the summit where we can execute quickly and still know how we got there and why.
[0] https://github.com/MattSayar/post_to_socials
It would also be nice if it would show you all the steps beforehand, and then check each item as you progress. Sometimes it's good to actually prepare from a broader perspective.
And it could log into a file as a summary.
So much that could be improved, which is why the simplest solution might be the best.
And you leave us hanging: which solution is the "simplest solution"?
(Then again, I'd do this in Obsidian.)
The hardest to resist is when you have a similar framework in place for another process, but getting a new process to use that framework is still going to take 4x longer (or whatever) than starting from scratch and getting the initial consistency that the do-nothing approach gives.
My main issue with that is that a do nothing shell script is so easy to get started with that it's hard not to complete it, and your efforts may be better used automating one of the steps. You may get lost in a fun but not that productive quagmire of which TUI library and how to structure everything.
I'm glad this is mentioned! This is why instead of a Bash script, I use a Makefile. Each step is a rule with a *.done name, that generates a .done file once it's done. I can interrupt it any time, modify the script to fix something, and `make` to resume.
But writing that Makefile is a PITA. Is there a better solution?
So if you OK the first step, I can touch a 2025/first-step file. If the script crashes or is interrupted and rerun, it can check for that file and skip the first step
If something has changed so the automation doesn't work, it's nice to be able to crash out without losing state, fix the script and rerun.
I usually have the script tell me just the next manual step and then exit, because that frees the terminal up for me to do other things. I can use the command history to rerun the script easily
I just never think to create cli applications
I wanted a HIPAA compliant PWA that was HTML + js + CSS, but I am not a web developer and wasted a lot of time relying on Google and AI that "service workers are totally the way, dude".
Service workers require http[s] "domain" or something so I ditched that idea and implemented a 30 line discord bot in node. It writes JSON for alarms and journal entries.
It isn't what I wanted, but my friend gets a beep to take their medicine and they reply "took it" in the morning and journal at night. I had then make a private channel on their own Discord server and they just journal them there. I figured it would be really easy to export for my experiment.
P. S. Timezones suck I am not dealing with it, so this isn't a product. I actively dislike development, probably because I keep messing with new languages to more efficiently (read faster and less effort on my part) solve specific problems.
Thank you for linking to it.
Does that mean the "do-nothing script" should eventually have some automated steps that do-something?
As a placeholder for future possible automation, this feels like the right balance between automation and efficiency. It allows you to make the first stab without investing too much and it leaves some low-hanging fruit for another time when the effort might be more obviously worthwhile. Thanks for sharing!
> Each step of the procedure is now encapsulated in a function, which makes it possible to replace the text in any given step with code that performs the action automatically.
Like, sometimes you can automate 99% of a procedure, except like putting a secret into an so-far not automated secret management solution, or running a terraform apply that requires access to something that's not accessible from the automation just yet.
Instead of giving up there, I now just go ahead and insert e.g. an `ansible.builtin.pause` with clear instructions to the user what to do, and when to continue the play. This might not be gloriously fully automated (yet), but it is so much better than having to do the other 12 things manually.
Similar, we have "standard plays", which are just shell scripts to invoke ansible in some specific way. But those have started to accrue some user guidance and some do-nothing instruction steps as well. The database creation script asks you if you've added the database in the three other places upon startup, since it'd fail otherwise. Or a disk resize standard play asks you if you need to resize the disk on a failover cluster as well now?
I would like to have these things fully automated, but having these simple scripts as guidance for admins is surprisingly valuable.
> Don't use a class that wraps one method (or one method and init).
It's irrelevant to this particular blog article because while the classes start that way, they are expected to grow (if they don't, they probably don't need to be steps in your procedures and you can delete them). The author gives each class the same run method as an interface so the steps can be moved around into other procedures more easily (config with class instantiation, execute with a call to run).
The speaker's point is generally valid, but like all advice should be considered in context and not taken as a thing to do (or not do) all the time.
So why not just use functions directly? Well, sometimes things are too complicated to be put in a Clean-Code-compliant function, and standardisation means less maintenance / and less rewriting if it turns out what you considered function-simple ... isn't.
Also it hallucinated (as usual) some extra args to ssh-keygen.
But: The LLMs can produce rather good code. They can cover a lot of typing and low to mid level design work from a short description. I'm bringing value to my company and my life by using this tool, plain and simple.
This GPT did the thing it was supposed to do: produce an implementation using a previous script's structures and processes. I'd bet explaining the reasoning, discussing potential vulnerabilities, or changing the business processes, wasn't in the prompt. Or that metadata wasn't included in GP for brevity.
But it has succeeded in sparking discussion, similar to rubber-duck debugging. A good org will look at this as a starting point, discuss the details, and iterate.
> Also it hallucinated (as usual) some extra args to ssh-keygen.
I don't see a hallucination here. I can confirm it works, and is correct on my system with OpenSSH on it.
I assume you mean the slightly strange `["-N", ""]` argument pair? This tells ssh-keygen to create the file with no passphrase and no prompting for a passphrase.
I tried automatizing those with some tools intended for gui testing, but those solutions tend to be brittle and I just don’t feel well if I cannot get a real success report.
I’d be fretful for somthing that solves that problem.
It's a thought technology which I suspect will result in better final scripts than what I have tended to do, which is much more linear and requires a significant refactoring step at the end to avoid having one long function of poor quality.
I find the idea of setting up “do nothing workflows” that I can compose and implement more thoroughly over time helpful. I’ll probably put this into use.
However the task used as an example just shows how provisionning SSH keys was insecure at that company. In fact the user should generate his private key by himself and just provide the public key to the sysadmin to inject it in the system to grant access. AT NO POINT THE SYSDAMIN SHOULD HAVE A COPY OF THE PRIVATE KEY, even temporary. So the 1Password step shouldn't even be necessary.
By the way, I'm the author of github-keygen, a tool to automate the creation of SSH keys dedicated to GitHub access, and to setup SSH settings for that context.
https://github.com/dolmen/github-keygen
I always found this such an annoying step to implement. We've switched to certificate based authentication on SSH - no more moving around public keys. Really simplified the whole process!
What do you actually do, and how is it better?
What public key is installed where on the servers? What self-serve system where generating certs how and in what form do users get them and what do they do with them?
And how is the user authenticating to the self-serve system - username/password? And why can't they just do that to the SSH server?
https://smallstep.com/blog/use-ssh-certificates/
The user uses the SSH key as normal. The server checks that if key is signed.
The self-serve system uses the single-sign-on system for the company. The SSH server can't do SSO, maybe can do LDAP, but it is giant annoyance to set it up. A lot SSH use assumes that using key and doesn't support username/password.
https://news.ycombinator.com/item?id=29083367 - 3 years ago (230 comments)
https://news.ycombinator.com/item?id=20495739 - 6 years ago (124 comments)
MM, interesting idea.
Otherwise, it'd be trivially easy for an unfamiliar user (or the automated script) to ignore unclear errors or exit codes and march blindly to the next wait_for_enter().
Fix the process, fix the script. Onwards....
"09:53 - User parasti indicated that he has indeed checked the server room being locked."