[HN Gopher] Do-nothing scripting: the key to gradual automation ...
       ___________________________________________________________________
        
       Do-nothing scripting: the key to gradual automation (2019)
        
       Author : tehnub
       Score  : 323 points
       Date   : 2025-02-07 19:48 UTC (1 days ago)
        
 (HTM) web link (blog.danslimmon.com)
 (TXT) w3m dump (blog.danslimmon.com)
        
       | IanCal wrote:
       | I'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 wrote:
         | 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..
        
         | dheera wrote:
         | I 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 wrote:
           | 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
        
             | IanCal wrote:
             | 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.
        
           | IanCal wrote:
           | 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.
        
           | Xmd5a wrote:
           | >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 wrote:
         | 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.
        
           | IanCal wrote:
           | I'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.
        
         | hinkley wrote:
         | My 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.
        
         | dejj wrote:
         | 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.
        
       | MattSayar wrote:
       | I 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
        
         | picture wrote:
         | What does POSSE stand for?
        
           | kawera wrote:
           | https://indieweb.org/POSSE
        
       | qwertox wrote:
       | It'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 wrote:
         | Are these actual criticisms of the article?
         | 
         | And you leave us hanging: which solution is the "simplest
         | solution"?
        
           | codetrotter wrote:
           | 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.
        
             | qwertox wrote:
             | Yes, this was what I meant. Sorry to your parent commenter
             | for not being explicit.
             | 
             | (Then again, I'd do this in Obsidian.)
        
               | gertlex wrote:
               | 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.
        
         | IanCal wrote:
         | 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.
        
         | vagab0nd wrote:
         | > but it can't be interrupted
         | 
         | 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?
        
           | mwdomino wrote:
           | 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
        
       | mettamage wrote:
       | I 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 wrote:
         | 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.
        
           | mettamage wrote:
           | Yep, 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
        
           | RodgerTheGreat wrote:
           | 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.
        
       | captnswing wrote:
       | https://www.pyinvoke.org/
        
         | qwertox wrote:
         | > 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 wrote:
       | > 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 wrote:
         | Yes.
         | 
         | > 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 wrote:
       | 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.
        
       | linsomniac wrote:
       | The author needs to watch my buddy Jack's talk: Stop Writing
       | Classes: https://youtu.be/o9pEzgHorH0?si=FgZqFGQNQUU2iREQ
        
         | PNewling wrote:
         | Care to give a TL;DW for those of us not able to watch this at
         | the moment?
        
           | nerdponx wrote:
           | The title I think gets the point across!
        
             | linsomniac wrote:
             | 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.
        
           | Jtsummers wrote:
           | 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.
        
             | linsomniac wrote:
             | 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". :-)
        
       | linsomniac wrote:
       | 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()
        
         | do_not_redeem wrote:
         | 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.
        
           | linsomniac wrote:
           | Which 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 wrote:
             | Original 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.
        
               | linsomniac wrote:
               | 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.
        
           | linsomniac wrote:
           | Note: ChatGPT didn't blindly reuse a private key:
           | [N] /tmp> "ssh-keygen" "-t" "rsa" "-f" foo "-N" ""
           | Generating public/private rsa key pair.         foo already
           | exists.         Overwrite (y/n)?
           | 
           | 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.
        
             | do_not_redeem wrote:
             | These lines skip the call to ssh-keygen:                 if
             | os.path.exists(keyfile):           print("Key file {}
             | already exists. Skipping generation.".format(keyfile))
        
             | oasisaimlessly wrote:
             | It seems to me like you are assuming ChatGPT is always
             | going to be _right_ , which is coloring your use of the
             | tool.
        
               | linsomniac wrote:
               | 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.
        
           | bagok wrote:
           | > security vulnerability
           | 
           | 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.
        
         | bshacklett wrote:
         | 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.
        
           | linsomniac wrote:
           | 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.
        
         | daxfohl wrote:
         | 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.
        
       | niemandhier wrote:
       | 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.
        
       | xp84 wrote:
       | 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.
        
       | rpicard wrote:
       | 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.
        
         | gertlex wrote:
         | 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.
        
           | rpicard wrote:
           | 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.
        
       | dolmen wrote:
       | This 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
        
         | chuckadams wrote:
         | Making unskilled users manage their keys themselves doesn't
         | sound very secure either. That's the point of moving to a
         | script.
        
         | JimBlackwood wrote:
         | > 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 wrote:
           | 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?
           | 
           | What do you actually do, and how is it better?
        
       | Jtsummers wrote:
       | Past discussions (lots of comments):
       | 
       | https://news.ycombinator.com/item?id=29083367 - 3 years ago (230
       | comments)
       | 
       | https://news.ycombinator.com/item?id=20495739 - 6 years ago (124
       | comments)
        
       | mamidon wrote:
       | To be clear; you're supposed to have a separate shell open where
       | you do these steps?
       | 
       | MM, interesting idea.
        
       | starkparker wrote:
       | 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().
        
       | deadbabe wrote:
       | Great in theory until some error or problem comes up and you
       | don't know how to handle it.
        
         | Jailbird wrote:
         | I'd say that's about the process itself, not the script
         | mirroring the process.
         | 
         | Fix the process, fix the script. Onwards....
        
       | __MatrixMan__ wrote:
       | 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".
        
       | parentheses wrote:
       | 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.
        
       | avipars wrote:
       | A good way of documenting processes for people that prefer to
       | look at code than long PDfs
        
       | tejtm wrote:
       | Haven'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.
        
       | parasti wrote:
       | 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.
        
       | perpil wrote:
       | I 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
        
       | hinkley wrote:
       | I 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 wrote:
       | Even 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 wrote:
       | Just 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]")
        
         | oulipo wrote:
         | Here's a screenshot:
         | 
         | https://imgur.com/a/MmViG7G
        
       | iancmceachern wrote:
       | I 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".
        
       | machine_ghost wrote:
       | This 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 wrote:
         | I 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.
        
       | layer8 wrote:
       | I 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".
        
       | outofpaper wrote:
       | This 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
       | 
       | 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 wrote:
       | Oh 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.
        
       ___________________________________________________________________
       (page generated 2025-02-08 23:00 UTC)