spotifyovercastrssapple-podcasts

GitHub Actions

We discuss best practices to setup GitHub Actions to make sure everyone has the same source of truth for checking your Elm code and deploying to production.
April 12, 2021
#28

Transcript

[00:00:00]
Hello, Jeroen.
[00:00:02]
Hello, Dillon.
[00:00:03]
And what are we talking about today?
[00:00:04]
Today we're talking about GitHub actions
[00:00:07]
and maybe also just CI in general.
[00:00:10]
Yeah, I'm hoping that I can get into some controversial opinions
[00:00:14]
and rile you up so we can hear about your thoughts
[00:00:16]
about this topic.
[00:00:19]
All right, all right.
[00:00:21]
I'm looking forward to it.
[00:00:23]
Let's see if I can do that.
[00:00:28]
They were running Elm review locally on their machine,
[00:00:32]
but they weren't running it anywhere else.
[00:00:35]
It's terrible.
[00:00:39]
Yeah, I already spoke about that during,
[00:00:42]
like every time I talk about Elm review,
[00:00:44]
I just run it in CI.
[00:00:46]
If nowhere else, in CI.
[00:00:50]
Yeah, CI.
[00:00:51]
So like why is that important?
[00:00:56]
Because it's a team.
[00:00:57]
So if you run Elm review on your machine, that's great.
[00:01:00]
But if another teammate doesn't run it on his machine by habit,
[00:01:05]
then there might be problems.
[00:01:07]
But as long as CI runs it,
[00:01:09]
then everyone will agree at some point,
[00:01:12]
as long as they don't merge in four requests
[00:01:15]
that failed tests and failed CI.
[00:01:17]
Right, right.
[00:01:19]
Yeah, it's almost like a way of making
[00:01:24]
it makes me think of this recent news story
[00:01:27]
where I don't remember what the company was,
[00:01:29]
but some company was blaming some like large security incident
[00:01:33]
on an intern using an insecure password.
[00:01:36]
And it was like, come on,
[00:01:38]
you're blaming this giant security vulnerability on an intern.
[00:01:43]
Obviously, the problem is that the intern was able
[00:01:46]
to use an insecure password
[00:01:48]
and an insecure password was able to lead
[00:01:53]
to the vulnerability, right?
[00:01:54]
So it's not the intern's fault.
[00:01:57]
Just like if somebody commits some code
[00:02:01]
and they don't use Elm format,
[00:02:03]
it's not their fault for messing up the code base
[00:02:07]
with non Elm formatted code or non Elm reviewed code.
[00:02:10]
It's the fault of the system for allowing it
[00:02:13]
and you need to address the systemic problem.
[00:02:15]
Yeah, I heard about the intern problem,
[00:02:20]
I heard about people blaming things on the intern
[00:02:23]
and like, you shouldn't blame things on the intern.
[00:02:25]
That's stupid.
[00:02:26]
And like, yeah, but why is everyone talking about this?
[00:02:29]
I didn't get that.
[00:02:31]
Right.
[00:02:32]
That's what happens when you read Twitter,
[00:02:34]
but you get the last things first.
[00:02:37]
Then you have to scroll down a lot.
[00:02:39]
Isn't that all that Twitter is?
[00:02:41]
Yeah, I know.
[00:02:42]
But if you don't scroll enough,
[00:02:44]
which I usually unfortunately do,
[00:02:49]
I didn't scroll enough that day, I guess.
[00:02:52]
I think, yeah, the bottom line is,
[00:02:55]
if you blame the cause, not the problem,
[00:02:58]
then it means you're not looking at the root cause.
[00:03:00]
And I think that this is like a cultural value
[00:03:03]
in the Elm community and in the Elm language itself.
[00:03:07]
Sometimes people talk about like,
[00:03:09]
what, you don't trust developers to write code
[00:03:12]
with side effects?
[00:03:17]
I'm glad that Elm has these built in constraints
[00:03:22]
because it allows me to trust myself more
[00:03:25]
because I know I'm working within those constraints.
[00:03:28]
And so CI is an application of that same principle.
[00:03:32]
And it allows you to put in constraints and guarantees
[00:03:37]
because your central source of truth
[00:03:39]
is actually enforcing those things.
[00:03:44]
And if you're finding that issues are coming up,
[00:03:49]
just like instead of blaming the intern and saying,
[00:03:52]
have you heard of the five whys?
[00:03:56]
Go ahead, repeat them.
[00:03:58]
Well, it's actually not a specific set of whys,
[00:04:01]
but the idea of the five whys is that you start with,
[00:04:05]
it's also sometimes called root cause analysis.
[00:04:07]
So the idea is you start with the problem,
[00:04:12]
which is we had a security exploit.
[00:04:15]
So why did we have that security exploit?
[00:04:17]
Why did we have the security exploit?
[00:04:19]
And if you do the one whys,
[00:04:21]
then you end up with,
[00:04:23]
why did we have a security exploit?
[00:04:25]
Because the intern used a weak password.
[00:04:27]
And then you stop there and blame the intern
[00:04:29]
and call it a day.
[00:04:30]
Yeah, perfect.
[00:04:32]
But that's why you do the five whys.
[00:04:34]
Five whys is just an arbitrary number,
[00:04:36]
but the point is you keep going until you can't.
[00:04:41]
Why was the security,
[00:04:44]
why was the intern able to use a weak password?
[00:04:47]
And why was a weak password
[00:04:50]
able to cause a security exploit?
[00:04:53]
So I think that that's an important process for CI
[00:04:56]
to ask yourself,
[00:04:57]
what do we want to make impossible in our code?
[00:05:00]
And when you run into an issue,
[00:05:02]
just like in your Elm code,
[00:05:04]
you run into a problem and you say,
[00:05:09]
how did this type of prevented this bug?
[00:05:11]
That's like a standard part of my workflow
[00:05:14]
working with Elm code.
[00:05:15]
If I find a bug,
[00:05:17]
then my first question is,
[00:05:18]
could I fix this bug
[00:05:20]
through better types and constraints?
[00:05:23]
Yeah, or better abstractions
[00:05:25]
or whatever technique.
[00:05:26]
Right, right, exactly.
[00:05:28]
Maybe an opaque type would have fixed that issue
[00:05:31]
or some sort of constraint.
[00:05:33]
So with CI, it's the same thing.
[00:05:38]
It's those root causes.
[00:05:40]
So what are GitHub Actions?
[00:05:44]
So from my understanding,
[00:05:45]
GitHub Actions is the CI that is rolled out by GitHub.
[00:05:49]
So I used to use Travis before that.
[00:05:54]
And GitHub Actions is just another one
[00:05:56]
that is built into the GitHub platform
[00:06:00]
and that I find pretty easy to use
[00:06:05]
for GitHub Actions configurations files.
[00:06:08]
And that works well.
[00:06:09]
And we will go into how well that works
[00:06:12]
and how that works.
[00:06:14]
Yeah, if you like YAML,
[00:06:16]
you will love GitHub Actions.
[00:06:17]
Yeah, yeah.
[00:06:19]
Yeah.
[00:06:24]
But YAML aside,
[00:06:25]
GitHub Actions are great
[00:06:26]
and it sort of lets you tap into the raw compute power
[00:06:31]
that YAML now gives you.
[00:06:33]
I mean, the free tier is limitless.
[00:06:38]
At least I haven't run up against the limits of it
[00:06:41]
and I use them a lot.
[00:06:42]
I've never looked at the pricing actually.
[00:06:45]
Is it not limitless?
[00:06:47]
I think you get like 10,000 minutes a month
[00:06:51]
for free or something.
[00:06:52]
Yeah, you get a lot.
[00:06:54]
How many runs is that per month?
[00:06:59]
Oh, you get 2,000 per month.
[00:07:01]
I think you get 10,000 per month maybe
[00:07:04]
if you have a pro plan.
[00:07:06]
So I guess I just haven't run...
[00:07:08]
Oh, you get 3,000 per month with pro.
[00:07:10]
Interesting.
[00:07:11]
Well, I haven't run up against the limits of it.
[00:07:13]
I guess my CI jobs are running fast enough
[00:07:18]
and I don't have too many of them to cause issues.
[00:07:20]
Yeah.
[00:07:21]
Well, for my open source projects,
[00:07:23]
they're very fast.
[00:07:28]
I guess you can easily run into those limits
[00:07:33]
when you run full test suites for giant projects,
[00:07:36]
work projects usually.
[00:07:38]
But for open source projects,
[00:07:40]
you don't have to think about the limits.
[00:07:42]
It's a no brainer.
[00:07:43]
And projects like Travis CR
[00:07:46]
are shutting down their operations, I think,
[00:07:48]
because they can't compete with that anymore.
[00:07:50]
If the only thing you're offering is raw compute power,
[00:07:55]
you're not offering GitHub Actions.
[00:07:56]
I think Travis stopped proposing a free tier, actually.
[00:07:59]
That would make sense.
[00:08:00]
Yeah, I've noticed that a lot of the Travis CI jobs
[00:08:03]
in open source Elm packages and tools have started failing.
[00:08:07]
So I had to migrate some tools over to use GitHub Actions.
[00:08:11]
But I've been quite happy with the way that GitHub Actions
[00:08:16]
is set up and it's been a very good experience.
[00:08:19]
It's very powerful, it's fast.
[00:08:24]
It's the best way to run GitHub Actions.
[00:08:27]
Do we have to do any definitions before that?
[00:08:30]
Good question.
[00:08:32]
We defined CI and some of the reasons behind it.
[00:08:35]
We defined GitHub Actions.
[00:08:37]
Are we missing anything?
[00:08:38]
What does CI stand for?
[00:08:40]
Do you know the etymology of CI?
[00:08:44]
Continuous integration?
[00:08:45]
It stands for continuous integration.
[00:08:47]
And I believe the term was first coined
[00:08:52]
and actually, this is a bit of a tangent,
[00:08:56]
but continuous integration was initially a concept
[00:09:01]
from extreme programming where you're actually
[00:09:04]
not using long lived branches.
[00:09:06]
So you don't have your feature branch
[00:09:09]
that is drifting away from the rest of the code
[00:09:12]
that's getting merged in for a month
[00:09:14]
and then the feature is done and then it gets merged in
[00:09:19]
and you're sort of rapidly iterating with
[00:09:22]
trunk based development or short lived branches
[00:09:26]
that don't live for longer than hours or a day.
[00:09:29]
But the basic idea is it's a feedback mechanism.
[00:09:34]
And this is one of the other principles
[00:09:37]
of continuous integration that sometimes gets overlooked
[00:09:40]
is it is about that source of truth
[00:09:43]
that you enforce your constraints
[00:09:48]
and also are speeding up your feedback loop.
[00:09:51]
So instead of finding out about code not being formatted
[00:09:55]
or some dead code sitting around a month later
[00:09:59]
when you next get to it,
[00:10:01]
you have to address those things
[00:10:02]
and build in quality as you work.
[00:10:05]
So it shortens the feedback loop.
[00:10:07]
That is my understanding from Agile in general.
[00:10:10]
You can say whatever it is,
[00:10:12]
but I feel like it's just short feedback loops
[00:10:17]
of product design and product development.
[00:10:20]
Right. People get fixated on standup meetings
[00:10:24]
and estimation or not doing estimation or doing sprints
[00:10:28]
or not doing sprints and poll based and Kanban.
[00:10:31]
But it's actually about feedbacks about the dailies.
[00:10:36]
So you do the daily, then you do feedback on the daily,
[00:10:39]
then you do feedback on the feedback of the daily.
[00:10:41]
That's how it works, right?
[00:10:46]
More meetings. More meetings is the answer.
[00:10:49]
Answer that question.
[00:10:51]
And then feedback is on the meetings.
[00:10:53]
The idea of extreme development is really cool actually.
[00:10:56]
It's this idea that Kent Beck described
[00:10:59]
having a knob on a guitar amp or a stereo or something.
[00:11:04]
And the knob is, you just take all the knobs
[00:11:08]
and you turn them up to 11.
[00:11:13]
His idea of you take the things that are working,
[00:11:16]
short feedback loops and collaborating with people
[00:11:19]
and those sorts of ideas.
[00:11:22]
So pair programming is just taking this idea
[00:11:24]
of collaborating with people and you say,
[00:11:26]
oh, we like that.
[00:11:27]
Well, what if we did more of it?
[00:11:29]
And what if we did the most we could of that?
[00:11:31]
And like, oh, feedback loops are nice.
[00:11:34]
Well, what if every code we wrote
[00:11:36]
was starting with a failing test?
[00:11:41]
Every time you checked in code,
[00:11:43]
it gave you feedback to make sure everything is good.
[00:11:45]
So mob programming is like pair programming
[00:11:48]
but dialed from 2 to 11.
[00:11:50]
So you have 11 people.
[00:11:52]
Yeah, it's taking something that was dialed up to 10 or 11
[00:11:56]
to get pair programming.
[00:11:57]
And then it's dialing that up to 11.
[00:12:02]
All right.
[00:12:03]
So I think that's a good definition of CI.
[00:12:08]
Those are core definitions here.
[00:12:10]
I think then you also have CD, continuous development,
[00:12:14]
which is just continuation of that idea, I guess.
[00:12:18]
Well, there are actually two.
[00:12:20]
CD is a bit ambiguous.
[00:12:21]
There's continuous deployment
[00:12:23]
and there's continuous delivery
[00:12:25]
and there are all sorts of nuances with those terms.
[00:12:27]
Oh, I would have expected them to be the same thing.
[00:12:30]
All right.
[00:12:31]
There are some subtle distinctions,
[00:12:36]
but I would say that you're not delaying deployments
[00:12:39]
until your release is ready.
[00:12:42]
You're getting code out there
[00:12:44]
and using techniques like feature flags
[00:12:46]
to continuously have the latest code out there.
[00:12:49]
And it's just another turning the dial up to 11
[00:12:52]
to get better feedback
[00:12:54]
because you're not delaying
[00:12:56]
when you find out if there's an issue with your code.
[00:12:59]
If you deploy a year's worth of code at once,
[00:13:04]
you're going to get a lot of speed
[00:13:06]
because you can end up with very large problems
[00:13:08]
and problems that you're building on top of.
[00:13:10]
Whereas if you deploy every 30 minutes,
[00:13:14]
then you may occasionally deliver a small issue,
[00:13:18]
but it's a tiny issue compared to that yearly release.
[00:13:23]
And also, it forces you to build in feedback mechanisms
[00:13:27]
where you're finding out you're doing,
[00:13:32]
program tests and tools like that too,
[00:13:35]
so that you can safely release that frequently
[00:13:38]
without long manual testing cycles and things like that.
[00:13:42]
So it gets you to automate quality more.
[00:13:45]
Yeah, and then you usually also try to shorten
[00:13:48]
the execution times of your tests and deployments.
[00:13:51]
If you only deploy once a year,
[00:13:53]
then I guess it would be fine
[00:13:58]
to take four hours, maybe three days to prepare.
[00:14:01]
But if you try to deploy on every commit
[00:14:04]
on the main branch, that can't take three days.
[00:14:07]
That has to take five minutes at most.
[00:14:10]
Yeah, exactly.
[00:14:12]
So when you do that, you put in the effort
[00:14:15]
into making a good deployment experience
[00:14:18]
and a good experience in general, I guess, too.
[00:14:22]
Yeah, exactly. It's sort of a forcing function.
[00:14:27]
Do it more often.
[00:14:29]
Because if you have painful releases,
[00:14:33]
then you do your yearly releases.
[00:14:36]
It's full of manual scripts in Google Docs
[00:14:39]
that you're running through and checklists with team members.
[00:14:42]
And things fail, and you have to address them.
[00:14:45]
And you have to tweak the manual process.
[00:14:47]
Some things aren't documented in the scripts.
[00:14:50]
But you're doing it once a year.
[00:14:55]
You tend to want to do it less frequently
[00:14:57]
when something is painful.
[00:14:59]
But actually, if you want to address the problem,
[00:15:01]
doing it more often is going to be a forcing function
[00:15:04]
that forces you to address those problems.
[00:15:07]
Yeah, do it more often
[00:15:09]
so that you will find a way not to do it anymore.
[00:15:11]
Right, yes.
[00:15:13]
In that way, in that painful way.
[00:15:16]
And that's the definition of CD,
[00:15:18]
whatever it might be.
[00:15:23]
So shall we talk a little bit about some of the specific syntax
[00:15:27]
that GitHub Actions give you?
[00:15:29]
Yeah, sure.
[00:15:30]
I think some of the origins of GitHub Actions
[00:15:32]
were kind of having specific hooks for GitHub events.
[00:15:37]
So if somebody comments on an issue,
[00:15:39]
or if somebody opens an issue,
[00:15:42]
then you could have a bot that says,
[00:15:45]
oh, thanks for opening an issue.
[00:15:47]
Here are some guidelines.
[00:15:52]
The functionality still exists.
[00:15:54]
So you can have event triggers
[00:15:56]
where you say,
[00:15:58]
I want to do this on new issue.
[00:16:02]
Another example would just be run tests
[00:16:05]
whenever you get a pull request,
[00:16:07]
something like that.
[00:16:08]
Yeah, exactly.
[00:16:09]
And I think that most people
[00:16:11]
who are familiar with GitHub Actions
[00:16:13]
are probably going to be most familiar
[00:16:16]
with just that standard on pull request
[00:16:21]
on new commit on the main branch.
[00:16:24]
That is all I know, actually.
[00:16:26]
And you can get a lot of mileage with just that.
[00:16:29]
You can also trigger jobs on a schedule.
[00:16:32]
It's on schedule,
[00:16:34]
and it just uses cron syntax.
[00:16:36]
And by the way,
[00:16:38]
if you're using cron syntax,
[00:16:40]
there's a site, I think it's cron.guru.
[00:16:44]
And once you use it,
[00:16:49]
if you're wondering,
[00:16:50]
how do I run something every morning at this time
[00:16:54]
and finding stack overflow answers,
[00:16:56]
you'll just open that up.
[00:16:57]
crontabguru.
[00:16:58]
crontabguru.
[00:17:00]
crontab.guru,
[00:17:01]
for those who are looking it up right now.
[00:17:03]
Oh, okay.
[00:17:05]
Yeah, makes me think of regex101.com.
[00:17:09]
Also very nice.
[00:17:10]
So you can run things on a schedule.
[00:17:13]
You can run things on a schedule.
[00:17:18]
We don't have that functionality at the moment,
[00:17:20]
so our Elm Radio episodes are released
[00:17:22]
with an on schedule trigger from a GitHub action.
[00:17:27]
So we have a GitHub action
[00:17:30]
that calls the API from NetDefy to say,
[00:17:33]
please deploy.
[00:17:34]
Yeah, it's actually just a web hook.
[00:17:36]
You just hit a URL,
[00:17:37]
and it causes a deployment.
[00:17:39]
And there's also a lesser known feature in GitHub actions
[00:17:43]
where you can use something called Workflow Dispatch.
[00:17:48]
It's in the show notes.
[00:17:49]
And that allows you to click a button in the UI
[00:17:52]
for GitHub actions and trigger something,
[00:17:54]
and you can actually use different inputs.
[00:17:57]
So you can have different input fields
[00:18:00]
and use those in your GitHub action job.
[00:18:04]
So I could have a button that says,
[00:18:07]
run the very long end to end tests right now.
[00:18:11]
Okay, cool.
[00:18:12]
Or you could have,
[00:18:17]
because this sounds kind of cool,
[00:18:19]
I could imagine having a button that says,
[00:18:21]
hey, I'm ready for a new release of this Elm package.
[00:18:26]
And you click a button,
[00:18:27]
and you could have it actually run Elm bump.
[00:18:31]
Oh, yeah, I like that.
[00:18:33]
That could be kind of cool.
[00:18:35]
So I mean, it's one of those things
[00:18:37]
where GitHub actions gives you
[00:18:39]
a lot of these building blocks,
[00:18:41]
and you sort of get creative
[00:18:46]
with the building blocks.
[00:18:47]
But the building blocks,
[00:18:49]
I mean, just being able to take user input
[00:18:51]
and run a workflow with those input fields,
[00:18:54]
there's so much you can do with that.
[00:18:55]
You can get really creative.
[00:18:56]
Maybe I shouldn't talk about this right now,
[00:18:58]
but if we have the button to bump the version
[00:19:01]
and then publish,
[00:19:02]
could anyone do that on my repo?
[00:19:05]
Or only me and the maintainers?
[00:19:07]
Or can I say, who has access to that button?
[00:19:12]
I have a great discourse thread
[00:19:14]
about this on the GitHub discourse.
[00:19:17]
So you can enforce that.
[00:19:20]
You can do github.actor
[00:19:23]
to find out who triggered the workflow
[00:19:25]
using that dispatch action.
[00:19:28]
And what's the intern?
[00:19:30]
Right, if it's the intern,
[00:19:32]
then don't do it.
[00:19:33]
No.
[00:19:35]
No, make your CI process robust enough
[00:19:40]
to be able to do that.
[00:19:41]
So this gets at one of the core concepts,
[00:19:45]
I think, which is that
[00:19:46]
just like you can have your server
[00:19:50]
enforce certain things.
[00:19:52]
So you have to validate something
[00:19:54]
before you write it to the database.
[00:19:55]
You have to authenticate somebody
[00:19:57]
before you give them some information
[00:19:59]
or let them perform some task.
[00:20:01]
It's the same with a CI.
[00:20:02]
So you can build in
[00:20:04]
some of these permissions into the CI.
[00:20:09]
It automatically runs Elm Publish for you
[00:20:12]
because there's this sort of dance
[00:20:13]
that you do when you publish an Elm package.
[00:20:15]
You have to create a tag,
[00:20:18]
and you want to do that after your CI passes
[00:20:22]
because you want Elm Review to check out fine,
[00:20:25]
and you want Elm Tests to say
[00:20:27]
everything's good in Elm format.
[00:20:29]
You wouldn't want to run Elm Publish
[00:20:31]
and push and then get a red CI back
[00:20:36]
that would be a bummer.
[00:20:38]
So this is the cool thing,
[00:20:40]
is that can anybody do an Elm Publish?
[00:20:43]
Well, it's built into the CI,
[00:20:45]
so when your main branch gets a release
[00:20:49]
that has a bumped Elm version,
[00:20:52]
it automatically publishes.
[00:20:53]
So anybody who has permission
[00:20:56]
to change the version in your Elm.json
[00:20:59]
for a package has permission to publish,
[00:21:04]
and if somebody has right access,
[00:21:06]
then they have publish access.
[00:21:08]
I imagine that in some companies,
[00:21:10]
like very large companies,
[00:21:11]
a lot of people can merge into master,
[00:21:13]
but then more select group can publish, can release.
[00:21:17]
So maybe it makes sense for smaller teams
[00:21:21]
or smaller organizations,
[00:21:23]
but not for larger ones.
[00:21:25]
I'm a little hesitant
[00:21:27]
with giving people special access.
[00:21:32]
I'm more on making it safe for anybody to do so,
[00:21:36]
but that's just my inclination.
[00:21:38]
But people can figure out
[00:21:40]
whatever sort of permissions schema
[00:21:43]
that they want to there.
[00:21:44]
But this is one of the cool things in CI
[00:21:46]
is that you can build those things into the CI.
[00:21:48]
So if somebody makes a pull request
[00:21:51]
that bumps the Elm version,
[00:21:53]
when you merge that,
[00:21:55]
then a new version goes out.
[00:21:56]
But if they don't have permission
[00:22:01]
to have guards that functionality,
[00:22:03]
and so you have these sort of built in permissions
[00:22:06]
and things that you can enforce
[00:22:07]
through your GitHub action.
[00:22:09]
So that's kind of a cool thing.
[00:22:10]
I think that in your GitHub action,
[00:22:12]
because it's under your name,
[00:22:14]
you have a specific guard
[00:22:15]
that this only runs on the main branch, right?
[00:22:18]
Yes.
[00:22:19]
It only runs on the default branch,
[00:22:21]
whether that's main or master,
[00:22:23]
or whatever your default branch
[00:22:24]
is configured to be.
[00:22:25]
It also only runs after version 1.0.0.
[00:22:30]
So it requires you to manually say,
[00:22:32]
hey, I'm ready to make this package public,
[00:22:35]
because if you set up that action
[00:22:37]
and it accidentally 1.0 something for you,
[00:22:40]
that would be unfortunate.
[00:22:42]
So it will never do that.
[00:22:44]
But that could be interesting.
[00:22:45]
You could have a button that says,
[00:22:48]
do the initial release,
[00:22:49]
and then remove the button from the GitHub actions,
[00:22:52]
and then let the Elm published action
[00:22:57]
be a success for the other releases.
[00:23:00]
The button is not something you can configure
[00:23:02]
based on a condition, I think.
[00:23:04]
The button is something you have to build into your...
[00:23:06]
No, but you can make the action
[00:23:09]
change the GitHub workflow configuration.
[00:23:13]
I don't know.
[00:23:14]
That's starting to get...
[00:23:15]
If something gets too sophisticated
[00:23:18]
and clever like that,
[00:23:19]
I start to worry that...
[00:23:21]
I start to trust it less.
[00:23:26]
If you have a new package command
[00:23:28]
that creates a new project
[00:23:30]
and adds GitHub action CI,
[00:23:32]
well, maybe that could be interesting
[00:23:34]
for those people,
[00:23:35]
even though it will feel like magic,
[00:23:37]
like, hey, I had a button.
[00:23:40]
Where did it go?
[00:23:42]
But yeah, I agree that it's pushing
[00:23:45]
the envelope a little bit too far.
[00:23:47]
It seems like performing some side effects
[00:23:52]
on the function there.
[00:23:55]
I really like the idea, though.
[00:23:59]
It's fun.
[00:24:00]
Maybe for Halloween you can enable that,
[00:24:02]
because it's a little spooky.
[00:24:06]
We should mention also that
[00:24:08]
this Elm publish action that we're talking about
[00:24:11]
is sort of another special feature
[00:24:14]
that GitHub actions has,
[00:24:16]
which is that you can package up JavaScript code
[00:24:21]
and so the interface to it is
[00:24:23]
you can provide inputs that you pass in through your YAML.
[00:24:27]
So you wire in this action,
[00:24:30]
you say it uses
[00:24:32]
dylan kerns slash elm publish action
[00:24:34]
and then add a specific version,
[00:24:36]
and then you give it,
[00:24:38]
I think it's a with,
[00:24:40]
with a list of the inputs,
[00:24:42]
and you have to pass in things like...
[00:24:44]
So you can pull secrets.
[00:24:45]
Secrets is another feature
[00:24:50]
that creates to give permission to do certain things,
[00:24:52]
like elm publish action needs to create a git tag.
[00:24:55]
And then it passes those things in,
[00:24:58]
and that's published in the GitHub marketplace.
[00:25:02]
So people can install that NPM package
[00:25:05]
and run it as a GitHub action.
[00:25:07]
So you don't have to manually NPM install it
[00:25:09]
or anything like that.
[00:25:10]
You just reference it in your workflow.
[00:25:12]
Okay, does it only work for JavaScript packages?
[00:25:17]
And you can also just have a Docker image.
[00:25:20]
You can actually run things with Docker.
[00:25:23]
So you can do anything you could imagine
[00:25:26]
since you can just use Docker,
[00:25:28]
but JavaScript is the most common way I see of doing things
[00:25:32]
with sort of front end focused tools,
[00:25:34]
like if you're running prettier or something like that.
[00:25:37]
So there was a, Phil Sparks created this tool
[00:25:41]
for running elm review and giving you feedback
[00:25:46]
which is pretty cool.
[00:25:47]
Yeah, so you make a pull request
[00:25:49]
and then it adds annotations
[00:25:51]
wherever elm review reports things.
[00:25:53]
So if you have something that is unused,
[00:25:55]
it adds an annotation,
[00:25:57]
so kind of like a comment,
[00:25:59]
by the elm review action bots,
[00:26:02]
or I don't know what that is called.
[00:26:05]
That's incredible.
[00:26:06]
That's huge.
[00:26:07]
And that's the kind of thing
[00:26:09]
that I love about GitHub actions
[00:26:10]
is it's giving you this sort of core platform
[00:26:15]
pointing elm review rules,
[00:26:18]
pointing out the line where there's a problem
[00:26:20]
with the comment is huge.
[00:26:23]
Yeah, and there's also another one
[00:26:25]
that Phil Sparks made,
[00:26:27]
which is not published
[00:26:29]
because it is more of a succession
[00:26:31]
of different actions,
[00:26:33]
which is to run elm review, fix all the issues,
[00:26:37]
and then make a pull request.
[00:26:39]
Oh, cool, cool, cool, yes.
[00:26:44]
Well, for the ones that can be fixed, obviously.
[00:26:47]
Right, the ones that can be auto fixed
[00:26:49]
and then that may result in a green build
[00:26:51]
once you merge that.
[00:26:52]
Hopefully, yeah.
[00:26:54]
That's the feeling I get for most issues,
[00:26:57]
is things are just unused
[00:26:59]
or something that is easy to fix
[00:27:01]
by the elm review tool anyway.
[00:27:04]
Right, and then the intern
[00:27:05]
doesn't even have to install elm review.
[00:27:07]
Yeah, exactly.
[00:27:12]
If you install elm and elm review, who cares?
[00:27:15]
Right, right.
[00:27:17]
If there's a compiler error,
[00:27:19]
maybe it'll use machine learning
[00:27:20]
to automatically fix the compiler error for them.
[00:27:24]
Maybe we should tell the intern
[00:27:25]
not to use Notepad to edit elm code and not to...
[00:27:32]
Yeah.
[00:27:33]
No, we love interns.
[00:27:35]
You're great interns.
[00:27:40]
Then we put the blame on you.
[00:27:42]
Yeah, it's a good scapegoat.
[00:27:44]
That's what we should call them, scapegoats.
[00:27:46]
Hey, we have a new scapegoat coming on this week.
[00:27:51]
Let's use the one whys to figure out the problem.
[00:27:55]
Oh, that's terrible.
[00:27:59]
So for this elm review GitHub action you're in,
[00:28:02]
would you say that that would replace
[00:28:07]
the build review in the CI?
[00:28:09]
Probably would, right?
[00:28:10]
Yes, as long as the CI stops
[00:28:12]
whenever there's an elm review error.
[00:28:15]
If it makes the build be green, then no,
[00:28:18]
that's not enough.
[00:28:19]
But I think it does, so yeah.
[00:28:21]
Yeah, so that gets into an interesting space
[00:28:23]
that I sometimes wonder about,
[00:28:25]
which is like, what's the relationship
[00:28:27]
between the checks that you have
[00:28:30]
in your local environment versus the CI checks, right?
[00:28:35]
We say that you want this source of truth
[00:28:40]
of the CI, right?
[00:28:42]
But that doesn't mean that you want
[00:28:44]
to ever find out about errors there.
[00:28:46]
But you want to know that if for some reason
[00:28:49]
something passed through, that it would be caught there.
[00:28:53]
But you want to catch it sooner if you can.
[00:28:55]
So you want to run your unit tests
[00:29:00]
and your end to end tests and all these things in your CI,
[00:29:05]
and you want to know the source of truth,
[00:29:07]
and you don't want to go live and do a deployment
[00:29:10]
if those things are failing.
[00:29:11]
But what's the relationship between that set of checks
[00:29:15]
that you do in your CI and the set of checks
[00:29:17]
that you do locally, and how you do them?
[00:29:19]
Do you encapsulate them in the same scripts?
[00:29:21]
I noticed that when you do elm review new package,
[00:29:26]
which is like a little init helper
[00:29:28]
that you have to create a folder
[00:29:33]
to run all, which is like a little npm package.
[00:29:37]
And you basically just run that in the CI
[00:29:40]
where the check does, it runs the unit tests,
[00:29:43]
it runs elm review, it runs all these checks.
[00:29:45]
Yeah, just for those who don't know npm run all,
[00:29:48]
so in npm scripts, usually people do this,
[00:29:52]
then the end sign, I don't know, what's the name?
[00:29:56]
Double ampersand?
[00:30:01]
You can do that and so forth,
[00:30:03]
but that doesn't work on Windows,
[00:30:05]
so that's why I used npm run all
[00:30:08]
to run all of them together in sequence,
[00:30:11]
just for it to work on Windows.
[00:30:14]
Yeah, I think you can even use
[00:30:16]
a glob style syntax with npm run all.
[00:30:19]
I think you can say,
[00:30:21]
test colon star.
[00:30:24]
Yeah, you don't like the implicitness of it.
[00:30:29]
And for people who don't know npm run all,
[00:30:32]
which I think is most people,
[00:30:34]
even I don't really like it that particularly,
[00:30:37]
if you use that and use like test colon star,
[00:30:41]
like you will know where test dot elm review will be used,
[00:30:46]
or test colon elm review.
[00:30:48]
So I just want to be able to find it.
[00:30:53]
Right, because you want to run elm review
[00:30:58]
and test colon elm review.
[00:31:01]
Yeah, also.
[00:31:02]
You would want to find out that elm make fails,
[00:31:05]
you'd prefer to have elm make's error message
[00:31:09]
take precedence and then fail the rest of the build.
[00:31:11]
Yeah, it makes sense.
[00:31:13]
But as to what do I run in CI,
[00:31:16]
I really like having the CI do the same thing
[00:31:19]
as what I would do locally.
[00:31:22]
Or, instead of another way,
[00:31:27]
whenever I push something to get up
[00:31:31]
and I make a pull request and then it fails,
[00:31:34]
most of the time I want it to be because I was lazy
[00:31:36]
and I forgot to run tests.
[00:31:38]
But if I run tests, I want to succeed in CI.
[00:31:41]
Right, if you have a surprise in CI,
[00:31:44]
it means something went wrong.
[00:31:46]
Yeah, the obvious exception is when for very long tests,
[00:31:49]
like end to end tests,
[00:31:51]
if they take a long time, let the CI do it.
[00:31:56]
Right, because, I mean, but sometimes that is unavoidable
[00:31:59]
and sometimes you, maybe you have some smoke tests
[00:32:01]
that before something goes live to production,
[00:32:04]
you need to run and they're just going to be long running tests
[00:32:07]
and there's really nothing you can do about it.
[00:32:09]
And in cases like that,
[00:32:10]
sometimes you do have to make that trade off to say,
[00:32:13]
we know that any code that goes to production
[00:32:15]
passes these tests, but they just are expensive tests
[00:32:19]
that we're not going to run locally every time.
[00:32:24]
It's up to you to make sure that it often won't break
[00:32:28]
in end to end tests.
[00:32:30]
So if you do something wrong,
[00:32:32]
maybe add an Elm review rule that says you shouldn't do this.
[00:32:36]
That would prevent something to break in the end to end test
[00:32:40]
or something.
[00:32:42]
That's obviously not possible because end to end tests
[00:32:44]
have their own use and they're very useful.
[00:32:47]
But yeah, you want to push things to the fast thing
[00:32:52]
that's possible.
[00:32:53]
Right, right.
[00:32:54]
Yeah, the sooner you can find out the better.
[00:32:56]
Ideally, there are kind of like three different stages
[00:32:59]
in this actually.
[00:33:00]
We've talked about like, you know,
[00:33:02]
the CI running things before deploy.
[00:33:04]
We've talked about running these things locally,
[00:33:07]
but we haven't talked about the local iterations
[00:33:10]
and development.
[00:33:11]
So there's sort of like a step before you commit and push
[00:33:15]
where you run things locally.
[00:33:20]
It's sort of a different workflow because you're running
[00:33:23]
most of these things in watch tasks.
[00:33:25]
So you're running, you know,
[00:33:27]
elm test dash dash watch.
[00:33:29]
You're running elm review dash dash watch or dash dash fix dash all dash dash watch.
[00:33:35]
How's that for podcast material, Jeroen?
[00:33:37]
I love it.
[00:33:39]
Great radio here.
[00:33:40]
We haven't made it with an Elm review episode in a while.
[00:33:45]
So yeah, I mean,
[00:33:47]
the awkward thing about it is there's no way to just say like,
[00:33:51]
okay, there's no declarative way where you say,
[00:33:53]
here are all the things that I test when I run my CI job.
[00:33:58]
And now do all of those things in their watch mode.
[00:34:01]
There's no way to do that.
[00:34:02]
You just sort of like manually keep them in sync,
[00:34:05]
which, you know, as people who are obsessive about automating everything
[00:34:09]
and making everything safe, it hurts our brains,
[00:34:14]
I guess there are git commit hooks, which are kind of in between.
[00:34:19]
Yeah, but that's not the watch mode, right?
[00:34:21]
That's like,
[00:34:22]
well, if you commit often, then kind of.
[00:34:26]
Yeah.
[00:34:27]
Those are way too long, I think.
[00:34:30]
Like if you run your whole test suite every time you commit
[00:34:33]
and you try to commit small things as we both like to do,
[00:34:37]
then I don't think the experience is great.
[00:34:42]
I don't like git commit hooks at all.
[00:34:43]
Yeah, I don't like git commit hooks.
[00:34:45]
And I mean, the problem with git commit hooks is that they're not shared,
[00:34:51]
they're individual, and there are some tools that sort of try to help with this,
[00:34:55]
but they're not, you certainly can't treat it as an assumption that they're run,
[00:35:00]
but the CI you can treat as an assumption.
[00:35:02]
So they certainly are not a replacement for CI.
[00:35:04]
Yeah, I actually joined a company which were using git commit hooks pretty heavily
[00:35:09]
and they didn't enforce ESLint, so a linting tool in CI,
[00:35:15]
only during the git commit hook phase.
[00:35:18]
And well, no surprise, there were a lot of issues
[00:35:22]
and no one was noticing them because no one was looking at them.
[00:35:26]
It's a bummer because then, you know,
[00:35:28]
somebody goes and they want to enforce something with a linter or with whatever tool,
[00:35:33]
and now they're responsible for fixing all the things
[00:35:38]
and they have a clean slate.
[00:35:39]
And you know, as opposed to the person who was working on something
[00:35:42]
and could have addressed it right as they were introducing that issue,
[00:35:45]
they could just turn around and fix it.
[00:35:47]
They have the context.
[00:35:49]
Well, actually, I have to precise something.
[00:35:51]
They were running ESLint, but only on the diff difference between what they did
[00:35:55]
and what was on master commit before.
[00:36:00]
So that's why a lot of things accumulated.
[00:36:05]
They weren't checking what was there before already.
[00:36:08]
Because you can actually write,
[00:36:10]
if you're able to get a certain build through, then now you're good,
[00:36:15]
even if that build was red potentially, right?
[00:36:19]
They were doing that locally with git commit hooks,
[00:36:22]
but in the CI, they were not rerunning ESLint at all.
[00:36:27]
So a lot of circumstances that led to that.
[00:36:32]
Interesting.
[00:36:33]
Yeah, I think where I come down with this stuff is ultimately like,
[00:36:37]
as much as I would love there to be an elegant way
[00:36:41]
to just sort of keep all these things in sync,
[00:36:43]
I think you have to sort of treat it as independent, but related things
[00:36:48]
that you have to maintain independently,
[00:36:51]
but you have to try to make sure that conceptually,
[00:36:56]
you're enforcing everything very robustly at the CI level.
[00:37:02]
You're trying to get as close as possible to knowing that your CI is going to pass
[00:37:07]
when you run your whatever you do pre commit,
[00:37:10]
whether it's running an NPM script or a bash script or a make file
[00:37:15]
or a pre commit hook or whatever, however you do that,
[00:37:19]
you want to get as close as possible to being confident that the CI will pass.
[00:37:24]
In some cases, not exactly,
[00:37:26]
because you may have long running CI tasks.
[00:37:28]
And then for your local watch mode, it's sort of its own thing too,
[00:37:32]
where there are certain things you want to run in a watch loop.
[00:37:35]
Maybe you don't want to run your end to end tests in a watch loop.
[00:37:38]
You probably don't,
[00:37:40]
but you probably do want to run your unit tests in a watch loop.
[00:37:43]
Yeah.
[00:37:44]
Maybe you do.
[00:37:45]
Even on review, I sometimes run it in watch modes when I'm developing,
[00:37:50]
but I'm not looking at it all that often.
[00:37:53]
Yeah.
[00:37:54]
I really like the experience of refactoring with Elm review,
[00:37:59]
watch fix all in the background,
[00:38:02]
because you start deleting instances where you're calling a function
[00:38:05]
and move something over to a new function you're using
[00:38:09]
or a new way you're writing some code.
[00:38:11]
And then all the old code just starts disappearing.
[00:38:13]
Beautiful, isn't it?
[00:38:14]
It's great.
[00:38:19]
You can start writing codes and then gradually move those
[00:38:22]
and then remove the old ones.
[00:38:24]
And Elm reviews just gives a great experience for doing that.
[00:38:28]
But you also want to know when that happens
[00:38:30]
so you can rename the old one, do a better name.
[00:38:35]
I'll duplicate by adding just two.
[00:38:38]
So I have new function and then I have a view two function
[00:38:42]
because I hate to replace the view function.
[00:38:47]
It's not fixed yet because you have unused code at first, right?
[00:38:51]
Well, the view function will be used.
[00:38:53]
And once I will migrate things, it will become unused.
[00:38:57]
Did it get you?
[00:38:58]
Well, isn't some of the code dead?
[00:39:00]
Oh, yeah.
[00:39:01]
You mean when you rename things?
[00:39:03]
Or if you're introducing a new function.
[00:39:05]
Yeah, I'm duplicating the code.
[00:39:07]
Right.
[00:39:08]
So once it's duplicated, it's dead
[00:39:10]
and you can't run Elm review dash dash fix all.
[00:39:15]
When you create it.
[00:39:17]
Yeah.
[00:39:18]
So you don't want to delete it whenever you create it.
[00:39:22]
Right.
[00:39:23]
So you sort of have to have a custom workflow.
[00:39:25]
You can't just assume that you're going to run these things.
[00:39:28]
Even if you do have that fix all enabled in your CI
[00:39:32]
where it's automatically going to fix things when you push,
[00:39:34]
it's different in the lifecycle of your local development
[00:39:37]
where you may want to hold off on some of those things
[00:39:39]
during your development cycle.
[00:39:44]
I think you have to treat them as three different things.
[00:39:47]
At least three, I think.
[00:39:49]
At least three different things.
[00:39:50]
But just having that mental model hopefully helps.
[00:39:53]
So to go back to what should we run in CI,
[00:39:56]
I usually run NPM tests and maybe additional things.
[00:39:59]
So we talked about the Elm review action,
[00:40:03]
which adds annotations about things that went wrong.
[00:40:07]
And I would probably run that next to it.
[00:40:12]
I've done Elm review twice.
[00:40:14]
Really?
[00:40:15]
Yeah.
[00:40:16]
Just because you would try to encapsulate
[00:40:18]
your local scripts that mirror your CI?
[00:40:21]
Yeah.
[00:40:22]
And as long as they're both really fast,
[00:40:25]
it's not worth optimizing.
[00:40:27]
Just run it twice.
[00:40:28]
If you have a very long setup,
[00:40:30]
then I'm guessing the Elm build step will not be the longest one.
[00:40:35]
At my work, we have plenty of GitHub jobs,
[00:40:40]
and the Elm ones are the fastest ones.
[00:40:44]
The backend takes a lot longer.
[00:40:47]
So I couldn't imagine just having one additional job running Elm review,
[00:40:52]
which would take like 30 seconds maybe at most
[00:40:55]
with the whole setup and stuff.
[00:40:57]
So it's fine, I'd say.
[00:40:59]
I would tend to just have separate scripts for that.
[00:41:02]
But it's, yeah,
[00:41:03]
I mean, unfortunately, there's no silver bullet here.
[00:41:08]
They picked their poison a little bit.
[00:41:10]
Yeah, because in my case,
[00:41:12]
you would double some of the work,
[00:41:14]
and in your case, you could have the problem
[00:41:17]
that they're not in sync anymore.
[00:41:19]
Yep.
[00:41:20]
So let's talk about some of the other cool workflows
[00:41:22]
that you can do with GitHub actions in an Elm project.
[00:41:26]
So of course, you should run your tests,
[00:41:29]
you should run the compiler,
[00:41:31]
you should run Elm format verify and Elm review.
[00:41:36]
There's a cool thing that's not directly using a GitHub action.
[00:41:40]
But I wrote a blog post a little while back
[00:41:43]
about keeping your Elm dependencies current using Dependabot.
[00:41:47]
And I think this is like maybe a lesser known feature,
[00:41:50]
but people might know Dependabot as something
[00:41:53]
that updates your NPM dependencies
[00:41:56]
with like 10 million pull requests every day.
[00:42:01]
Elm being for vulnerabilities.
[00:42:04]
Exactly.
[00:42:05]
It's like you'll never get to zero.
[00:42:08]
It's just not going to happen.
[00:42:10]
But it also works with Elm dependencies,
[00:42:12]
which don't have 10 million
[00:42:15]
security vulnerability updates per day
[00:42:17]
that might have zero security vulnerability updates ever.
[00:42:22]
One reason might also be
[00:42:24]
because no one actually cares about Elm vulnerabilities.
[00:42:29]
I mean, there's a lot of people who,
[00:42:32]
well, I guess it's NPM who checks security issues.
[00:42:36]
But no one does that for Elm,
[00:42:38]
at least for now, until we find attack vectors.
[00:42:43]
That's true.
[00:42:44]
There could be some sitting out there
[00:42:45]
that we don't know about.
[00:42:46]
I think it would be pretty easy to make one.
[00:42:50]
Like just run one HTTP request
[00:42:53]
that does something that you don't want it to do.
[00:42:58]
Yeah, sure.
[00:42:59]
But as long as that is part of your API
[00:43:03]
and people use it, then you have a problem.
[00:43:05]
But it is really, really edgy.
[00:43:09]
That doesn't really happen at all.
[00:43:11]
Don't encourage the hackers you're in.
[00:43:13]
You're just trying to give them a challenge.
[00:43:14]
Yeah, so that's kind of a cool workflow.
[00:43:17]
You can actually point Dependabot to your Elm projects.
[00:43:20]
And it makes a pull request.
[00:43:22]
It shows you the relevant change log
[00:43:27]
that you're updating to.
[00:43:28]
That's a cool workflow.
[00:43:30]
So what you mean is you could do that
[00:43:31]
with GitHub Actions also?
[00:43:33]
Well, those are the kinds of workflows
[00:43:36]
you can get into your CI with GitHub.
[00:43:39]
What are some other cool workflows?
[00:43:41]
You've got some interesting workflows
[00:43:44]
that you do for the Elm Review New Package CI.
[00:43:48]
Yeah, so in Elm Review New Package,
[00:43:50]
I'm creating boilerplates
[00:43:55]
for Elm Review rules.
[00:43:56]
So there's a few things that we can check
[00:43:58]
with Elm Test and with Elm Review,
[00:44:00]
and I run those in the default settings.
[00:44:03]
And there's also some checks that I want to run
[00:44:05]
only when people are attempting to publish.
[00:44:09]
So there's a Preview folder,
[00:44:11]
which people can use to run the Elm Review rules
[00:44:14]
before they're published.
[00:44:15]
And there's an Example folder,
[00:44:17]
which uses the latest published version.
[00:44:22]
So you can update the Example folder
[00:44:24]
with whatever is in the Preview folder.
[00:44:27]
So if you have a new rule,
[00:44:29]
then your example is now up to date.
[00:44:31]
And that is a test that I only run
[00:44:34]
right before publishing,
[00:44:36]
so right before running Elm Publish Action.
[00:44:39]
So that way, you bump your version,
[00:44:42]
you push, it runs that test,
[00:44:45]
and if you forgot to update the examples,
[00:44:50]
you have a helpful script to update the examples,
[00:44:54]
but they need to be run before publishing.
[00:44:57]
I try to publish the experience here and there.
[00:45:00]
Right.
[00:45:01]
It really makes a difference.
[00:45:02]
I mean, just kind of having those checks
[00:45:04]
to make sure everything is polished before it goes out,
[00:45:09]
like CI is so good for that.
[00:45:11]
And you can get so creative too.
[00:45:14]
So like, I think it's really good to get creative
[00:45:19]
and force using my CI.
[00:45:21]
What quality can I check and automate?
[00:45:24]
There's one thing that we may not have talked about too much.
[00:45:28]
It's like GitHub Actions works with configuration files
[00:45:31]
that are checked into your repo.
[00:45:33]
So it's in the.github slash workflow slash whatever.
[00:45:38]
And the very nice thing with GitHub Actions
[00:45:40]
is that it works only with those files
[00:45:43]
in the sense that Travis,
[00:45:48]
you also needed to go to Travis website
[00:45:51]
and configure your repo so that the hooks worked.
[00:45:53]
Oh, yeah. That's a good point.
[00:45:56]
So if I provided a Travis setup,
[00:45:59]
I would still have to tell people,
[00:46:01]
hey, after you used Elmer View new package,
[00:46:03]
you should also go to Travis,
[00:46:05]
maybe create an account,
[00:46:07]
and then you're good to go.
[00:46:08]
But with GitHub Actions, I'm like,
[00:46:10]
here are the files, and you're good to go already.
[00:46:13]
You don't have to do anything more than that.
[00:46:18]
That's really the killer feature.
[00:46:20]
Yeah, it's huge.
[00:46:22]
I mean, there's just so much you can do with them.
[00:46:25]
You know what would be cool?
[00:46:26]
So you can send a tweet or call an API
[00:46:29]
or post to a webhook, right?
[00:46:31]
You can trigger a deployment.
[00:46:33]
So what if after you publish a package,
[00:46:37]
what if you set a Twitter account to automatically tweet
[00:46:41]
that you published it with the changelog, right?
[00:46:46]
So you have like a certain mindset
[00:46:48]
to just getting creative with these little automations.
[00:46:51]
I wired up, I don't know if you've seen this, Yaron,
[00:46:53]
but on my GitHub profile,
[00:46:56]
I think that's the term they use for it.
[00:46:58]
If you go to github.com slash Dillon Kerns,
[00:47:01]
it says, Hi, I'm Dillon,
[00:47:02]
and it's got some weekly tips that I've written
[00:47:06]
and Elm Radio podcast episodes.
[00:47:09]
So it actually gets RSS feeds from those,
[00:47:14]
and it shows the latest.
[00:47:17]
You can click in there and you can go to see
[00:47:20]
the latest Elm Radio episode.
[00:47:21]
It's a fun little automation,
[00:47:23]
and all it does is it uses this GitHub actions workflow.
[00:47:28]
It's called blog post workflow.
[00:47:30]
I'll put a link in the show notes,
[00:47:32]
but it's so easy to just wire it in.
[00:47:35]
You point it to an XML feed.
[00:47:37]
You give it like the name of a comment
[00:47:42]
that you're going to HTML with,
[00:47:44]
and then it puts in a UL with list items
[00:47:47]
within those comments in your HTML in that markup.
[00:47:50]
Then you just have to hope that the latest episode,
[00:47:53]
because you only showed the latest ones,
[00:47:55]
that the latest episodes are better
[00:47:56]
than the ones that were removed before.
[00:48:00]
Well, if I wanted to get really fancy,
[00:48:03]
I pull in data from the Simplecast API,
[00:48:06]
which under the hood hosts Elm Radio.com.
[00:48:11]
I could have a special Elm Radio feed
[00:48:14]
that sorts episodes by download count,
[00:48:18]
because that's available in the Simplecast API.
[00:48:20]
I use the Simplecast API to get the data in Elm pages
[00:48:24]
to generate the feed.
[00:48:26]
I could say here are some popular Elm Radio episodes.
[00:48:30]
I wonder if our listeners can guess
[00:48:32]
which one is the most popular one.
[00:48:34]
Please tweet about this.
[00:48:39]
It's going to be released on the day we're recording,
[00:48:41]
which is the one with Evan.
[00:48:43]
We'll see.
[00:48:44]
Evan?
[00:48:45]
Elm UI is pretty popular too.
[00:48:47]
Spoiler.
[00:48:48]
I'm guessing we won't edit this out.
[00:48:53]
We're rolling with it.
[00:48:56]
Sorry, Rune.
[00:48:57]
We'll put a spoiler warning.
[00:49:00]
Yeah, so there are all sorts
[00:49:02]
of little clever things you can do.
[00:49:07]
You can do it with SQL code,
[00:49:09]
using GitHub pages with a GitHub action.
[00:49:13]
It's worth kind of browsing through the marketplace
[00:49:16]
for some GitHub actions.
[00:49:18]
But the really exciting thing to me is just,
[00:49:21]
I mean, number one, the raw compute power
[00:49:23]
that you have easily available.
[00:49:25]
But number two, the fact that you can piece together
[00:49:28]
these tools and encapsulate them
[00:49:30]
with these little published actions
[00:49:35]
and wire together something.
[00:49:37]
You can grab output from one action
[00:49:39]
and pass it to another action.
[00:49:41]
There's a syntax for that.
[00:49:42]
It's the kind of thing that you have to look up
[00:49:45]
every time you do it,
[00:49:46]
but it's not that hard to do.
[00:49:49]
I think of it like automation.
[00:49:52]
It's just like this Rube Goldberg machine
[00:49:54]
that you create these cool things
[00:49:56]
that one thing happens
[00:49:58]
and it triggers another thing to happen
[00:50:03]
to just get creative about what you can enforce.
[00:50:06]
Run Lighthouse on every build
[00:50:08]
and then publish those stats someplace
[00:50:11]
and publish it to a spreadsheet or to Airtable
[00:50:14]
and keep track of those metrics there
[00:50:16]
and then build a little web page
[00:50:19]
that shows charts of those.
[00:50:21]
Get creative and automate things.
[00:50:23]
Do you know if this, then that?
[00:50:25]
Or ifttt.com?
[00:50:27]
Yeah, that's exactly the thing
[00:50:32]
that's going through the explore page right now.
[00:50:34]
There's one that says,
[00:50:35]
when I answer a call, pause the Roomba.
[00:50:40]
Yeah, that makes sense, I guess.
[00:50:42]
Sure.
[00:50:44]
If my CI fails, then pause the Roomba.
[00:50:47]
If I succeed.
[00:50:49]
Because I'm going to need to concentrate.
[00:50:52]
If I make a pull request and the test pass,
[00:50:54]
hand me a soda or something.
[00:50:56]
I don't know.
[00:51:01]
Actually, at a company I worked for
[00:51:04]
several years ago,
[00:51:06]
I built this thing.
[00:51:08]
I thought it was really fun.
[00:51:10]
Where I got a green lava lamp and a red lava lamp.
[00:51:14]
Do you see where this is going?
[00:51:16]
And I would publish our CI status
[00:51:19]
so it was accessible with some JSON file somewhere or something.
[00:51:24]
And then I would do a polling thing
[00:51:29]
or whatever.
[00:51:30]
And then this little like
[00:51:34]
Wi Fi power switch would automatically toggle
[00:51:38]
the lamps on based on whether the CI was failing.
[00:51:42]
The really cool thing about the lava lamps
[00:51:44]
is that if you look over and you see the red lava lamp on
[00:51:49]
and the little bubbles are floating around,
[00:51:52]
then you know it's been red for a while
[00:51:57]
and the green one is completely stable and not moving.
[00:52:02]
Someone just fixed it.
[00:52:04]
Then it means that it's been broken for a long time.
[00:52:06]
Or if the green one is on, then someone just fixed it.
[00:52:09]
Exactly.
[00:52:10]
Whenever I think of lava lamps,
[00:52:12]
I think of the Cloudflare wall.
[00:52:15]
Do you know that?
[00:52:17]
Oh yeah.
[00:52:19]
They have a wall full of lava lamps
[00:52:24]
and because the movements inside the lamps are pretty random,
[00:52:30]
they use that to generate random numbers,
[00:52:33]
which is like, what the hell?
[00:52:35]
Whoa.
[00:52:37]
That's crazy.
[00:52:38]
What a world we live in.
[00:52:40]
In a way it's automation, right?
[00:52:46]
So what did we miss about how GitHub actions work?
[00:52:51]
You can compose actions together.
[00:52:54]
There's a lot of syntax for that.
[00:52:56]
Do this when this happens.
[00:52:58]
Do that when that does not happen.
[00:53:01]
Things like that, I'm guessing.
[00:53:03]
I got the feeling that you can't do this.
[00:53:08]
You published an unpublished action.
[00:53:12]
That's what it's called, right?
[00:53:14]
That's the thing about literal naming, right?
[00:53:19]
Elm package called Elm package, right.
[00:53:23]
So if I wanted to reuse that one and another one
[00:53:27]
or maybe some additional script
[00:53:29]
and I wanted to wrap that itself into one action,
[00:53:32]
can I do that?
[00:53:33]
Can I compose actions together like that
[00:53:35]
or do I need to tell people,
[00:53:37]
please copy paste this portion of this script
[00:53:42]
and put it into yours?
[00:53:47]
I created the Elm publish action code.
[00:53:49]
It's just JavaScript code.
[00:53:51]
It's actually TypeScript
[00:53:53]
and it transpiles down to JavaScript.
[00:53:55]
You have such a sour face right now.
[00:53:58]
It's JavaScript crap.
[00:54:03]
No, it's great.
[00:54:05]
I think JavaScript is kind of a good tool for the job.
[00:54:09]
It's got its blemishes,
[00:54:11]
but I'd rather use that than most things
[00:54:16]
because it's just a,
[00:54:18]
it's ultimately just some JavaScript calls.
[00:54:20]
They call some APIs.
[00:54:21]
It calls this like core octokit thing
[00:54:24]
and this core GitHub actions core package stuff
[00:54:27]
which allows you to like write out debug statements
[00:54:31]
if you want to or print things to the logs.
[00:54:34]
And it sort of,
[00:54:35]
I think it's the same as Travis this way
[00:54:37]
where actually they use some conventions
[00:54:39]
where they have some like prefix
[00:54:44]
and expandable or to highlight certain things
[00:54:47]
as errors and things like that.
[00:54:48]
Just like ANSI color codes in the terminal.
[00:54:51]
That sort of deal.
[00:54:52]
But they encapsulate that
[00:54:54]
using these like JavaScript NPM packages
[00:54:57]
that you pull into your code
[00:54:59]
and do it in a higher level way.
[00:55:01]
But so basically I don't think there's like,
[00:55:04]
I don't think there's a way,
[00:55:05]
it's not a workflow.
[00:55:06]
It's just JavaScript code
[00:55:08]
and you call some code
[00:55:13]
but it actually doesn't run like a YAML workflow.
[00:55:17]
So you can't call other people's workflows
[00:55:20]
and encapsulate those.
[00:55:21]
You just kind of would have to create your own thing.
[00:55:23]
But it works pretty well
[00:55:24]
and it's kind of tricky like testing things out
[00:55:27]
and making sure everything works.
[00:55:29]
But it's quite nice
[00:55:30]
being able to encapsulate these things.
[00:55:32]
How do you go about testing those actually
[00:55:34]
and writing one maybe first?
[00:55:37]
Well, you can start with their starter repos.
[00:55:42]
And I mean, you can write tests with a bajillion mocks.
[00:55:47]
I kind of didn't find much value in that.
[00:55:50]
So to be honest, I kind of,
[00:55:52]
I mean, I think of it as a script.
[00:55:54]
And like, so I kind of test out the script
[00:55:58]
and make sure it works
[00:55:59]
and build it in such a way that it's robust
[00:56:01]
and not going to do anything dangerous.
[00:56:03]
Like for example, you and I discussed this year
[00:56:05]
and when I built this that I added a dry run feature
[00:56:10]
to publish actions.
[00:56:11]
So you can see if everything checks out
[00:56:13]
and if it's going to publish.
[00:56:15]
And I don't accept your GitHub token in that form
[00:56:20]
and I'll actually reject it if you pass that in.
[00:56:23]
And so that's like a safety measure
[00:56:24]
where it's like, okay,
[00:56:26]
you don't need to test that.
[00:56:28]
Just don't pass your GitHub token.
[00:56:30]
And you can be confident
[00:56:32]
that if anything goes wrong,
[00:56:34]
it would be that it crashes
[00:56:39]
and you have to do a package.
[00:56:41]
So you have some load,
[00:56:43]
but it's basically a way of nicely encapsulating a script.
[00:56:46]
And most of these things are scripting tasks
[00:56:48]
like the, like Matthew Pitzenberg created this GitHub action
[00:56:53]
that encapsulates the Elm tooling CLI
[00:56:56]
for packages that, for projects that are not using NPM
[00:57:01]
because like we talked about in our Elm tooling episode,
[00:57:06]
it takes a lot of VX to sort of install
[00:57:08]
and run these dependencies.
[00:57:10]
But for projects that don't use that,
[00:57:12]
he created a GitHub action that encapsulates that.
[00:57:15]
And like that's another great use case.
[00:57:17]
Like there's really not a lot of logic to it.
[00:57:20]
It's just sort of conveniently wiring some things for you.
[00:57:23]
And so I would say like probably
[00:57:26]
the Unix tool chain philosophy
[00:57:28]
is a good strategy for publishing
[00:57:30]
these little standalone actions
[00:57:35]
that are not doing well.
[00:57:36]
It should send a tweet, install a tool,
[00:57:39]
cache something, whatever that may be.
[00:57:41]
And the gluing is done by listing them in the workflow
[00:57:44]
in the GitHub configuration YAML.
[00:57:47]
Exactly.
[00:57:48]
And sometimes it's a bit of a pain to glue them together,
[00:57:52]
but it's better to have that flexibility
[00:57:54]
than have one tool that does everything
[00:57:57]
except for this one use case where it doesn't work.
[00:58:02]
Also, we haven't mentioned,
[00:58:04]
we haven't talked about caching,
[00:58:06]
but it's worth knowing how caching works.
[00:58:09]
So I recommend looking at the example setup
[00:58:13]
that Simon created for the Elm Tooling CLI.
[00:58:17]
He's got a nice, well sort of documented
[00:58:20]
with a bunch of comments workflow.
[00:58:22]
And he, so but basically the way that it works
[00:58:26]
is there's this like,
[00:58:31]
there's these steps in your GitHub actions workflow
[00:58:33]
in this YAML file, and you enumerate these steps
[00:58:35]
and you can list a step that uses actions slash cache.
[00:58:40]
And all that's going to do is you give it a cache key
[00:58:44]
and to get that cache key,
[00:58:46]
you hash the files that determine
[00:58:49]
whether it's a cache hit or a cache miss.
[00:58:52]
So for NPM projects,
[00:58:54]
that would be the package lock.json
[00:58:59]
then it's a cache miss.
[00:59:02]
And for Elm projects,
[00:59:04]
that would be the Elm.json file,
[00:59:06]
but it would also be the review slash Elm.json file
[00:59:09]
if you have an Elm review configuration
[00:59:11]
because that's a separate Elm.json file
[00:59:13]
with its own Elm dependencies.
[00:59:15]
But you're caching the Elm home directory
[00:59:18]
which keeps a cache of the packages installed
[00:59:21]
throughout that entire project.
[00:59:22]
So what happens if the cache is a miss?
[00:59:27]
Then it's just not going to download the cache, right?
[00:59:30]
Yeah, that's my understanding as well.
[00:59:33]
But then you will still need to do the task
[00:59:37]
of installing NPM packages or...
[00:59:40]
Right.
[00:59:41]
The way that it works,
[00:59:42]
basically there's like a...
[00:59:45]
I think this is like a general feature of GitHub actions.
[00:59:48]
I don't use it for Elm publish action,
[00:59:50]
but I think that anybody can hook into this functionality
[00:59:55]
that has like setup tasks and tear down tasks.
[01:00:00]
And so for the caching action,
[01:00:03]
and again, it's just one of these little
[01:00:05]
Unix tool chain pieces,
[01:00:07]
this small thing that does one job well.
[01:00:09]
And so for the caching action,
[01:00:12]
the setup is check if it's a cache hit
[01:00:15]
and then restore the cache if so.
[01:00:18]
And then for the tear down,
[01:00:23]
you can cache the cached locations
[01:00:25]
under a particular, like push it up
[01:00:28]
to this temporary storage location,
[01:00:30]
which like GitHub actions has a way of sort of pushing up
[01:00:34]
tar balls somewhere and then pulling them down
[01:00:36]
and restoring them.
[01:00:37]
So that's basically how the caching works.
[01:00:40]
So it's interesting because it is kind of low level,
[01:00:44]
but I think it's because it's that
[01:00:46]
Unix tool chain philosophy.
[01:00:47]
So you sort of like,
[01:00:52]
you have a node and then you run the GitHub actions caching
[01:00:57]
for NPM and then you NPM install.
[01:01:01]
But I think that's just the philosophy
[01:01:03]
that they've gone with is to be explicit about these things
[01:01:06]
and let you configure them.
[01:01:08]
But so basically the way the tear down is going to work
[01:01:12]
is you have to NPM install in the appropriate places
[01:01:16]
and you have to L make so that it installs
[01:01:21]
and it will be the cache that gets restored.
[01:01:23]
So there's one thing about caching
[01:01:24]
that never properly understood.
[01:01:27]
So the way it works, as we said before,
[01:01:30]
is it uses the actions slash cache and a version of that.
[01:01:34]
If you give it a path where to restore the cache from two,
[01:01:40]
I guess, and a key which gets,
[01:01:43]
which determines whether there will be a hit or a miss.
[01:01:46]
But it doesn't say what to do if the cache is a miss.
[01:01:49]
So that's something that you run in a later step.
[01:01:52]
But when does it then save that cache?
[01:01:56]
Does it do that at the end of the workflow?
[01:01:58]
And if so, only if it succeeds? Do you know that?
[01:02:01]
I do know that it saves the cache
[01:02:04]
at the end of the workflow.
[01:02:06]
That's like that tear down thing I was talking about.
[01:02:08]
I'm actually not sure if it, well, I mean,
[01:02:12]
it's going to save the cache no matter what, right?
[01:02:17]
Whether it's a, well, I guess if it's a cache hit,
[01:02:20]
then it doesn't save it, right?
[01:02:22]
It doesn't need to resave it.
[01:02:23]
Because it restored the previous version.
[01:02:26]
So it won't save it again if it doesn't need to.
[01:02:29]
And it will save a fresh cache if it was a cache miss.
[01:02:33]
Right? So that's what the core thing does.
[01:02:35]
But it also provides an output.
[01:02:38]
So these are sort of the basic building blocks
[01:02:40]
of these actions you piece together.
[01:02:45]
So you can do your own steps, which are just like running
[01:02:48]
a bash script or a little bash command,
[01:02:51]
or these sort of things that are published in the marketplace
[01:02:54]
as little JavaScript snippets of code,
[01:02:58]
like unpublish action and the actions cache.
[01:03:01]
Either way, you can have inputs to that action
[01:03:04]
that they depend on and outputs that they pass out.
[01:03:08]
And the actions cache actually provides an output
[01:03:13]
for it was a cache hit.
[01:03:14]
Yeah, so you can do, if there was a cache hit,
[01:03:17]
then you don't have to rerun npm install.
[01:03:20]
Yeah, exactly.
[01:03:22]
Yeah, that's what Simon does in his boilerplate
[01:03:26]
for Elm tooling CLI.
[01:03:28]
He skips npm CI if it was a cache hit.
[01:03:32]
All right.
[01:03:33]
I feel like we went through everything, right?
[01:03:35]
I think we've largely exhausted our knowledge on this topic.
[01:03:40]
I'm certainly not an expert on GitHub actions,
[01:03:43]
but I use them a lot, and I get a lot of value from them.
[01:03:46]
So I hope there were some useful tips in there for people.
[01:03:49]
And there are a lot of resources online too.
[01:03:53]
I think a lot of GitHub actions is just really getting creative
[01:03:57]
with what you do with it.
[01:03:58]
Yeah, obviously learning the basics,
[01:04:00]
but after that getting creative.
[01:04:03]
By learning the basics, do you mean Googling
[01:04:08]
every single time you use it?
[01:04:10]
Because it's YAML and you can never remember it?
[01:04:14]
And talk about Norway a lot.
[01:04:16]
What's that?
[01:04:18]
In YAML, if you have NO, that means false.
[01:04:24]
But if you use that as the Norway, like the two letter,
[01:04:29]
the country code, well, you have trouble.
[01:04:34]
Yes, that's true.
[01:04:36]
Also dates.
[01:04:37]
If you do dates, it will automagically parse them
[01:04:41]
into these weird string things.
[01:04:44]
And you're like, what?
[01:04:45]
That's not the date I wrote.
[01:04:46]
Turns out you have to put it between quotes
[01:04:48]
to have the literal 2021 dash 03 dash 15.
[01:04:55]
It'll parse that out to a UTC time.
[01:05:00]
Okay, so next time you do a date, don't do YAML,
[01:05:03]
go to a restaurant or something.
[01:05:06]
That's right.
[01:05:08]
YAML would be a very bad date idea.
[01:05:10]
It would be a terrible date night.
[01:05:13]
You can just, yeah, no.
[01:05:16]
You feel bad about yourself?
[01:05:18]
No.
[01:05:18]
Because you probably should a little bit.
[01:05:22]
So how should people get started?
[01:05:24]
Besides just scouring through the documentation
[01:05:29]
there.
[01:05:29]
What I'm doing is just taking a look
[01:05:31]
at existing ones.
[01:05:33]
Mostly Simon Lytle hits GitHub action.
[01:05:38]
And yeah, going through the docs from GitHub.
[01:05:41]
Do you have good courses or good resources?
[01:05:45]
There are a couple of Brian Douglas works at GitHub
[01:05:48]
and he's been publishing a lot of stuff about it.
[01:05:51]
So he's got like a series, a blog post series on dev.to
[01:05:56]
has a lot of videos and a lot of,
[01:05:58]
it's almost like an Advent style thing of one thing
[01:06:01]
he posted every month recently.
[01:06:03]
So that's useful.
[01:06:05]
And then Edward Thompson, who was one of the product managers
[01:06:09]
that developed the product of GitHub actions,
[01:06:12]
has a GitHub actions actual Advent calendar.
[01:06:15]
So kind of similar things there.
[01:06:17]
An actual one.
[01:06:18]
It's useful to just look at lots of examples, as you say.
[01:06:23]
You can look at a bunch of other Elm open source projects
[01:06:25]
or look at these cool things people are doing with it
[01:06:29]
in these blog posts.
[01:06:31]
Well thanks so much for listening everyone.
[01:06:33]
And be sure to leave us a review on Apple Podcasts
[01:06:36]
if you enjoy the podcast.
[01:06:38]
Tell a friend, if you've got an Elm friend
[01:06:40]
who doesn't know about us, let them know
[01:06:42]
and send us a tweet.
[01:06:45]
Let us know what question you'd like us to talk about
[01:06:47]
or go to elm.radio.com slash question.
[01:06:52]
And as always, have a good one.
[01:06:53]
Have a good one.
[01:06:54]
.
[01:06:54]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:06:55]
.
[01:07:00]
.