aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2020-11-18 12:18:24 -0500
committerGitHub <noreply@github.com>2020-11-18 12:18:24 -0500
commitf643496416c75ea468ffd866ccfee6436a3912f0 (patch)
tree902a3b987474906360544c55bd28b96f9e2bb44a
parent089b14788dbc0fe9a6b3a9263d5926a27c96f237 (diff)
downloadxesite-f643496416c75ea468ffd866ccfee6436a3912f0.tar.xz
xesite-f643496416c75ea468ffd866ccfee6436a3912f0.zip
various updates (#263)
* various updates * fix glory shot * fix mi url for updating my blog * fix CI
-rw-r--r--.github/workflows/nix.yml5
-rw-r--r--blog/various-updates-2020-11-18.markdown230
-rw-r--r--config.dhall18
-rwxr-xr-xscripts/release.sh2
-rw-r--r--src/app/mod.rs16
-rw-r--r--src/main.rs26
-rw-r--r--templates/header.rs.html3
7 files changed, 278 insertions, 22 deletions
diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml
index b43b2db..5b96165 100644
--- a/.github/workflows/nix.yml
+++ b/.github/workflows/nix.yml
@@ -11,10 +11,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- - uses: cachix/install-nix-action@v6
- - uses: cachix/cachix-action@v3
+ - uses: cachix/install-nix-action@v12
+ - uses: cachix/cachix-action@v7
with:
name: xe
+ - run: nix-build
- name: Log into GitHub Container Registry
run: echo "${{ secrets.CR_PAT }}" | docker login https://ghcr.io -u ${{ github.actor }} --password-stdin
- name: Docker push
diff --git a/blog/various-updates-2020-11-18.markdown b/blog/various-updates-2020-11-18.markdown
new file mode 100644
index 0000000..bc85ebc
--- /dev/null
+++ b/blog/various-updates-2020-11-18.markdown
@@ -0,0 +1,230 @@
+---
+title: Various Updates
+date: 2020-11-18
+tags:
+ - personal
+ - consulting
+ - docker
+ - nixos
+---
+
+# Various Updates
+
+Immigration purgatory is an experience. It's got a lot of waiting and there is a
+lot of uncertainty that can make it feel stressful. Like I said
+[before](/blog/new-adventures-2020-10-24), I'm not concerned; however I have a
+lot of free time on my hands and I've been using it to make some plans for the
+blog (and a new offering for companies that need help dealing with the new
+[Docker Hub rate
+limits](https://docs.docker.com/docker-hub/download-rate-limit/)) in the future.
+I'm gonna outline them below in their own sections. This blogpost was originally
+about 4 separate blogposts that I started and abandoned because I had trouble
+focusing on finishing them. Stress sucks lol.
+
+## WebMention Support
+
+I recently deployed [mi v1.0.0](https://github.com/Xe/mi) to my home cluster. mi
+is a service that handles a lot of personal API tasks including the automatic
+post notifications to Twitter and Mastodon. The old implementation was in Go and
+stored its data in RethinkDB. I also have a snazzy frontend in Elm for mi. This
+new version is rewritten from scratch to use Rust, [Rocket](https://rocket.rs/)
+and SQLite. It is also fully
+[nixified](https://github.com/Xe/mi/blob/mara/default.nix) and is deployed to my
+home cluster via a [NixOS
+module](https://github.com/Xe/nixos-configs/blob/master/common/services/mi.nix).
+
+One of the major new features I have in this rewrite is
+[WebMention](https://www.w3.org/TR/webmention/) support. WebMentions allow
+compatible websites to "mention" my articles or other pages on my main domains
+by sending a specially formatted HTTP request to mi. I am still in the early
+stages of integrating mi into my site code, but eventually I hope to have a list
+of places that articles are mentioned in each post. The WebMention endpoint for
+my site is `https://mi.within.website/api/webmention/accept`. I have added
+WebMention metadata into the HTML source of the blog pages as well as in the
+`Link` header as the W3 spec demands.
+
+If you encounter any issues with this feature, please [let me know](/contact) so
+I can get it fixed as soon as possible.
+
+### Thoughts on Elm as Used in mi
+
+[Elm](https://elm-lang.org/) is an interesting language for making single page
+applications. The old version of mi was the first time I had really ever used
+Elm for anything serious and after some research I settled on using
+[elm-spa](https://www.elm-spa.dev/) as a framework to smooth over some of the
+weirder parts of the language. elm-spa worked great at first. All of the pages
+were separated out into their own components and the routing setup was really
+intuitive (if a bit weird because of the magic involved). It's worked great for
+a few years and has been very low maintenance.
+
+However when I was starting to implement the backend of mi in Rust, I tried to
+nixify the elm-spa frontend I made. This was a disaster. The magic that elm-spa
+relied on fell apart and _at the time I attempted to do this_ it was very
+difficult to do this.
+
+As a result I ended up rewriting the frontend in very very boring Elm using
+information from the [Elm Guide](https://guide.elm-lang.org/) and a lot of
+blogposts and help from the Elm slack. Overall this was a successful experiment
+and I can easily see this new frontend (which I have named sina as a compound
+[toki pona](https://tokipona.org/) pun) becoming a powerful tool for
+investigating and managing the data in mi.
+
+[Special thanks to malinoff, wolfadex, chadtech and mfeineis on the Elm slack
+for helping with the weird issues involved in getting a split model approach
+working.](conversation://Mara/hacker)
+
+Feel free to check out the code [here](https://github.com/Xe/mi/tree/mara/sina).
+I may try to make an Elm frontend to my site for people that use the Progressive
+Web App support.
+
+### elm2nix
+
+[elm2nix](https://github.com/cachix/elm2nix) is a very nice tool that lets you
+generate Nix definitions from Elm packages, however the
+template it uses is a bit out of date. To fix it you need to do the following:
+
+```console
+$ elm2nix init > default.nix
+$ elm2nix convert > elm-srcs.nix
+$ elm2nix snapshot
+```
+
+Then open `default.nix` in your favorite text editor and change this:
+
+```nix
+ buildInputs = [ elmPackages.elm ]
+ ++ lib.optional outputJavaScript nodePackages_10_x.uglify-js;
+```
+
+to this:
+
+```nix
+ buildInputs = [ elmPackages.elm ]
+ ++ lib.optional outputJavaScript nodePackages.uglify-js;
+```
+
+and this:
+
+```nix
+ uglifyjs $out/${module}.${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \
+ | uglifyjs --mangle --output=$out/${module}.min.${extension}
+```
+
+to this:
+
+```nix
+ uglifyjs $out/${module}.${extension} --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' \
+ | uglifyjs --mangle --output $out/${module}.min.${extension}
+```
+
+These issues should be fixed in the next release of elm2nix.
+
+## New Character in the Blog Cutouts
+
+As I mentioned [in the past](/blog/how-mara-works-2020-09-30), I am looking into
+developing out other characters for my blog. I am still in the early stages of
+designing this, but I think the next character in my blog is going to be an
+anthro snow leopard named Alicia. I want Alicia to be a beginner that is very
+new to computer programming and other topics, which would then make Mara into
+more of a teacher type. I may also introduce my own OC Cadey (the orca looking
+thing you can see [here](https://christine.website/static/img/avatar_large.png)
+or in the favicon of my site) into the mix to reply to these questions in
+something more close to the Socratic method.
+
+Some people have joked that the introduction of Mara turned my blog into a shark
+visual novel that teaches you things. This sounds hilarious to me, and I am
+looking into what it would take to make an actual visual novel on a page on my
+blog using Rust and WebAssembly. I am in very early planning stages for this, so
+don't expect this to come out any time soon.
+
+## Gergoplex Build
+
+My [Gergoplex kit](https://www.gboards.ca/product/gergoplex) finally came in
+yesterday, and I got to work soldering it up with some switches and applying the
+keycaps.
+
+![Me soldering the Gergoplex](https://cdn.christine.website/file/christine-static/img/keeb/gergoplex/EnEYNxvW4AEfWcH.jpg)
+
+![A glory shot of the Gergoplex](https://cdn.christine.website/file/christine-static/img/keeb/gergoplex/Elm3dN8XUAAYHws.jpg)
+
+I picked the Pro Red linear switches with a 35 gram spring in them (read: they
+need 35 grams of force to actuate, which is lighter than most switches) and
+typing on it is buttery smooth. The keycaps are a boring black, but they look
+nice on it.
+
+Overall this kit (with the partial board, switches and keycaps) cost me about
+US$124 (not including shipping) with the costs looking something like this:
+
+| Name | Count | Cost |
+| :------------------------- | :----- | :---- |
+| Gergoplex Partial Kit | 1 | $70 |
+| Choc Pro Red 35g switches | 4 | $10 |
+| Keycaps (15) | 3 | $30 |
+| Braided interconnect cable | 1 | $7 |
+| Mini-USB cable | 1 | $7 |
+
+I'd say this was a worthwhile experience. I haven't really soldered anything
+since I was in high school and it was fun to pick up the iron again and make
+something useful. If you are looking for a beginner soldering project, I can't
+recommend the Gergoplex enough.
+
+I also picked up some extra switches and keycaps (prices not listed here) for a
+future project involving an eInk display. More on that when it is time.
+
+## Branch Conventions
+
+You may have noticed that some of my projects have default branches named `main`
+and others have default branches named `mara`. This difference is very
+intentional. Repos with the default branch `main` generally contain code that is
+"stable" and contains robust and reusable code. Repos with the default branch
+`mara` are generally my experimental repos and the code in them may not be the
+most reusable across other projects. mi is a repo with a `mara` default branch
+because it is a very experimental thing. In the future I may promote it up to
+having a `main` branch, however for now it's less effort to keep things the way
+it is.
+
+## Docker Consulting
+
+The new [Docker Hub rate
+limits](https://docs.docker.com/docker-hub/download-rate-limit/) have thrown a
+wrench into many CI/CD setups as well as uncertainty in how CI services will
+handle this. Many build pipelines implictly trust the Docker Hub to be up and
+that it will serve the appropriate image so that your build can work. Many
+organizations use their own Docker registry (GHCR, AWS/Google Cloud image
+registries, Artifactory, etc.), however most image build definitions I've seen
+start out with something like this:
+
+```Dockerfile
+FROM golang:alpine
+```
+
+which will implicitly pull from the Docker Hub. This can lead to bad things.
+
+If you would like to have a call with me for examining your process for building
+Docker images in CI and get a list of actionable suggestions for how to work
+around this, [contact me](/contact) so that we can discuss pricing and
+scheduling.
+
+I have been using Docker for my entire professional career (way back since
+Docker required you to recompile your kernel to enable cgroup support in public
+beta) and I can also discuss methods to make your Docker images as small as they
+can possibly get. My record smallest Docker image is 5 MB.
+
+If either of these prospects interest you, please contact me so we can work
+something out.
+
+---
+
+Here's hoping that the immigration purgatory ends soon. I'm lucky enough to have
+enough cash built up that I can weather this jobless month. I've been using this
+time to work on personal projects (like mi and
+[wasmcloud](https://wasmcloud.app)) and better myself. I've also done a little
+writing that I plan to release in the future after I clean it up.
+
+In retrospect I probably should have done [NaNoWriMo](https://nanowrimo.org/)
+seeing that I basically will have the entire month of November jobless. I've had
+an idea for a while about someone that goes down the rabbit hole of mysticism
+and magick, but I may end up incorporating that into the visual novel project I
+mentioned in the Elm section.
+
+Be well and stay safe out there. Wear a mask, stay at home.
diff --git a/config.dhall b/config.dhall
index f461134..192955d 100644
--- a/config.dhall
+++ b/config.dhall
@@ -1,24 +1,30 @@
let Person =
{ Type = { name : Text, tags : List Text, gitLink : Text, twitter : Text }
, default =
- { name = "", tags = [] : List Text, gitLink = "", twitter = "" }
+ { name = "", tags = [] : List Text, gitLink = "", twitter = "" }
}
let defaultPort = env:PORT ? 3030
+let defaultWebMentionEndpoint =
+ env:WEBMENTION_ENDPOINT
+ ? "https://mi.within.website/api/webmention/accept"
+
let Config =
{ Type =
{ signalboost : List Person.Type
, port : Natural
, clackSet : List Text
, resumeFname : Text
+ , webMentionEndpoint : Text
}
, default =
- { signalboost = [] : List Person.Type
- , port = defaultPort
- , clackSet = [ "Ashlynn" ]
- , resumeFname = "./static/resume/resume.md"
- }
+ { signalboost = [] : List Person.Type
+ , port = defaultPort
+ , clackSet = [ "Ashlynn" ]
+ , resumeFname = "./static/resume/resume.md"
+ , webMentionEndpoint = defaultWebMentionEndpoint
+ }
}
in Config::{
diff --git a/scripts/release.sh b/scripts/release.sh
index 544df55..9510d39 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -7,4 +7,4 @@ kubectl rollout status -n apps deployment/christinewebsite
kubectl apply -f ./k8s/job.yml
sleep 10
kubectl delete -f ./k8s/job.yml
-curl --http1.1 -H "Authorization: $MI_TOKEN" --data "https://christine.website/blog.json" https://mi.within.website/blog/refresh
+curl --http1.1 -H "Authorization: $MI_TOKEN" https://mi.within.website/api/blog/refresh
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 035db07..c18e121 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -2,24 +2,28 @@ use crate::{post::Post, signalboost::Person};
use color_eyre::eyre::Result;
use serde::Deserialize;
use std::{fs, path::PathBuf};
-use tracing::{instrument, error};
+use tracing::{error, instrument};
pub mod markdown;
#[derive(Clone, Deserialize)]
pub struct Config {
#[serde(rename = "clackSet")]
- clack_set: Vec<String>,
- signalboost: Vec<Person>,
- port: u16,
+ pub(crate) clack_set: Vec<String>,
+ pub(crate) signalboost: Vec<Person>,
+ pub(crate) port: u16,
#[serde(rename = "resumeFname")]
- resume_fname: PathBuf,
+ pub(crate) resume_fname: PathBuf,
+ #[serde(rename = "webMentionEndpoint")]
+ pub(crate) webmention_url: String,
}
#[instrument]
async fn patrons() -> Result<Option<patreon::Users>> {
use patreon::*;
- let creds: Credentials = envy::prefixed("PATREON_").from_env().unwrap_or(Credentials::default());
+ let creds: Credentials = envy::prefixed("PATREON_")
+ .from_env()
+ .unwrap_or(Credentials::default());
let cli = Client::new(creds);
match cli.campaign().await {
diff --git a/src/main.rs b/src/main.rs
index 01333c9..0baaeef 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,12 +26,15 @@ async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
log::info!("starting up commit {}", env!("GITHUB_SHA"));
- let state = Arc::new(app::init(
- std::env::var("CONFIG_FNAME")
- .unwrap_or("./config.dhall".into())
- .as_str()
- .into(),
- ).await?);
+ let state = Arc::new(
+ app::init(
+ std::env::var("CONFIG_FNAME")
+ .unwrap_or("./config.dhall".into())
+ .as_str()
+ .into(),
+ )
+ .await?,
+ );
let healthcheck = warp::get().and(warp::path(".within").and(warp::path("health")).map(|| "OK"));
@@ -144,6 +147,17 @@ async fn main() -> Result<()> {
)
})
.map(|reply| warp::reply::with_header(reply, "X-Clacks-Overhead", "GNU Ashlynn"))
+ .map(|reply| {
+ warp::reply::with_header(
+ reply,
+ "Link",
+ format!(
+ r#"<{}>; rel="webmention""#,
+ std::env::var("WEBMENTION_URL")
+ .unwrap_or("https://mi.within.website/api/webmention/accept".to_string())
+ ),
+ )
+ })
.with(warp::log(APPLICATION_NAME))
.recover(handlers::rejection);
diff --git a/templates/header.rs.html b/templates/header.rs.html
index 37e6eb2..ca49a36 100644
--- a/templates/header.rs.html
+++ b/templates/header.rs.html
@@ -30,7 +30,7 @@
<link rel="apple-touch-icon" sizes="144x144" href="/static/favicon/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/static/favicon/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-icon-180x180.png">
- <link rel="icon" type="image/png" sizes="192x192" href="/static/favicon/android-icon-192x192.png">
+ <link rel="icon" type="image/png" sizes="192x192" href="/static/favicon/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/static/favicon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon/favicon-16x16.png">
@@ -38,6 +38,7 @@
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/static/favicon/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
+ <link href="https://mi.within.website/api/webmention/accept" rel="webmention" />
@if styles.is_some() {
<style>
@styles.unwrap()