<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>lucasew&apos;s blog posts</title><description>RSS feed for English posts</description><link>https://lucasew.github.io/</link><item><title>Release automation and testing on CI</title><link>https://lucasew.github.io/en/post/20250919-project-automations/</link><guid isPermaLink="true">https://lucasew.github.io/en/post/20250919-project-automations/</guid><description>How I am doing it in my projects</description><pubDate>Fri, 19 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am the kind of guy that feels annoyed when doing the same thing twice by
process, like fill the same task on two places, so I often look for a way to
automate. Also, I do not like to do repetitive stuff often like checking for
dependencies on my not so active projects.&lt;/p&gt;
&lt;p&gt;For this repetitive stuff of checking for dependencies I rely on the renovate
bot[^renovate_bot] but often the users don’t clone the project to use the
software, so I had to find a way to setup releases and build artifacts to them.
As I am using GitHub Actions because I am on GitHub and I am most comfortable
using it, mostly because of choice inertia to be honest.&lt;/p&gt;
&lt;p&gt;[^renovate_bot]: Renovate: &lt;a href=&quot;https://github.com/renovatebot/renovate&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I may translate the renovate post from portuguese[^renovate-portuguese] to
english soon.&lt;/p&gt;
&lt;p&gt;[^renovate-portuguese]: Renovate post in portuguese:
&lt;a href=&quot;/pt/post/20250515-mantendo-projetos-atualizados/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Going back to the release problem, what I did is to basically move it all to an
Autorelease workflow. In my GitHub, most of the projects that are not just
“Deploy to Vercel” are having that or being archived.&lt;/p&gt;
&lt;p&gt;The specific approaches actually depend on the things used to develop that
specific software, but it’s mostly the same.&lt;/p&gt;
&lt;p&gt;Basically the repository has the following items:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mise.toml&lt;/code&gt;: Has the toolchain versions and sometimes the commands to build
the repository.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;renovate.json&lt;/code&gt;: Renovate config file, out of the standard often there are
only some automerge rules to merge patch updates and stuff like that. It
merges automatically those cases when CI is green by default.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make_release&lt;/code&gt;: Changes version.txt, or some other files if needed, to update
the version of the project. Normally it’s run by CI. In some Python projects
this file is inside the project main module.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Dockerfile&lt;/code&gt;: Some of the projects package a service. This file mostly have a
standard multi-stage docker build to generate the project’s container.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.dockerignore&lt;/code&gt; and &lt;code&gt;.gitignore&lt;/code&gt;: Has the output directory of builds and other
stuff, so it doesn’t get committed by the workflow. It sucks when it happens!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.github/workflows/autorelease.yaml&lt;/code&gt;: The one and only workflow required.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How the workflow is set up&lt;/h2&gt;
&lt;p&gt;I’ll take the workflow from ts-proxy[^ts-proxy-repo]. I think it’s one of the
reference implementations and often the one that I copy over to new projects
when I am setting it up on another project, even when the project is not made in
Golang.&lt;/p&gt;
&lt;p&gt;[^ts-proxy-repo]: ts-proxy: &lt;a href=&quot;https://github.com/lucasew/ts-proxy&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;name: Autorelease

on:
  push:
    branches:
    - main
    tags:
    - &apos;*&apos;
  workflow_dispatch:
    inputs:
      new_version:
        description: &apos;New tag version&apos;
        default: &apos;patch&apos;
  schedule:
    - cron: &apos;0 2 * * 6&apos; # saturday 2am
jobs:
  autorelease:
    env:
      REGISTRY: ghcr.io
      IMAGE_NAME: ${{ github.repository }}
      USERNAME: ${{ github.actor }}
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write
      attestations: write
      id-token: write
      pull-requests: write
    steps:

    - uses: actions/checkout@v5
    - name: Setup git config
      run: |
        git config user.name actions-bot
        git config user.email actions-bot@users.noreply.github.com

    - uses: jdx/mise-action@v3

    - name: Create Pull Request if there is new stuff from updaters
      uses: peter-evans/create-pull-request@v7
      id: pr_create
      with:
        commit-message: Updater script changes
        branch: updater-bot
        delete-branch: true
        title: &amp;quot;Updater: stuff changed&amp;quot;
        body: |
          Changes caused from update scripts

    - name: Stop if a pull request was created
      env:
        PR_NUMBER: ${{ steps.pr_create.outputs.pull-request-number }}
      run: |
        if [[ ! -z &amp;quot;$PR_NUMBER&amp;quot; ]]; then
          echo &amp;quot;The update scripts changed something and a PR was created. Giving up deploy.&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
          exit 1
        fi

    - name: Build binaries
      env:
        TAG: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      run: |
        echo &amp;quot;::group::Build container&amp;quot;
        docker build -t &amp;quot;$TAG:latest&amp;quot; .
        echo &amp;quot;::endgroup::&amp;quot;

        mkdir build -p &amp;amp;&amp;amp; ls &amp;amp;&amp;amp; pwd

        echo &amp;quot;# Built targets&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
        export CGO_ENABLED=0
        go tool dist list | grep -v wasm | while IFS=/ read -r GOOS GOARCH; do
          echo &amp;quot;::group::Build $GOOS/$GOARCH&amp;quot;
          GOOS=$GOOS GOARCH=$GOARCH go build -v -o build/ts-proxyd-$GOOS-$GOARCH ./cmd/ts-proxyd &amp;amp;&amp;amp; (echo &amp;quot;- $GOOS/$GOARCH&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY) || true
          echo &amp;quot;::endgroup::&amp;quot;
        done

    - name: Make release if everything looks right
      env:
        NEW_VERSION: ${{ github.event.inputs.new_version }}
      run: |
        if [[ ! -z &amp;quot;$NEW_VERSION&amp;quot; ]]; then
          NO_TAG=1 ./make_release &amp;quot;$NEW_VERSION&amp;quot;
          echo &amp;quot;New version: $(cat version.txt)&amp;quot; &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY
          echo &amp;quot;RELEASE_VERSION=$(cat version.txt)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV
        fi

    - name: Create release
      if: env.RELEASE_VERSION != &apos;&apos;
      env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TAG: ${{ env.RELEASE_VERSION }}
          TITLE: Release ${{ env.RELEASE_VERSION }}
      run: |
        gh release create &amp;quot;$TAG&amp;quot; \
          --title &amp;quot;$TITLE&amp;quot; \
          --generate-notes \
          --notes-start-tag $(gh release list --limit 1 --json tagName -q .[].tagName) 

    - uses: svenstaro/upload-release-action@v2
      if: env.RELEASE_VERSION != &apos;&apos;
      with:
        repo_token: ${{ secrets.GITHUB_TOKEN }}
        file: build/*
        tag: ${{ env.RELEASE_VERSION }}
        overwrite: true
        file_glob: true

    - name: Login to registry
      uses: docker/login-action@v3
      if: env.RELEASE_VERSION != &apos;&apos;
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ env.USERNAME }}
        password: ${{ github.token }}

    - name: &amp;quot;Build and publish container&amp;quot;
      env:
        TAG: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      if: env.RELEASE_VERSION != &apos;&apos;
      run: |
        VERSION=&amp;quot;$(cat version.txt)&amp;quot;
        docker tag &amp;quot;$TAG:latest&amp;quot; &amp;quot;$TAG:$VERSION&amp;quot;
        docker push &amp;quot;$TAG:$VERSION&amp;quot;
        docker push &amp;quot;$TAG:latest&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First things first, if you want to take a workflow like this, you must in the
project settings enable an option so GitHub Actions can create PRs. It will not
explode if you don’t do that, but it’s an avoidable workflow failure. Not gonna
lie, I often forget that when setting up new projects!&lt;/p&gt;
&lt;p&gt;As you may have noticed, this bad boy has a lot of triggers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;push&lt;/strong&gt; triggers are for commits on the main branch, or master if your
project is older. I still have some of these out there. The tag trigger is so
the deployment of the new release happens properly on a new release.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;workflow_dispatch&lt;/strong&gt; trigger is there so I can trigger a new release via
the web interface. If ts-proxy receives a Tailscale update from renovate I
don’t want to have to ssh to somewhere to run &lt;code&gt;./make_release patch&lt;/code&gt;. I can do
it all on my phone, via the browser. By default, if I don’t specify, the
release will be of type patch, like in a “x.y.z” scenario it would bump the z.
It can be major, minor, patch or a specific version but this last case I never
used after I set up this named bump system.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;schedule&lt;/strong&gt; is basically to run consistency checks to review on saturday
morning. Some projects that still use Nix would have their flakes updated even
if there is no other activity in the repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now for the jobs part, there is only one. No need for more!&lt;/p&gt;
&lt;p&gt;First, there is the &lt;strong&gt;env&lt;/strong&gt; part, where I setup some variables to use below.&lt;/p&gt;
&lt;p&gt;The steps part I can separate in the following phases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Environment setup&lt;/strong&gt;: sets up Git to be able to commit the consistency check
changes and have all that is required to run the consistency checks and the
build itself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consistency checks&lt;/strong&gt;: some programs have code generation dependencies or
just need to keep lock files up to date, this is the phase that runs those
code generation tools, this includes the Nix flake bump.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pull request creation&lt;/strong&gt;: if the consistency check step left the Git tree in
a dirty state, this part commits this state and creates a PR, if not, the
process continues.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build&lt;/strong&gt;: this is the phase where the actual build happens, in Go projects,
the build happens both for binaries and containers. Nothing is pushed yet in
this phase.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conditional release&lt;/strong&gt;: if the workflow was launched by the user, the
workflow_dispatch route, it will run the make_release without creating a tag
and create a release with an automatically generated changelog. Also, this is
the part that the artifacts and containers are uploaded. Artifacts become
release artifacts and containers are tagged and pushed. If there is no
release, the workflow skips those steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now I am using mostly Mise to setup the build environment. This is not the first
iteration. I used Nix before and had good results with it, but Nix has a little
annoying problem: It forces you to go all-in. Also, it doesn’t allow one to use
a specific version of packages without adding a significant amount of
complexity. And as Nix is mostly Linux specific it limits adoption of the
software being built by it to other platforms. Mise doesn’t have this problem. I
used it to setup the JRE on Windows for a Java program I am doing to a company,
and it worked really well. Also, the environment setup of those projects is
mostly simple enough that Mise could do it in a much simpler and faster way.&lt;/p&gt;
&lt;p&gt;This system could be very likely ported to another CI system, and that may be a
future project, but the way GitHub Actions and Renovate works is simple enough
for this to not be urgent.&lt;/p&gt;
&lt;p&gt;And that’s it. That’s how I am shipping software faster and with less
annoyances. Want me to set it up for you? Let me know at &lt;a href=&quot;mailto:lucas@lew.tec.br&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;lucas@lew.tec.br&lt;/a&gt;!&lt;/p&gt;
</content:encoded></item><item><title>How I entered the state of flow reviewing PRs in nixpkgs</title><link>https://lucasew.github.io/en/post/20241224-nixpkgs-reviewd-flow/</link><guid isPermaLink="true">https://lucasew.github.io/en/post/20241224-nixpkgs-reviewd-flow/</guid><description>The story of how nixpkgs-reviewd became a reality</description><pubDate>Tue, 24 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For those that don’t know, I am a Linux user, specifically a NixOS user (and I
expect memes incoming about this) for over 4 years,
&lt;a href=&quot;https://github.com/lucasew/nixcfg/commit/10ed3d3c9ed02b97bb0d82545499a9fc51a39e63&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;2020-07-37 to be exact&lt;/a&gt;,
and eventually in the Nix world you will need to engage in nixpkgs somehow.&lt;/p&gt;
&lt;p&gt;I have over 100 PRs there, some of them adding modules, some of them adding
packages, some maintaining packages and some failed experiments
(&lt;a href=&quot;https://github.com/lucasew/nixcfg/blob/b754398dd6e699c5bedbf0317e9661894a5f85ec/nix/nodes/bootstrap/port-alloc.nix&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;that some of them I don’t consider exactly failed&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;One struggle I had with reviewing PRs is being a bit too superficial, like I
can’t test stuff properly. Having whiterun now (Ryzen 5600G) helped a lot
building tests because riverwood (i5 7200U) is a little too slow for builds.&lt;/p&gt;
&lt;p&gt;From a few months to now we (the NixOS Brazil group) experimented with
implementations of GitHub Actions workflows to build stuff for us. Most of the
work came from me and &lt;a href=&quot;https://github.com/thiagokokada&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;thiagokokada&lt;/a&gt;. We first
wanted a way to clean up space from the GitHub Actions runtime. This is
&lt;a href=&quot;https://github.com/thiagokokada/free-disk-space&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;his implementation&lt;/a&gt; and this
is
&lt;a href=&quot;https://github.com/lucasew/action-i-only-care-about-nix/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;my implementation&lt;/a&gt;.
My implementation is much more aggressive and ignorant working on files
themselves because, as the name says, I only care about Nix. If it’s not
strictly essential for the workflow runtime I am deleting it. He may have
tweaked it more since I visit the last time tho.&lt;/p&gt;
&lt;p&gt;About the automatic review system, I had built, at first, a workflow that runs
in my
&lt;a href=&quot;https://github.com/lucasew/nixcfg/blob/master/.github/workflows/nixpkgs-review.yml&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;dotfiles repository&lt;/a&gt;,
and he
&lt;a href=&quot;https://github.com/thiagokokada/nixpkgs/blob/fork/actions/nixpkgs-review.nix&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;committed to his nixpkgs fork&lt;/a&gt;.
Different approaches, basically the same results.&lt;/p&gt;
&lt;p&gt;There is nothing stolen in either repo. It’s all public property :)&lt;/p&gt;
&lt;p&gt;Then he &lt;a href=&quot;https://t.me/nixosbrasilofftopic/118034&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;commented this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was just entered end of year collective vacations (this is a thing here at
$WORK) and I was kinda bored looking for a side project when at home.&lt;/p&gt;
&lt;p&gt;Seemed like a perfect fit.&lt;/p&gt;
&lt;p&gt;At first their idea was to write a cronjob that would &lt;code&gt;getUpdates&lt;/code&gt; Telegram then
react to messages, then I told them about Cloudflare Workers.&lt;/p&gt;
&lt;p&gt;I did some stuff with Cloudflare Workers already, and I loved how fast and
responsive things are. No cold starts. At the end of the day it’s all a JS
bundle. Would be fun. This was in 2024-12-19.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Lucão é uma máquina de falar coisa aleatória e implementação duvidosa :P
(translation: Lucão is a random talk and doubtful implementation machine :P)
~thiagokokada, 2024 - &lt;a href=&quot;https://t.me/nixosbrasilofftopic/118049&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He is not wrong.&lt;/p&gt;
&lt;p&gt;I was defending my idea like a good father of ideas would do, showing the
concerns, how the technology deals with common problems in the scope.&lt;/p&gt;
&lt;p&gt;And I was alone because I was basically the only one that did know about this
technology, and that’s when
&lt;a href=&quot;https://github.com/nixosbrasil/nixpkgs-reviewd&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;nixpkgs-reviewd&lt;/a&gt; was born.&lt;/p&gt;
&lt;p&gt;Most of the work happened in two days. Basically the challenge was the
following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A route handler that would treat webhooks from Telegram&lt;/li&gt;
&lt;li&gt;That route handler would parse Telegram commands and react accordingly and if
the command is well formed, it would trigger a GitHub Actions workflow
dispatch workflow with arguments from that command.&lt;/li&gt;
&lt;li&gt;That workflow would trigger either one or three jobs that would run
nixpkgs-review in each target I can setup. One == only linux. Three == linux +
darwin.&lt;/li&gt;
&lt;li&gt;Each job would post the result independently.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This approach had some issues, especially around spammy behavior. I needed to
iterate on this because some people got angry about that, and I am fine with it.
It was a bit rude but, let’s be honest, I deserved it.&lt;/p&gt;
&lt;p&gt;After many iterations and bug fixes the current iteration only posts two
comments. One to warn that the workflow started, so the people on the PR can get
real time information about the state of the build, and another when everything
is done, that would post a comment almost the same as the one &lt;code&gt;nixpkgs-review&lt;/code&gt;
itself would post.&lt;/p&gt;
&lt;p&gt;Yeah, there were suggestions around using multi-target &lt;code&gt;nixpkgs-review&lt;/code&gt; then
setting up workflows as remote builders, but this would cause some issues like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remote builders have to have ssh authentication.&lt;/li&gt;
&lt;li&gt;Remote builders would have to be running for as long as the slowest build is
running.&lt;/li&gt;
&lt;li&gt;To connect the builders, there would need to have some kind of overlay
networking that is fast, so they can reach each other.&lt;/li&gt;
&lt;li&gt;I can get a very close result with much less complexity involved.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, while doing this I learned a GitHub Actions thing I really loved. You can
add user-friendly summaries that appear when the workflow finishes by writing it
to &lt;code&gt;$GITHUB_STEP_SUMMARY&lt;/code&gt;. This helped me to resolve the spammy behavior by
bringing the details of a run in the summary so if someone wants to know
something about the run, the workflow link is there, so you only need to visit
it.&lt;/p&gt;
&lt;p&gt;How it helped me to achieve flow?&lt;/p&gt;
&lt;p&gt;Nixpkgs has some patterns around the PR list.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most of them are &lt;a href=&quot;https://github.com/r-ryantm&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;r-ryantm&lt;/a&gt; automated PRs, so I
could only skip them unless they tag me for being a maintainer.&lt;/li&gt;
&lt;li&gt;There are some first time contributors that bring more out of shape PRs that
need some iterations until buildable state is achievable.&lt;/li&gt;
&lt;li&gt;Other PRs may include manual bumps and &lt;em&gt;backports&lt;/em&gt;, miscellaneous fixes,
people adding update scripts to let the bot cook the next updates and stuff
like that, and refactoring.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The flow came from the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I search for PRs that are not created by &lt;em&gt;r-ryantm&lt;/em&gt; and not stale:
&lt;code&gt;is:open is:pr -author:r-ryantm -label:&amp;quot;2.status: stale&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Open a few in new tab. I only open PRs that already have the rebuild tags in
there.&lt;/li&gt;
&lt;li&gt;If it looks functionally good, I run the bot. If there is &lt;em&gt;darwin&lt;/em&gt; rebuilds I
also run the bot with the &lt;code&gt;+darwin&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;When the bot notifies me that the PR is ready I then look at the results, try
to help debug the package and if it’s alright I check if stuff is in the right
place, commit names OK and if everything seems mergeable I try to bring more
people to look at it either by adding the link to
&lt;a href=&quot;https://discourse.nixos.org/t/prs-ready-for-review/3032&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;“PRs ready for review”&lt;/a&gt;
or adding the reviewers manually.&lt;/li&gt;
&lt;li&gt;I get an email for each round trip, and email is asynchronous communication,
so I look when I am ready.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that none of the steps requires me to wait, stay on the computer and react
fast. I can put a dozen PRs to review then touch some grass.&lt;/p&gt;
&lt;p&gt;I can do most of the work in my phone. Right now only pragmatic tests,
&lt;a href=&quot;https://github.com/NixOS/nixpkgs/pull/367491&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;like the one I did with chime&lt;/a&gt;,
require me to stay at the computer, and those I can queue up and when I go to
the computer those are basically all cached.&lt;/p&gt;
&lt;p&gt;And that’s it. By &lt;em&gt;dogfooding&lt;/em&gt; a tool I created based on shoulders of giants
I’ve never reviewed so many &lt;em&gt;nixpkgs&lt;/em&gt; PRs.&lt;/p&gt;
&lt;p&gt;BTW Merry Christmas to you all, and I hope you have a 2025 as wonderful as 2024
was to me!&lt;/p&gt;
</content:encoded></item><item><title>Hashbang hacking for fun and, maybe in the future, profit</title><link>https://lucasew.github.io/en/post/20240717-hashbang-hacking-for-fun-and-maybe-in-the-future-profit/</link><guid isPermaLink="true">https://lucasew.github.io/en/post/20240717-hashbang-hacking-for-fun-and-maybe-in-the-future-profit/</guid><description>This is the story of how I created a thing to make self contained scripts.</description><pubDate>Wed, 17 Jul 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is the story of how I created a thing to make self contained scripts. It’s
basically a Nix flakes based workaround, so the environment of a script can be
automatically provisioned before the actual script starts without having to
install stuff globally.&lt;/p&gt;
&lt;p&gt;I am a Nix user, and as a Nix user, I tend to put Nix in everything. At least
everything that I think it makes sense.&lt;/p&gt;
&lt;p&gt;Hashbangs are the UNIX-like way to make a text file executable, so it becomes a
program, and a pain point I have is that there is so much boilerplate to have
something simple to start hacking on something. In a non-Nix distro one would
have to install many packages and pray for them to not conflict with each other,
build some kind of boilerplate like a package.json for a Node application, or a
requirements.txt for a Python application, or a pom.xml, or Gradle, for a Java
project. What if I do it a little different?&lt;/p&gt;
&lt;p&gt;For the ones that don’t know, Nix allows one to setup temporary environments in
a way that you don’t need to install stuff globally. Think of it like a Python
virtualenv but using a content addressed storage, so, if you use the exact same
packages in more than one project, these are only downloaded once. And if there
is a native extension in the middle that requires compilation it can just be
downloaded using Nix’s substituters (aka binary caches) if available. And if
stuff needs to be compiled you can setup remote builders to a beefier machine so
the compilation happens somewhere else and you just get the chewed result from
that machine.&lt;/p&gt;
&lt;p&gt;Because stuff changes, this ephemeral shell thing changed too. Right now in Nix
there is a old way (nix-shell, nix-env and stuff) and the new way (flakes, nix
command, right now all behind a feature flag) and some stuff doesn’t map exactly
from the old world to the new world. An example is how development shell works.
In nix-shell the environment is built using the &lt;code&gt;pkgs.mkShell&lt;/code&gt; function, but in
&lt;code&gt;nix develop&lt;/code&gt; it either assumes that this &lt;code&gt;pkgs.mkShell&lt;/code&gt; is already applied or
just add the binaries to the &lt;code&gt;PATH&lt;/code&gt; environment variable ignoring all the other
details such as shell hooks.&lt;/p&gt;
&lt;p&gt;Also, nix-shell allows it to be
&lt;a href=&quot;https://nixos.wiki/wiki/Nix-shell_shebang&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;used in hashbangs&lt;/a&gt; but the old way
is very reliant on the &lt;code&gt;NIX_PATH&lt;/code&gt; environment variable, that is basically system
state, so there is a limbo in the middle. What if I could use the power of
flakes and bring it to a nix-shell-esque style?&lt;/p&gt;
&lt;p&gt;That’s what I tried to do in
&lt;a href=&quot;https://github.com/lucasew/nix-flake-shell&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;nix-flake-shell&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Basically one adds a hashbang running &lt;code&gt;nix run&lt;/code&gt; to the repository and adds a
bunch of directives using comments, that would be ignored by the language but
interpreted using a Nix script. For it to be recognized the line must only have
a &lt;code&gt;#!nix-flake-shell&lt;/code&gt; somewhere.&lt;/p&gt;
&lt;p&gt;This way one can declare fetchers in a way that the result path is available in
an environment variable passed to the payload application, what is the
interpreter, which flake inputs to use, which extra packages to bring with all
it’s bells and whistles and propagated stuff and Nix dark magic for stuff to be
available.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/lucasew/nix-flake-shell/tree/main/tests&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;code&gt;tests&lt;/code&gt;&lt;/a&gt; folder
has examples of usage of the script. If you know some more exoteric languages
and want to contribute with examples feel free to try and play with it, if you
found some rough edges or suggestions please feel free to open an issue or a
pull request.&lt;/p&gt;
&lt;p&gt;BTW this is me exploring the potential of this workaround: &lt;img src=&quot;meme.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
</content:encoded></item><item><title>Do not say hello only</title><link>https://lucasew.github.io/en/post/20210811-naodigaola/</link><guid isPermaLink="true">https://lucasew.github.io/en/post/20210811-naodigaola/</guid><description>Why you should unroll the subject directly</description><pubDate>Wed, 11 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;This post is based in dedicated pages about the subject, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://no-hello.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://no-hello.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Very likely, someone sends you here using a link in some sort of chat, like
Slack, IRC, WhatsApp, Facebook Messenger, and maybe Telegram after you entered
the chat and only sent a “hello”, or a “good afternoon” or any greeting waiting
for a response and is curious why this someone sent a link to here.&lt;/p&gt;
&lt;h1&gt;Did I do anything wrong?&lt;/h1&gt;
&lt;p&gt;Well, yes and no:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It’s polite to start a conversation with an introduction.&lt;/li&gt;
&lt;li&gt;When you arrive only saying “hello” or greeting and waits an answer, you
either &lt;strong&gt;force the other to ignore your greeting&lt;/strong&gt; or &lt;strong&gt;answer trying to
understand the reason of the contact&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s imagine Alice and Fred. Alice is working in something difficult, and it’s
highly concentrated in the task while Fred wants to ask a question to Alice.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[fred] Good morning Alice, I have a question!
[alice] Good morning, what is your question?
[fred] * finally unrolls *
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, Alice got the message from Fred, stopped what she was doing and
asked how she could help. Only when she asked back Fred started typing (at least
in WhatsApp, they often send audios, preferentially when I do not have a
headphone) and Alice tries to resume what she was doing while Fred types and
asks the actual question, which makes Alice lose the focus in her task and very
likely will take some time until she goes back to the flow again.&lt;/p&gt;
&lt;p&gt;Now with another example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[fred] Good morning Alice, * unrolls *?
[alice] * answers *
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Details to be noted:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fred did finish typing when Alice sees the message.&lt;/li&gt;
&lt;li&gt;Alice can instantly see the question and answer it directly, or with some
waiting: She can delay the response until she achieves a checkpoint in her
task where she doesn’t need to maintain the task context in her head.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Another level, isn’t it?&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;How I deal with this stuff&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Priority is always text, if the person didn’t yet ask I send a “send it” when
I am ready.&lt;/li&gt;
&lt;li&gt;If you want me to make some effort to answer fast, do not send audios.&lt;/li&gt;
&lt;li&gt;Phone in silent 24/7 with floating notifications off. I look when I take it,
and I kinda take it a lot.&lt;/li&gt;
&lt;li&gt;If you want the fish it’s because you can pay.&lt;/li&gt;
&lt;li&gt;I always try to answer with a link. The site generally explains better than I
could explain at the moment. I created this blog to reference my own posts out
there hehehe.&lt;/li&gt;
&lt;li&gt;Silence is more efficient than rudeness.&lt;/li&gt;
&lt;li&gt;Want to exchange some ideas? Nice, I won’t bite. I am often chill when I am
not in much hurry, just cut the bs.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>