6 ms·
I'm completely done with configs written in YAML. Easily the worst part of Github Actions, even worse than the reliability. When I see some cool tool require a
by bilalq 3y ago
I'm completely done with configs written in YAML. Easily the worst part of Github Actions, even worse than the reliability. When I see some cool tool require a YAML file for config, I immediately get hit with a wave of apprehension. These same feelings extend to other proprietary config languages like HCL for Terraform, ASL for AWS Step Functions, etc. It's fine that you want a declarative API, but let me generate my declaration programatically.
Config declared in and generated by code has been a superior experience. It's one of the things that AWS CDK got absolutely right. My config and declarative definition of my cloud infra is all written in a typesafe language with great IDE support without the need for random plugins that some rando wrote and never updated since 2 years ago.
- weebull 3y agoGitHub actions would suck whatever you "configured" them in, because you are trying to describe a program in a data structure. Ansible makes the same mistake, as do countless other tools.
- tomjakubowski 3y ago"because you are trying to describe a program in a data structure" (cries in lisp)
- btown 3y agoI often wonder if the only reason we haven't used lisp more as a society, and certainly in the devops world, is because our brains find it easier to parse nested indentation than nested parentheses. But in doing so, we've thrown out the other important part of lisp, which is that you can use the same syntax for data that you do for control flow. And so we're stuck in this world where a "modern-looking" program is seen as a thing that must be evaluated to make sense, not a data structure in and of itself. https://www.reddit.com/r/lisp/comments/1pyg07/why_not_use_indentations_rather_than_numerous/ https://www.reddit.com/r/lisp/comments/1pyg07/why_not_use_in... is a fascinating 10 year old discussion. And of course, there's Smalltalk, which guided others to a treasure it could not possess. But most younger programmers have never even had these conversations.
- kazinator 3y agoThe vast majority of Lisp code is assiduously written with nested indentation! So that can't be it. Non-lisp languages have parentheses, brackets and braces, using indentation to clarify the structure. Nobody can reasonably work with minified Javascript, without reformatting it first to span multiple lines, with indentation. Lisp has great support for indentation; reformatting Lisp nicely, though not entirely trivial, is easier than other languages. Oh, have you seen parinfer? It's an editing mode that infers indentation from nesting, and nesting from indentation (both directions) in real-time. It also infers closing parentheses. You can just delete lines and it reshuffles the closers. The github.io site has animations: https://shaunlebron.github.io/parinfer/ https://shaunlebron.github.io/parinfer/
- eternityforest 3y agoTo me it seems a lot of the benefit of declarative programming is just that you can use less powerful tools that don't allow constructs you don't want to have to deal with . LISP seems great for tinkerers and researchers, but not so much corporate devs who want extreme amounts of consistency and predictability, but don't need the absolute most elegant solution.
- kazinator 3y agoThe best interpretation of weebull's comment is not that describing a program in a data structure is "bad" per se, but that doing that in a configuration language (or requiring configuration constructs to be programming constructs) might not be a hot idea. Even Lisp software that uses Lisp for configuration does not necessarily allow programming in that configuration notation.
- jrockway 3y agoYeah, I think describing a program in a data structure is fine. I honestly prefer it to any syntax that a "real" programming language has brought me. It's so consistent and you can really focus on what you care about. What is unhappy about Github Actions and similar is that your programming language has like 2 keywords; "download a container" and "run a shell script". I would have preferred starting with "func", "handle this error", and "retry this operation if the error is type Foo" ;) Since this article is about helm, I'll point out that Go templates are very lispy. I often have things in them that look like {{ and (foo bar) (bar baz) }} and it only gets crazier as you add more parentheses ;)
- throwaway894345 3y agoThe problem I have with GitHub Actions is that I usually want to metaprogram them. I have a monorepo and I want a particular action to run for each "project" subdirectory. I've written a program that generates GitHub Actions YAML files, but all of the ways to make sure the generator was run before each commit are fairly unsatisfying. The problem I have with infra-as-code tools is that what I really want is a pretty simple representation for "the state of the world" that some reconciliation can use, and then I want to generate that stuff in a typesafe, expression-based language like TypeScript or Python (Dhall exists, but its Haskell-like syntax and conventions are too steep a learning curve to get mainstream adoption). Instead we get CloudFormation and Terraform which shoehorn programming language constructs into a configuration language (which isn't strictly an objection to code-as-data generally) or things like Helm which uses text templates to generate a "state of the world" description or these CDKs which all seem to depend on a full JavaScript engine for reasons that don't make sense to me (why do I need JavaScript to generate configuration?).
- latchkey 3y ago> Ansible makes the same mistake, as do countless other tools. My favorite example of this is chown/chmod taking 4-5 lines, in yaml. Sure you can do it a bunch of different ways, sure it allows for repeatable commands. But, it just sucks.
- lolinder 3y ago> you are trying to describe a program in a data structure This describes 100% of software development, though! Programming is just designing data structures that represent some computation. Each language lends itself better to some computations than to others (and some, like YAML, are terrible for describing any kind of computation at all), but they're all just data structures describing programs. The problem isn't that GitHub Actions tries to describe a program in a data structure, the problem is that the language that they chose to represent those programs (YAML and the meta language on top) is ill-suited to the task.
- hintymad 3y agoThe same reason I don't like AWS' Step Functions. The spec in JSON is horrible. On the other hand, Step Functions is pretty scalable and reliable and can take practically unlimited throughput. It's a good story for how a product can succeed by getting the primitives right and by removing just the key obstacle for users. Now that Step Functions has gained momentum, they can construct higher-level APIs and SDKs to translate user spec to the low-level JSON/YAML payload.
- treflop 3y agoIf configs had well-adopted schema support, it wouldn't be so bad.
- bilalq 3y agoEven then, it gets messy. From a tooling standpoint, how will I load your schema? How will my editor respect it? How do I run a validator against it? I know XML kind of solves some of these problems, but it has its own thorns and despite what anyone says, it is not easy to work with. XSD, XSLT, etc. So much complexity that needs to be managed in a different way in every runtime. And then type safety goes out at the boundary where it connects to your code.
- treflop 3y agoThat's how it used to be for your suggestion too. We're living in a dream state now where the creators of IDEs like Visual Studio (Code) or IntelliJ actively implement common languages and frameworks. It used to be 'find a half-baked community plugin so JSON works.' If someone made a standard schema and people used it, I can assure you the magic you are expecting from your tooling would suddenly pop in just like how JSON support appeared one day. But they can't do nothin' if there is no community support for it. XSD and XSLT are complicated because XML is complicated.
- jrockway 3y agoAt this point, I even prefer plain JSON to YAML. What pushed me over the edge is that "deno fmt" comes with a JSON formatter, but not a YAML formatter. It's a single binary that runs in milliseconds. For YAML auto-formatting you basically have to use Prettier, and Prettier depends on half of NPM and takes a good 2 seconds to startup and run. So, I literally moved every YAML file in our repository at work that could be JSON to JSON and I think everyone has been much happier. Or, at least I have been, and nobody has complained to me about it. Various editors also support a $schema tag in the JSON. I added this feature to our product (which has a flow that invokes your editor on a JSON file), and it works great. You can just press tab and make a config file without reading the docs. Truly wonderful. YAML has this too with the YAML language server, but you need your tab key to indent stuff, so the ergonomics are pretty un-fun. JSON isn't perfect, but at least the text "no" is true.
- matsemann 3y agoAt work we're currently expanding to another country. Which means that many services now need a country label etc., which is fun when you're adding "no" to all our existing services. Luckily it's quick to catch, but man... why?
- throwaway894345 3y agoYeah, I'm pretty sure there are exactly two substantive problems with JSON for (static) configuration file use cases, which are comments and multiline strings (especially with sane handling of indentation). YAML fixes these, but it adds so much complexity in the process including such a predictable footgun of unquoted strings (the no/false problem is particularly glaring/absurd, but it's also easy to forget to quote other boolean values or numbers in a long list of other strings).
- radlad 3y agoCan I add "trailing commas are invalid" to the list?
- Footkerchief 3y agoIn the case of GitHub Actions, it's made more painful by the lack of support for YAML anchors, which would provide a bare minimum of composability. https://github.com/actions/runner/issues/1182 https://github.com/actions/runner/issues/1182
- throwaway894345 3y ago> These same feelings extend to other proprietary config languages like HCL for Terraform, ASL for AWS Step Functions, etc. It's fine that you want a declarative API, but let me generate my declaration programatically. Yeah, I've had the same sort of opinion since the bad old AWS CloudFormation days. I wrote an experimental CloudFormation generator 4 years ago where all of the resources and Python type hints were generated from a JSON file that AWS published and it worked really well (https://github.com/weberc2/nimbus/blob/master/examples/src/nimbus_examples/s3bucket.py https://github.com/weberc2/nimbus/blob/master/examples/src/n...). > Config declared in and generated by code has been a superior experience. It's one of the things that AWS CDK got absolutely right. Is that how CDK works? I've only dabbled with it, but it was pretty far from the "generate cloudformation" experience that I had built; I guess I never "saw the light" for CDK. It felt like trading YAML/templating problems for inheritance/magic problems. I'd really like to hear from more people who have used AWS CDK, Terraform's CDK, and/or Pulumi.
- bilalq 3y agoIt's an annoyingly OOP model with mutations and side-effects, but if you look past that, it's pretty nice. The core idea is you create an instance of a CDK "App" object. You create new instances of "Stack" objects that take an "App" instance as a context parameter. From there, resources are grouped into logical chunks called "Constructs" which take either a stack or another construct as their parent context param. The only things you should ever inherit from are the base Constructs for Stack, Stage, and Construct. Don't use inheritance anywhere else and you'll be okay. The code then looks something like this (writing this straight in the comment box, probably has errors): // Entrypoint of CDK project like bin/app.ts or whatever import * as cdk from 'aws-cdk-lib' import { MyStack } from '../lib/my-stack.ts' const app = new cdk.App() const stack = new MyStack(app, 'StackNameHere', someProps) // lib/my-stack.ts // Imports go here export class MyStack extends cdk.Stack { constructor(scope: Construct, id: string, props: MyStackProps) { super(scope, id, props) const bucket = new s3.Bucket(this, 'MyBucket', { bucketName: 'example-bucket', }) const lambda = new NodejsFunction(this, 'MyLambdaFn', { functionName: 'My-Lambda-Fn', entryFile: 'my-handler.ts', memorySize: 1024, runtime: Runtime.NodeJS_20X }) bucket.grantRead(lambda), tracing: Tracing.Active }) } The best part is the way CI/CD is managed. CDK supports self-mutating pipelines where the pipeline itself is a stack in your CDK app. After the pipeline is created, it will update itself as part of the pipeline before promoting other changes to the rest of your environments. The equivalent CloudFormation for the above example would be ridiculously long. And that's putting aside all the complexity it would take for you to add on asset bundling for code deployed to things like Lambda. TL;DR: Infrastructure-as-code-as-code
- hintymad 3y agoAn often-heard benefit for using YAML is that JSON does not have comment. What I don't understand is why we would switch to a whole new language. Just add a filter before loading the configuration, which can't be harder than switching to YAML, right? Another reason for YAML is that it is easier to read. That I don't understand either. The endless pain of dealing with configuration does seem come from saving a few seconds of parsing off braces and brackets, but from not being about easily figure out what goes wrong, especially when what's wrong is a missing space or tab embedded in hundreds of lines of configurations.
- p10_user 3y agoJust make another named list key called "comment". Problem solved.
- int_19h 3y agoThis is not always an option when JSON is propagated as is, nor does it allow for comments on specific object properties.
- int_19h 3y agohttps://json5.org/ https://json5.org/
- m463 3y agoI like json a lot. That said, I think json would benefit from only two things: 1) comments 2) allow extra commas, like ["a", "b", "c",] or {"a":"b", "c":"d", } or more properly: { "a":"b", "c":"d", }, EDIT: and json5 does both, plus a few more niceties. (hmm. too much?)
- mekster 3y agoNot sure why people just don't settle with TOML.
- xdennis 3y agoIt has atrocious arrays. Example: https://youtu.be/n9mGk8_tQtM?t=367 https://youtu.be/n9mGk8_tQtM?t=367
- didip 3y agoFor real, I want a real language (Lua/JS/Lisp) for configuration but without 3rd party imports so that it's secure and predictable.
- SergeAx 3y ago> Config declared in and generated by code has been a superior experience. And here we are at the point in time when people are plainly forgotten about compiled programming languages.
- w0m 3y agoliving in a yaml-world; i honestly hate it.
- gofreddygo 3y ago> let me generate my declaration programatically this sort of thing looks and sounds like the right thing to do. Till you do it, on a largeish project with multiple teams that have experienced attrition. I quietly added a layer of yaml generating code to make it bearable.