11 ms·
Do-nothing scripting: the key to gradual automation (2019)
- IanCal 2y agoI'm a big fan of this approach. 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.
- itomato 2y agoYes 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..
- dheera 2y agoI would prefer if the script did the things that already are a command. 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)?"
- patcon 2y agoI 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
- IanCal 2y agoYou 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.
- SoftTalker 2y agoAnd 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. https://xkcd.com/1205/ https://xkcd.com/1205/
- patcon 2y agoI 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 :)
- IanCal 2y agoThen 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.
- Xmd5a 2y ago>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.
- 0xfaded 2y agoMy 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.
- IanCal 2y agoI'm confused as to what you're picturing. > 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.
- szundi 2y agoNo, 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.
- IanCal 2y agoI 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?
- hinkley 2y agoMy previous approach was: 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.
- catlifeonmars 2y agoWhat’s a giggle test?
- hinkley 2y agoOne 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.
- deleted 2y ago[deleted]
- natch 2y agoWhat’s a censorious as a noun? Hadn’t heard it used that way before.
- knome 2y agocensorious 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.
- dejj 2y agoI 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.
- MattSayar 2y agoI was looking for this article recently since it inspired my most recent script to POSSE to various websites [0]. Thanks for posting it again! [0] https://github.com/MattSayar/post_to_socials https://github.com/MattSayar/post_to_socials
- qwertox 2y agoIt's great, but it can't be interrupted. 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.
- gertlex 2y agoAre these actual criticisms of the article? And you leave us hanging: which solution is the "simplest solution"?
- codetrotter 2y agoI 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.
- qwertox 2y agoYes, this was what I meant. Sorry to your parent commenter for not being explicit. (Then again, I'd do this in Obsidian.)
- gertlex 2y agoGotcha. 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.
- IanCal 2y agoYou 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.
- mettamage 2y agoI should just do this for waking up so that I won't be confused on my morning routine. In a sense, it's a rudimentary slide show
- szvsw 2y agoIt’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.
- mettamage 2y agoYep, I realize that I can make a diary program that basically asks me how I am doing I just never think to create cli applications
- genewitch 2y agoI 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.
- 2y ago
- BLanen 2y ago[flagged]
- captnswing 2y agohttps://www.pyinvoke.org/ https://www.pyinvoke.org/
- qwertox 2y ago> 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. Thank you for linking to it.
- notarobot123 2y ago> 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!
- Jtsummers 2y agoYes. > 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.
- tetha 2y agoYeah, 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.
- linsomniac 2y agoThe author needs to watch my buddy Jack's talk: Stop Writing Classes: https://youtu.be/o9pEzgHorH0?si=FgZqFGQNQUU2iREQ https://youtu.be/o9pEzgHorH0?si=FgZqFGQNQUU2iREQ
- PNewling 2y agoCare to give a TL;DW for those of us not able to watch this at the moment?
- nerdponx 2y agoThe title I think gets the point across!
- linsomniac 2y agoYeah, 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.
- Jtsummers 2y agoDon'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.
- linsomniac 2y agoA 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()
- do_not_redeem 2y agoPart 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.
- linsomniac 2y agoWhich arguments did it hallucinate? [I] /tmp> "ssh-keygen" "-t" "rsa" "-f" foo "-N" "" Generating public/private rsa key pair. Your identification has been saved in foo [...]
- do_not_redeem 2y agoOriginal script: ssh-keygen -t rsa -f ~/{0} Chatgpt's version: ["ssh-keygen", "-t", "rsa", "-f", keyfile, "-N", ""] It added `-N ''`, which means don't set a passphrase—a second potential security downgrade.
- 2y ago
- niemandhier 2y agoThe 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.
- xp84 2y agoI 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.
- rpicard 2y agoI 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.
- gertlex 2y agoIs 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.
- rpicard 2y agoMy 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.
- dolmen 2y agoThis is an interesting approach. 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 https://github.com/dolmen/github-keygen
- chuckadams 2y agoMaking unskilled users manage their keys themselves doesn't sound very secure either. That's the point of moving to a script.
- JimBlackwood 2y ago> 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!
- jodrellblank 2y agoCertificates 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? What do you actually do, and how is it better?
- Jtsummers 2y agoPast discussions (lots of comments): https://news.ycombinator.com/item?id=29083367 https://news.ycombinator.com/item?id=29083367 - 3 years ago (230 comments) https://news.ycombinator.com/item?id=20495739 https://news.ycombinator.com/item?id=20495739 - 6 years ago (124 comments)
- mamidon 2y agoTo be clear; you're supposed to have a separate shell open where you do these steps? MM, interesting idea.
- deleted 2y ago[deleted]
- eyehatewindows 2y ago[dead]
- starkparker 2y agoIdeally 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().
- deadbabe 2y agoGreat in theory until some error or problem comes up and you don’t know how to handle it.
- Jailbird 2y agoI'd say that's about the process itself, not the script mirroring the process. Fix the process, fix the script. Onwards....
- __MatrixMan__ 2y agoI 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".
- parentheses 2y agoThis 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.
- avipars 2y agoA good way of documenting processes for people that prefer to look at code than long PDfs
- tejtm 2y agoHaven't had my coffee yet but this strike me as, "reinvent the Makefile". Which I have certainly used as a place to codify steps with benefits.
- hansvm 2y agoI'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.
- DocTomoe 2y agoI would love to see you automating "Take the tapes out of the backup robot and drive them to the safe on the bank" in a Makefile.
- parasti 2y agoThis 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.
- DocTomoe 2y agoAlso, a good way to log processes in cases where such logging is essential. "09:53 - User parasti indicated that he has indeed checked the server room being locked."
- perpil 2y agoI did something like this but it helps you build exact command lines or interact with AWS straight from your GitHub markdown. As a bonus, it very easily lets you prompt the user for inputs and pivot between different accounts. https://speedrun.cc https://speedrun.cc
- hinkley 2y agoI finally tried this an about a year so after it was first posted. Due to bugs in our toolchain we had a run book for hot fixes that was about twice as complicated as the normal release process. I never got the credit it deserved but it went from people only using it for sev 1 issues and “last mile” work in epics that were winding up, say once every ten weeks, to using it on average once a week and a couple times 3 in one week. We were able to dig a lot deeper into tech debt because not every single thing had to be a feature toggle. If you’re at a small company where cloning prod data into preprod is easy, you won’t see this sort of result. But I counted over 150 endpoints we talked to and I believe that averaged 3 per service. So that’s a lot of datasets, and some of them ingested in a Kafka-before-Kafka-existed sort of manner. We had only one guy who would even try to clone prod data, he only had the time (and really energy) to do it once or twice a year, and that was much slower than our customers and features morphed. So it was down to fiddling with the blue-green deployment process and jmeter to figure out if we were close and how to measure success/failure before we went live. And in the end it was the fiddly error-prone build process that stymied people until I half-automated it. Later on as we ramped up its use I hunted down all of the URLs for the manual steps and put them in a lookup table in the tool, and ended up exposing them for the normal validation process we did for release sign off as well. Which made that process a little faster and less stressful for the coordinator (that process was annoying enough that we round robined it through three separate teams to share the load)
- throwpoaster 2y agoEven though “toil” is a term of art, be careful using it around executives who are not SMEs. I once saw an SRE get managed out because he kept talking about “reducing toil” and his director eventually said, “he obviously didn’t like toiling here so we helped him leave.”
- oulipo 2y agoJust did a slightly more elaborate version (mostly colors) run it with `uv run --script script.py` #!/usr/bin/env -S uv run --script # /// script # requires-python = ">=3.13" # dependencies = [ # "rich", # ] # /// # run using `./script.py` or `uv run --script script.py` import argparse from rich import print from rich.prompt import Prompt from rich.panel import Panel def print_title(text): print(Panel(f" {text}", style="green")) print("\n") def print_desc(text): print(f"[yellow] {text}[/yellow]") def print_command(text): print(f"[white]{text}[/white]") def user_input(prompt): print("\n") return Prompt.ask(f"\n[red] {prompt}[/red]") def wait_for_enter(dummy_flag): print("\n") print(Panel(f" Press enter to continue", title_align="center", style="blue")) input() class CreateSSHKeypairStep: def run(self, context): print_title("Generating SSH Key Pair") print_desc("Run:") print_command(f"ssh-keygen -t rsa -f {context['key_path']}/{context['username']}.pub") wait_for_enter(True) class GitCommitStep: def run(self, context): print_title("Committing SSH Key to Git Repository") print_desc("Run:") print_command(f"cp {context['key_path']}/{context['username']}.pub user_keys/") print_command(f"git commit {context['username']}") print_command("git push") wait_for_enter(True) class WaitForBuildStep: build_url = "http://example.com/builds/user_keys" def run(self, context): print_title("Waiting for Build Job to Finish") print_desc(f"Wait for the build job at {self.build_url} to finish") wait_for_enter(True) class RetrieveUserEmailStep: dir_url = "http://example.com/directory" def run(self, context): print_title("Retrieving User Email") print_desc(f"Go to {self.dir_url}") print_desc(f"Find the email address for user `{context['username']}`") context["email"] = user_input("Paste the email address and press enter") class SendPrivateKeyStep: def run(self, context): print_title("Sending Private Key") print_desc("Go to 1Password") print_desc(f"Paste the contents of {context['key_path']}/{context['username']} into a new document") print_desc(f"Share the document with {context['email']}") wait_for_enter(True) if __name__ == "__main__": parser = argparse.ArgumentParser(description="Automate SSH key setup and sharing process.") parser.add_argument("username", type=str, help="Username for whom the SSH key will be generated") parser.add_argument("--key-path", type=str, default=".", help="Path where the SSH key will be stored (default: .)") parser.add_argument("--extra-args", nargs="*", help="Additional arguments for future use") args = parser.parse_args() context = { "username": args.username, "key_path": args.key_path, "extra_args": args.extra_args or [] } procedure = [ CreateSSHKeypairStep(), GitCommitStep(), WaitForBuildStep(), RetrieveUserEmailStep(), SendPrivateKeyStep(), ] for step in procedure: step.run(context) print("[green] Done.[/green]")
- iancmceachern 2y agoI cannot overstate how big a fan i am of this approach. I've successfully applied this approach to so many projects. My favorite example is a $30 million surgical robot that was failing labs because of the "human factor".
- treetalker 2y agoWould you mind sharing more details from one or more of your examples, or a summary of your experiences and tips (either here or in a blog post)? I would be interested to read, and from the looks of this thread, others would be too! I'm in a different field (law practice) but I'd love to consider how I could apply this approach in my firm.
- IanCal 2y agoOften these are setup scripts or similar for a codebase, so you might have a readme with instructions like 1. Update the submodules by running ... 2. Install volta 3. Run `volta ...` 4. Setup a user account 5. Sync the dev database by running `...` Now you can have that as documentation, or you can set it up as a checklist that runs the user through it and tells them what to do at each stage. Then you can swap out asking the user to do something to just doing it (e.g. 1, 3 and 5 are easy and 2 & 4 are at least less so). > I'm in a different field (law practice) but I'd love to consider how I could apply this approach in my firm The starting point is to consider any checklist type steps you have. Forgive me if I make up an example that sounds daft in your field but perhaps you have something like Finalising client. 1. Ensure invoices are filed 2. Check all invoices have been paid 3. Send email to client 4. Set status of account to CLOSED on lawversionofsalesforcemaybethatsjustsalesforce You can have this as a list of instructions. You could then change it to a checklist a person goes through and says which they've done. Then you might spot that #2 actually could just hit an API and check they've been paid. And #4 could be done too. You didn't have to automate 1 and 3, but you started with a useful thing and then incrementally removed busywork. The approach is both really useful and also not really that big of a deal. The first step is just moving a checklist to a small program that lists the checklist. You're not automating anything. But then it makes the job of automating something in the list far smaller.
- machine_ghost 2y agoThis same is also known by another name when it's used to teach new programmers: pseudo code. Sadly, because it's associated with learners/juniors, pseudo code gets a bad rap. But really, all engineering is translating English into code ... which means almost any complex operation (setting up a new employee's account, or anything else) can be made clearer by utilizing such an "in-between English and code" step. In the article they used Python, but for all the important stuff, they didn't: they used English. A "do-nothing" script is really just a script where instead of converting pseudo code to code (like programmers normally do), you just leave the English/pseudo code in, and wrap it with a print.
- hnlmorg 2y agoI get the point you’re making but I cannot say I agree with it. Pseudo code is non-compilable text that’s intended to illustrate a computer function. Whereas this is compilable code used to illustrate a human function. So in a sense, they’re solving the exact opposite problems.
- aqueueaqueue 2y agoNever heard pseudocode getting a bad rap. It is good for archutecture discussions, decision documents, comments and so on. But I don't often hear it referenced by name. I also think geohot(?) said something like "Python is popular as it feels like you are writing psuedocode". And I agree!
- jspash 2y agoIt goes by many names. I believe the original name was checklist. It used to be written on paper by the ancient ones and followed step by step until the task was complete. I can't wait for the npm package. /s
- layer8 2y agoI would use a checklist for that. Most wiki/notes/todo software supports checklists or checkboxes. It has the benefit that you can still see all steps at once, perform some steps out of order if the dependency isn’t linear, and it can be simply part of your process documentation instead of having to find and run a script. It’s also easier to edit. The article even mentions “just another checkbox checked”.
- thfuran 2y agoThe whole point is to get it automated. A checklist in a note app is not on the path to automation.
- dijksterhuis 2y agoOn a scale of 'no-one has a bloody clue' to 'fully automated', having the process written down somewhere is closer to fully automated than nothing. So, it is on the path. I've used checklist documentation to document the series of logical steps needed to deploy something. there were no docs left by the previous team, had to work it out myself. that checklist turned into an ansible playbook (which later got binned for something else, but we had all the steps worked out by then). wikis / markdown checklists have the benefit of being easy to copy and paste into. don't need to worry about "does it run" just "did i paste it in yet". having said that, for the SSH key example, I really like this idea. Not because it's a good example (who the hell shares the private key?!), but because I always forget the SSH commands I need as I use them so infrequently. so having a 'do-nothing' script laying around to make my dumb brain go to the right places and type the right things would be helpful.
- outofpaper 2y agoThis is a waste of energy as there a cleaner clearer more effective ways of dealing with this script. You can go much cleaner and just do a Markdown Slideshow. Alternatively allow for a little real automation and use something like Expect or Pexpect. https://pexpect.readthedocs.io/en/stable/overview.html https://pexpect.readthedocs.io/en/stable/overview.html Don't pretend to yourselves that presenting a series of instructions and only advancing on when someone clicks enter will prevent people hit enter. Even worse is someone missed up there's no going back. You have to either restart the whole process or you have to go and read over the python script. This is not something that prevents or helps with slog.
- aqueueaqueue 2y agoOh yeah! I've seen this pattern used at work. I don't have an opinion on if it is better than a checklist. The lack of will or time to automate affects a do nothing script as much as runbook.
- jiggawatts 2y agoMy variant of this is putting the manual steps in between scripted steps as a comment, but having read the article I can see the benefit of this approach. In PowerShell especially there are elegant ways to prompt users for “continue y/n?”.
- deleted 2y ago[deleted]
- PaulRobinson 2y ago1. Write the runbook 2. Automate the runbook 3. Delete the runbook This is just a means to get #2 done iteratively. I've done variations for a while, its a powerful technique.
- po84 2y agoWe taken this approach using streamlit to incrementally turn Markdown lists of instructions into mini, self-service web apps. Steps in lists are gradually replaced with widgets, collecting inputs for the automation to do the work instead.
- m463 2y agodo each of the steps, as an object, look overengineered? I follow the advice of this column, but I differ in my implementation. It is lightweight and not so OO.
- hansvm 2y agoI'm more anti-object than most people, and this doesn't look terrible to me. You have a sequence of imperative steps, and they're represented with two levels of nesting rather than one. So long as nobody fucks the thing up more and overcomplicates your do-nothing automation, even the most vocal opponents of 'class AbstractFoo: pass` are likely to agree that the damage here from that abstraction is minimal.
- HappMacDonald 2y agoI don't see any objects in this script though, just functions.
- m463 2y agowell, he defines a bunch of classes each with a single method then... just seems to add a lot of abstraction, that might bury your understanding.
- midtake 2y agoThen it really isn't doing nothing. Rather, it's a to-do app in the terminal. The reason it is helpful for decreasing activation energy is that it handles the "checklist" aspect of creating a user account for you. This is especially helpful for user account creation, which has to be done completely and then logged or it can lead to cybersecurity incidents.
- remram 2y agoclass Foo(object): def run(self, context): ... Objects with only a single method to run it are already built into Python, they are the functions. def foo(context): ...
- porridgeraisin 2y agoBut how can one survive without a daily dose of Utterly Brain Damaged Abstractions?
- itherseed 2y agoThe advantage of the original approach is that later, when you need it, you can just add more methods to a class that are private to them. In your approach, if you need a new function, you add it at the global level, which can totally be fine for one or two functions, but with any more you end up with a bunch of functions all at the same level that is no longer obvious the dependency between them.
- heisenzombie 2y agoIf you want a function that's private to a function in Python you _could_ also do: def foo(context): def bar(x): return x*2 baz = bar(context) ... This is particularly idiomatic for higher order functions, but I think it can be useful for other things if used with restraint. But if you have functions that only need to be called from one calling function then I why not just inline the code and eschew having a function at all. Long function bodies for the win!
- notfish 2y agoDon’t do this, it makes it a huge pain to test bar(). When you write the initial code to figure out bar, just throw that code in a unit test so you can run it any time. Stop throwing tests away!
- heisenzombie 2y ago
- 20after4 2y agoI found this a few years ago and was quite inspired by it. I then more recently found https://xcfile.dev/ https://xcfile.dev/ which is a great way to implement these sort of scripts directly in the project's README.
- sagarpatil 2y agoI’ll probably get down voted to oblivion, but this is really silly. I do not see any value proposition. To each their own, I guess.
- stego-tech 2y agoThis is, to a degree, how I’ve always written my SOPs. If anything, this approach is encouraging me to make two changes to my documentation approach: 1) Add a “Quick Run” section with just the steps/commands absent images and details, so it’s easier to perform routine slogs without having to scroll through unnecessary information. 2) Make (and link!) a companion code document that has the pseudocode for the process written out, so folks can contribute to it as time allows. If I’m a manager, I’d even incentivize it somehow - maybe covering a team lunch if we convert an SOP into an automation, for instance. In the meantime, I am totally cribbing this for documenting my homelab stuff and getting it out of Obsidian, as a means of encouraging me to automate routine tasks somehow.
- genewitch 2y agoWe made a headless, non-intaractive gentoo installer by basically doing your first change to the gentoo handbook and then my associate bashed it all. I think it still bootstraps AWS gentoo images.
- mind_ru 2y ago[dead]
- advael 2y agoI love this approach. I already like doing this in systems above a certain complexity made with programming languages too. I think the functional programming community calls this "holes"? Interface "not implemented" errors follow a similar logic but I honestly think the value of writing something trivial that gives a meaningless but valid output for each of a bunch of pieces that depend on each other goes a long way toward expediting the process of building those pieces. It makes it much more likely you can test and build one thing at a time and not need to write a bunch of separate parts before you can test any of them Having this type-wise validity matter in scripting contexts is sometimes harder, as in the use case described in the article, as a lot of the effects of command lines are going to be "side effects" from a functional perspective, but it being sequential makes this a lot less impactful and the waiting prompts make it so you can still preserve order of tasks at the low cost of needing manual steps you'd be doing without the script anyway Scaffolds are incomplete but they're still, fundamentally, useful
- aetherspawn 2y agoOne Note is good for this, it doesn’t have to be a do-nothing script. One Note also has the ability to add checkboxes as dot points, and you can make “template pages” for each procedure and then you can then just right click -> duplicate, and use the checkboxes to keep track of where you get upto in a process. The reason this is great for me is because I virtually never get to sit still and finish anything unless it takes less than 1 min. People pull my attention in every direction.
- rzzzt 2y agoIs it possible to make OneNote _not_ create a text block wherever I click the mouse? I'd like to write a series of paragraphs starting from the top left corner, but that corner seems to shift from page to page.
- IanCal 2y agoDoes one note have some way of adding scripted items to automate some of the steps?
- aetherspawn 2y agoI don’t think so, but in my opinion a lot of business stuff takes way too much effort to integrate and is too flakey (APIs keep changing) that we don’t bother automating much between silos anymore. It literally takes more time (and cost) on average to automate the task, than what you save if you do the task less than 50 times or so per month, and once you automate it you’ll have to maintain the automation which will break more than you expect (rotate API keys, APIs change, etc) So I used to push hard for automation. Now I push hard for simplicity (checklists) so the clerks can deal with it and free up the devs to improve product.
- al_borland 2y agoWhile I like this in theory, I think it would have trouble in practice. If an ops team is doing the same task over and over, and they see the do-nothing script does nothing, they will quickly stop using it once they think they’ve memorized the steps, or if they think it’s faster (or more interesting) to do it manually. I’ve written a lot of automation and documentation for ops teams and getting them to use it, and use it constantly, has always been an issue. Doc changes also needed announcements, as people quickly stop reading them once they know how to do something. In a perfect world, I think the approach makes a lot of sense, and I might even use it for some personal stuff. In practice the world is rarely perfect, and I think I’d only employ this if 90% was automated, but there was still 1 step I couldn’t quite get… and even then, I could see some members on the ops team skipping the manual step and assuming the whole thing is automated and magic.
- chikere232 2y agoOften some bits are automatable, or some manual steps are verifiable, and then suddenly it's a do something script
- chikere232 2y agoI do this for some yearly tax stuff, as the big issue for me is that it was a year since I did it last and getting started with a complex and boring thing is hard So I built a script that tells me what the first step is. When it's done I run the script again and it tells me what to do next. Often the first few steps are "download this CSV from the bank" so the script can detect I've done than and go directly to the next step when I rerun the script The reason I have a script I rerun rather than a "press enter to continue" is because it then only keeps persistent state, and I can easily do a bit every day until done A common pattern is if ! [[ -e checked-all-the-receipts ]]; then echo "check that the receipts match the list of expenses, then" echo " touch checked-all-the-receipts" exit 0 fi Then over time, I have automated some parts and added some checks. E.g. when I have downloaded a CSV I can check that the format looks right before considering the step done. I've added some autogeneration of documents I need, built a python script to add up transactions and check the that the totals match etc
- inib 2y agoAs someone who struggles on their personal life to do things step by step, I thank you for this private-life example of the OP approach.
- akkad33 2y agoI don't get why it's such a big deal
- dariusj18 2y agoHas anyone here successfully (or not) implemented BPMN for this kind of process management?
- DocTomoe 2y agoIn my time we called that a 'checklist'. We used it for overcomplicated build procedures in some forsaken Microsoft toolchain that did not have build automation, and which spanned several different systems that were firewalled off from each others.
- 0xbadcafebee 2y agoWhile the idea of it is nice, I've never actually used it more than once or twice. Instead I write runbooks in Confluence, and that evolves over time. Confluence is fantastic for runbooks. It's accessible to all kinds of users, you don't have to grant access to them, you get comments, people can edit on the fly without a review, the content is versioned, and most importantly, includes mixed media. My runbooks are often a mix of video clips, screenshots, text, and links to other pages. In order to automate the runbooks, I do a couple things: 1) I write little scriptlets and either drop them into the runbook as one-liners, or commit them to a `./bin/` directory in a repo with some basic documentation. 1a) If I write a script, usually I make it so it takes some arguments and produces output, so that it can be modified later in a backwards-compatible way, and so it can be composed-with. Every time I do this, I'm making automation easier later on. 2) I have a deployment wrapper `deploy.sh`, and a CI/CD job that calls the wrapper. If I make my scriptlets call-able from `deploy.sh`, then my scriptlets get to take advantage of all the environment set-up my CI/CD job did, so I don't have to do any more work to get the CI/CD system to call my scriptlet. And since my CI/CD job can take parameters and pass them onto `deploy.sh`, and `deploy.sh` can pass arguments to my scriptlet, and my scriptlet can take arguments, I can now re-use the one CI/CD job I made, to call my scriptlet, from any CI/CD pipeline, or from a one-time API call to the CI/CD provider with parameters. 3) I have a Slack bot that'll take commands from Slack and call the CI/CD job with parameters. Now I'm enabling chat users to call automation from Slack, reusing the CI/CD, reusing the deploy.sh, reusing my scriptlets, enabling users to call automation from their chat window. 4) I modify the Slack bot to allow users to edit cron jobs (really just scheduled CI/CD jobs) to run tasks on a regular basis. Now they can either use pre-written scripts, or write their own, and schedule them to run regularly. Now, my day job has quite a few different responsibilities (as all Sysadmi-cough I mean "DevOps Engineers"- tend to have), so I don't have time to build all this in one go at each job I work at. I build the whole thing slowly over time. As each new feature is available, I release it for use: first the Confluence runbooks, then the scriptlets, then the CI/CD jobs, then the Slack bot. It takes about two years for all of it to be ready. But once it is, it's amazing how much productivity a whole team of people gets out of it. If I was allowed to do all this automation at once, we'd reap the benefits much sooner. But people who have never seen the rewards of automation never prioritize it.
- euroderf 2y agoKinda sounds like a "TBS-driven" approach. Certainly helpful.
- jeffrallen 2y agoIn 2025, this is insane. With Aider + $10 of credit on OpenAI, I can tell Aider to make this same script and it will actually make it do something.
- btbuildem 2y agoIt's not a "do nothing" script at all! The script encodes a high-level workflow, which is crucial, mission-critical information. It doesn't really matter what "runs" the steps, you can assume it's an agent of some sort. Sometimes that role is played by a human person, sometimes not.
- maCDzP 2y agoSWE version of a checklist?
- shekhargulati 2y agoI wrote a simple LLM tool that helps generate such scripts. Tool: https://tools.o14.ai/do-nothing.html https://tools.o14.ai/do-nothing.html Blogged about here: https://shekhargulati.com/2025/02/16/do-nothing-script-generator/ https://shekhargulati.com/2025/02/16/do-nothing-script-gener...