924 karma · joined December 13, 2022
I studied electronics, so naturally we began with assembly (Motorola HC11). By the end of the course everyone had independently developed their macros to do things like for-loops, so it was a natural progression from there to C. By the end of the C course "C-style OOP" had also emerged naturally, which led to the next course in C++.
The downside of this approach is that it there is no gradual route from there to functional paradigms (or non-imperative in general). Also, one develops the habit of always thinking of how the language works under the hood, which can be counter, productive. E.g. when I was trying to learn Haskell, my mind was trying to understand how the interpreter worked.
Learning assembler is not just about the language, but understanding how the machine works (buses, memory-mapped peripherals, etc). In older platforms this is much simpler, so while ARM instructions can be easier to learn than the CISC instructions of the HC11, everything else is much friendlier for the beginner in the HC11.
In the real world the ultimate countermeasure is bullets. All the rest is to avoid reaching this last resort.
Information should only from from the user scripts to the CI, and communication should be done by creating files in a specific format and location. This way the system can run and produce the same results anywhere provided it has the right environment/container.
For example, tests involving read hardware can only run at 1x speed, so you will want to avoid running those if you can. If you are building a custom compiler toolchain, that is slow and you will want to skip it if the changes cannot possibly affect the toolchain.
The pipeline DSLs, because they are not full programming languages have to include lots of specific features and options and if you want something slightly outside of what they are designed for, you are out of luck. In a way it feels like how graphics were in the age of fixed-pipeline, when there had to be a complex API to cover all use cases yet it was not flexible enough.
Then there is the YAML config which is too convoluted. It took me several attempts to get things right.
What works better, IMO, is to have each CI step as a script or a Make target that can run anywhere (CI or dev PC) and in the CI configuration have a single line in each step that invokes the script.
I don't see the point of refusing to add additional (copyleft) terms to a license, only to end up hoping companies act as if the terms existed out of good will.
Companies like Google love the permissive licenses, and go as far as to sponsor MIT/BSD-licensed replacements to common building blocks like toybox.
EDIT: I see that Forgejo v9+ is indeed GPL-licensed.
It is the equivalent of eating soup at a homeless shelter when you can go to the store and buy something better, made worse by the fact that you are making the decision for someone else that cannot decide on their own.
For example, nobody in their right mind would consider a policeman being distinguished for stopping a shooter as "glorifying violence" even if the officer had to use violence to him down.
The rules are reasonable as far as they prohibit glorifying illegitimate violence. Whether the platforms applies the rules in this way for other cases or not is irrelevant for this particular case, even if we know the TOS are applied pretty arbitrarily.
For the use cases mentioned in the article, I have used JSON with schemas and JSON-merge and JSON-patch quite effectively. VScode supports schemas so it will help you edit the file without making mistakes. You can use JSON merge to combine global and local configs and you could even use custom fields in the schema to indicate metadata, for example, that a key represents an upper limit so the lowest value should be considered when merging.
In the end it is no different from any code that's suffered from 10 years of tuning and it can get ugly. Maybe Make is even somewhat worse in this respect, but then again it does not need to be changed often.