From c88646ce2d2c0c82efd2a0d0222b737a502cbc96 Mon Sep 17 00:00:00 2001 From: Skyler Grey Date: Thu, 28 Aug 2025 00:07:52 +0000 Subject: [PATCH] ci: translate to tangled Change-Id: nsvuptntpnyklvzqyuvxustxxkvxnmqp We've been using github CI for a while, let's translate everything to tangled format so that we can move across! We need to put our CI in the root of our monorepo as otherwise it won't run on our tangled spindle... --- .tangled/workflows/github.yml | 22 ++++ .tangled/workflows/packetmix-build.yml | 111 ++++++++++++++++++ .../packetmix-npins-duplicate-check.yml | 25 ++++ .tangled/workflows/packetmix-treefmt.yaml | 63 ++++++++++ .tangled/workflows/reuse.yml | 17 +++ packetmix/.github/workflows/eval.yml | 51 -------- packetmix/.github/workflows/nixos.yml | 69 ----------- .../workflows/npins-duplicate-check.yml | 38 ------ packetmix/.github/workflows/reuse.yml | 24 ---- packetmix/.github/workflows/tangled.yml | 33 ------ packetmix/.github/workflows/treefmt.yaml | 51 -------- packetmix/.github/workflows/update-npins.yml | 63 ---------- .../systems/midnight/packetmix-update.nix | 26 ++++ packetmix/workspace.josh | 1 + 14 files changed, 265 insertions(+), 329 deletions(-) create mode 100644 .tangled/workflows/github.yml create mode 100644 .tangled/workflows/packetmix-build.yml create mode 100644 .tangled/workflows/packetmix-npins-duplicate-check.yml create mode 100644 .tangled/workflows/packetmix-treefmt.yaml create mode 100644 .tangled/workflows/reuse.yml delete mode 100644 packetmix/.github/workflows/eval.yml delete mode 100644 packetmix/.github/workflows/nixos.yml delete mode 100644 packetmix/.github/workflows/npins-duplicate-check.yml delete mode 100644 packetmix/.github/workflows/reuse.yml delete mode 100644 packetmix/.github/workflows/tangled.yml delete mode 100644 packetmix/.github/workflows/treefmt.yaml delete mode 100644 packetmix/.github/workflows/update-npins.yml create mode 100644 packetmix/systems/midnight/packetmix-update.nix diff --git a/.tangled/workflows/github.yml b/.tangled/workflows/github.yml new file mode 100644 index 0000000..a438a5b --- /dev/null +++ b/.tangled/workflows/github.yml @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2025 FreshlyBakedCake +# +# SPDX-License-Identifier: MIT + +when: + - event: ["push"] + branch: ["release"] + +engine: nixery + +steps: + - name: Write SSH Key + command: | + echo $GITHUB_SSH_KEY > ssh_key + chmod 600 ssh_key + - name: Push to GitHub + command: | + export GIT_SSH_COMMAND="ssh -i $(realpath ./ssh_key) -o StrictHostKeyChecking=no" + git remote add github git@github.com:freshlybakedca.ke/Patisserie + git fetch --unshallow origin + git fetch github + git push tangled HEAD diff --git a/.tangled/workflows/packetmix-build.yml b/.tangled/workflows/packetmix-build.yml new file mode 100644 index 0000000..af02d22 --- /dev/null +++ b/.tangled/workflows/packetmix-build.yml @@ -0,0 +1,111 @@ +# SPDX-FileCopyrightText: 2025 FreshlyBakedCake +# +# SPDX-License-Identifier: MIT +when: + - event: ["push", "pull_request"] + branch: ["main"] + +engine: nixery + +dependencies: + nixpkgs: + - lix + - gnugrep + - openssh + +steps: + - name: Get remote builds SSH key + command: | + echo "$KEY_SSH_REMOTE_BUILD" > /tmp/key-ssh-remote-build + chmod 600 /tmp/key-ssh-remote-build + - name: Add base system files + command: | + # Let us SSH to midnight by name + echo "192.168.0.6 midnight" >> /etc/hosts + + # Avoid missing user with UID 0 error on ssh... + echo "root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash" >> /etc/passwd + + # Turn off SSH host key checking + echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config + echo "UserKnownHostsFile /dev/null" >> /etc/ssh/ssh_config + + echo "Host midnight" >> /etc/ssh/ssh_config + echo " User remoteBuilds" >> /etc/ssh/ssh_config + echo " IdentityFile /tmp/key-ssh-remote-build" >> /etc/ssh/ssh_config + + echo "extra-experimental-features = nix-command" >> /etc/nix/nix.conf + echo "max-jobs = 0" >> /etc/nix/nix.conf + echo "builders = ssh-ng://remoteBuilds@midnight?ssh-key=/tmp/key-ssh-remote-build x86_64-linux" >> /etc/nix/nix.conf + - name: Evaluate all systems + command: | + set +e + set -o pipefail + + eval_out=$(nix eval \ + -f ./packetmix/nilla.nix packages.allNixOSSystems.result.x86_64-linux.drvPath \ + --show-trace --raw \ + 2>&1 >/tmp/systems-drv-path | tee /dev/stderr) + eval_status=$? + + if [ $eval_status -ne 0 ]; then + echo "Evaluating your configuration failed with exit code $eval_status" + echo "Please fix this and squash into your existing commits" + exit $eval_status + fi + + eval_warns=$(echo "$eval_out" | grep "evaluation warning:" || true) + + if [ -n "$eval_warns" ]; then + echo "There were some warnings while evaluating your systems:" + echo "$eval_warns" + echo "Please fix these and squash into your existing commits" + exit 1 + fi + - name: Evaluate all homes + command: | + set +e + set -o pipefail + + eval_out=$(nix eval \ + -f ./packetmix/nilla.nix packages.allHomes.result.x86_64-linux.drvPath \ + --show-trace --raw \ + 2>&1 >/tmp/homes-drv-path | tee /dev/stderr) + eval_status=$? + + if [ $eval_status -ne 0 ]; then + echo "Evaluating your configuration failed with exit code $eval_status" + echo "Please fix this and squash into your existing commits" + exit $eval_status + fi + + eval_warns=$(echo "$eval_out" | grep "evaluation warning:" || true) + + if [ -n "$eval_warns" ]; then + echo "There were some warnings while evaluating your homes:" + echo "$eval_warns" + echo "Please fix these and squash into your existing commits" + exit 1 + fi + - name: Build all systems + command: | + set -e + nix-copy-closure \ + --to 'midnight' \ + "$(cat /tmp/systems-drv-path)" + nix build \ + "$(cat /tmp/systems-drv-path)"'^*' \ + --store 'ssh-ng://remoteBuilds@midnight?ssh-key=/tmp/key-ssh-remote-build' \ + --eval-store auto \ + --show-trace --print-out-paths + - name: Build all homes + command: | + set -e + nix-copy-closure \ + --to 'midnight' \ + "$(cat /tmp/homes-drv-path)" + nix build \ + "$(cat /tmp/homes-drv-path)"'^*' \ + --store 'ssh-ng://remoteBuilds@midnight?ssh-key=/tmp/key-ssh-remote-build' \ + --eval-store auto \ + --show-trace --print-out-paths diff --git a/.tangled/workflows/packetmix-npins-duplicate-check.yml b/.tangled/workflows/packetmix-npins-duplicate-check.yml new file mode 100644 index 0000000..42e5d65 --- /dev/null +++ b/.tangled/workflows/packetmix-npins-duplicate-check.yml @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2025 FreshlyBakedCake +# +# SPDX-License-Identifier: MIT + +when: + - event: ["push", "pull_request"] + branch: ["main"] + +engine: nixery + +dependencies: + nixpkgs: + - jq + +steps: + - name: Check for duplicate npins keys + command: | + dupes=$(jq --stream 'select((.[0] | length == 3) and (.[0][2] == "type")) | .[0][1]' ./packetmix/npins/sources.json | sort | uniq -d) + # We have to use the stream parser else jq will get rid of the duplicates + + if [ ! -z "$dupes" ]; then + echo "The following keys are duplicated in your npins pins. By default, npins will take *the later definition*:" + echo "$dupes" + exit 1 + fi diff --git a/.tangled/workflows/packetmix-treefmt.yaml b/.tangled/workflows/packetmix-treefmt.yaml new file mode 100644 index 0000000..b9bcca1 --- /dev/null +++ b/.tangled/workflows/packetmix-treefmt.yaml @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: 2025 FreshlyBakedCake +# +# SPDX-License-Identifier: MIT + +when: + - event: ["push", "pull_request"] + branch: ["main"] + +engine: nixery + +dependencies: + nixpkgs: + - lix + - openssh + +steps: + - name: Get remote builds SSH key + command: | + echo "$KEY_SSH_REMOTE_BUILD" > /tmp/key-ssh-remote-build + chmod 600 /tmp/key-ssh-remote-build + - name: Add base system files + command: | + # Let us SSH to midnight by name + echo "192.168.0.6 midnight" >> /etc/hosts + + # Avoid missing user with UID 0 error on ssh... + echo "root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash" >> /etc/passwd + + # Turn off SSH host key checking + echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config + echo "UserKnownHostsFile /dev/null" >> /etc/ssh/ssh_config + + echo "Host midnight" >> /etc/ssh/ssh_config + echo " User remoteBuilds" >> /etc/ssh/ssh_config + echo " IdentityFile /tmp/key-ssh-remote-build" >> /etc/ssh/ssh_config + + echo "extra-experimental-features = nix-command" >> /etc/nix/nix.conf + echo "sandbox = false" >> /etc/nix/nix.conf + echo "max-jobs = 0" >> /etc/nix/nix.conf + - name: Ensure files are formatted with treefmt + command: | + set -e + + treefmt=$(nix build \ + -f ./packetmix/nilla.nix packages.treefmt.result.x86_64-linux \ + --store 'ssh-ng://remoteBuilds@midnight?ssh-key=/tmp/key-ssh-remote-build' \ + --eval-store auto \ + --show-trace --print-out-paths) + nix copy \ + --from 'ssh-ng://remoteBuilds@midnight?ssh-key=/tmp/key-ssh-remote-build' \ + --no-check-sigs \ + "$treefmt" + + set +e + + "${treefmt}/bin/treefmt" --ci -C packetmix + exitCode=$? + + if [ $exitCode -ne 0 ]; then + echo "Your code isn't formatted correctly, please run 'nilla fmt' and squash it into each commit" + fi + + exit $exitCode diff --git a/.tangled/workflows/reuse.yml b/.tangled/workflows/reuse.yml new file mode 100644 index 0000000..6dbe442 --- /dev/null +++ b/.tangled/workflows/reuse.yml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2025 FreshlyBakedCake +# +# SPDX-License-Identifier: MIT + +when: + - event: ["push", "pull_request"] + branch: ["main"] + +engine: nixery + +dependencies: + nixpkgs: + - reuse + +steps: + - name: Check for REUSE compliance + command: reuse lint diff --git a/packetmix/.github/workflows/eval.yml b/packetmix/.github/workflows/eval.yml deleted file mode 100644 index 3c150d0..0000000 --- a/packetmix/.github/workflows/eval.yml +++ /dev/null @@ -1,51 +0,0 @@ -# SPDX-FileCopyrightText: 2025 FreshlyBakedCake -# -# SPDX-License-Identifier: MIT - -name: Evaluate NixOS systems and Homes - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - - workflow_dispatch: - -jobs: - evaluate: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Lix - uses: samueldr/lix-gha-installer-action@8dc19fbd6451fa106a68ecb2dafeeeb90dff3a29 - with: - extra_nix_config: "experimental-features = nix-command" - - - run: cd $GITHUB_WORKSPACE - - - name: Evaluate all systems - run: | - eval_out=$(nix-instantiate ./ci.nix -A packages.allNixOSSystems.result.x86_64-linux --add-root ./system-root 2>&1 | tee /dev/stderr) - eval_warns=$(echo "$eval_out" | grep "evaluation warning:" || true) - - if [ -n "$eval_warns" ]; then - echo "There were some warnings while evaluating your systems:" - echo "$eval_warns" - echo "Please fix these and squash into your existing commits" - exit 1 - fi - - - name: Evaluate all homes - run: | - eval_out=$(nix-instantiate ./ci.nix -A packages.allNixOSSystems.result.x86_64-linux --add-root ./home-root 2>&1 | tee /dev/stderr) - eval_warns=$(echo "$eval_out" | grep "evaluation warning:" || true) - - if [ -n "$eval_warns" ]; then - echo "There were some warnings while evaluating your homes:" - echo "$eval_warns" - echo "Please fix these and squash into your existing commits" - exit 1 - fi diff --git a/packetmix/.github/workflows/nixos.yml b/packetmix/.github/workflows/nixos.yml deleted file mode 100644 index 966ccd7..0000000 --- a/packetmix/.github/workflows/nixos.yml +++ /dev/null @@ -1,69 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Collabora Productivity Limited -# SPDX-FileCopyrightText: 2025 FreshlyBakedCake -# SPDX-FileCopyrightText: 2022 Markus Dobel -# -# SPDX-License-Identifier: MIT - -name: Build and cache NixOS systems and Homes - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - - workflow_dispatch: - -concurrency: # Since as this check is expensive, it's a bad idea to keep running it when we push new commits... - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Clean up runner - uses: easimon/maximize-build-space@c28619d8999a147d5e09c1199f84ff6af6ad5794 - with: - overprovision-lvm: true # needed for our mount path to be /nix - we'll cope with the weird errors this option suggests may arise as it'd be untenable to constantly readjust root-reserve-mb - remove-dotnet: true - remove-android: true - remove-haskell: true - remove-codeql: true - remove-docker-images: true - build-mount-path: /nix - build-mount-path-ownership: root:root - - - uses: actions/checkout@v4 - - - name: Install Lix - uses: samueldr/lix-gha-installer-action@8dc19fbd6451fa106a68ecb2dafeeeb90dff3a29 - with: - extra_nix_config: "experimental-features = nix-command" - - - run: cd $GITHUB_WORKSPACE - - - name: Set up a cachix cache - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad - with: - # Name of a cachix cache to push and pull/substitute - name: "freshlybakedcake" - authToken: "${{ secrets.CACHIX_TOKEN }}" - - # see https://git.lix.systems/lix-project/lix/issues/545 - - name: Fix apparmor configuration for building Lix - run: | - sudo sysctl -w kernel.apparmor_restrict_unprivileged_unconfined=0 - sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - - - name: Build all systems - run: nix build -f ./ci.nix packages.allNixOSSystems.result.x86_64-linux --show-trace - - - name: Build all homes - run: nix build -f ./ci.nix packages.allHomes.result.x86_64-linux --show-trace - - - if: github.event_name == 'push' - name: Push to release branch - run: | - git push -f origin HEAD:release diff --git a/packetmix/.github/workflows/npins-duplicate-check.yml b/packetmix/.github/workflows/npins-duplicate-check.yml deleted file mode 100644 index 824453c..0000000 --- a/packetmix/.github/workflows/npins-duplicate-check.yml +++ /dev/null @@ -1,38 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. -# SPDX-FileCopyrightText: 2025 FreshlyBakedCake -# -# SPDX-License-Identifier: CC0-1.0 - -name: Check for npins duplicate keys -# As it's possible to specify duplicate keys in npins, we need to route them -# out... Duplicated npins keys cause the earlier definition of a pin to be -# silently ignored, potentially causing confusion about what version is being -# used - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - workflow_dispatch: - -permissions: - contents: read - -jobs: - npins-duplicate-checker: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Check for duplicate npins keys - run: | - dupes=$(jq --stream 'select((.[0] | length == 3) and (.[0][2] == "type")) | .[0][1]' $GITHUB_WORKSPACE/npins/sources.json | sort | uniq -d) - # We have to use the stream parser else jq will get rid of the duplicates - - if [ ! -z "$dupes" ]; then - echo "The following keys are duplicated in your npins pins. By default, npins will take *the later definition*:" - echo "$dupes" - exit 1 - fi diff --git a/packetmix/.github/workflows/reuse.yml b/packetmix/.github/workflows/reuse.yml deleted file mode 100644 index 6738ea0..0000000 --- a/packetmix/.github/workflows/reuse.yml +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. -# -# SPDX-License-Identifier: CC0-1.0 - -name: Check REUSE compliance - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -permissions: - contents: read - -jobs: - reuse: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Check REUSE compliance - uses: fsfe/reuse-action@a46482ca367aef4454a87620aa37c2be4b2f8106 diff --git a/packetmix/.github/workflows/tangled.yml b/packetmix/.github/workflows/tangled.yml deleted file mode 100644 index 060524c..0000000 --- a/packetmix/.github/workflows/tangled.yml +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-FileCopyrightText: 2025 FreshlyBakedCake -# -# SPDX-License-Identifier: MIT - -name: Mirror to tangled.sh - -on: - push: - branches: [ "main", "release" ] - -jobs: - tangled-push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - run: cd $GITHUB_WORKSPACE - - - name: Write out SSH key - env: - TANGLED_SSH_KEY: ${{ secrets.TANGLED_SSH_KEY }} - run: | - echo "$TANGLED_SSH_KEY" > ../tangled_ssh_key - chmod 600 ../tangled_ssh_key - - - name: Push to tangled - run: | - git remote add tangled git@tangled.sh:freshlybakedca.ke/packetmix - export GIT_SSH_COMMAND="ssh -i $(realpath ../tangled_ssh_key) -o StrictHostKeyChecking=no" - git fetch --unshallow origin - git fetch tangled - git push tangled HEAD diff --git a/packetmix/.github/workflows/treefmt.yaml b/packetmix/.github/workflows/treefmt.yaml deleted file mode 100644 index 65046ed..0000000 --- a/packetmix/.github/workflows/treefmt.yaml +++ /dev/null @@ -1,51 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. -# SPDX-FileCopyrightText: 2025 FreshlyBakedCake -# -# SPDX-License-Identifier: CC0-1.0 - -name: Ensure files are formatted with treefmt - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - workflow_dispatch: - -permissions: - contents: read - -jobs: - treefmt-check: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install Nix - uses: cachix/install-nix-action@526118121621777ccd86f79b04685a9319637641 - with: - extra_nix_config: "experimental-features = nix-command" - - - run: cd $GITHUB_WORKSPACE - - - name: Set up a cachix cache - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad - with: - # Name of a cachix cache to push and pull/substitute - name: "freshlybakedcake" - authToken: "${{ secrets.CACHIX_TOKEN }}" - - - name: Ensure all files are formatted - run: | - set +e - - nix-shell ./ci.nix -A shells.default.result.x86_64-linux --run 'treefmt --ci' - - exitCode=$? - - if [ $exitCode -ne 0 ]; then - echo "Your code isn't formatted correctly, please run 'nilla fmt' and squash it into each commit" - fi - - exit $exitCode diff --git a/packetmix/.github/workflows/update-npins.yml b/packetmix/.github/workflows/update-npins.yml deleted file mode 100644 index fd71540..0000000 --- a/packetmix/.github/workflows/update-npins.yml +++ /dev/null @@ -1,63 +0,0 @@ -# SPDX-FileCopyrightText: 2025 FreshlyBakedCake -# -# SPDX-License-Identifier: MIT - -name: Update npins dependencies -# This is inspired by https://github.com/getchoo/update-npins - though I wrote it from scratch -# I'm not using it as I need to run the npins command in a shell - -on: - schedule: - - cron: "48 02 * * *" # Time is pretty arbitrary - the only important thing is that it's unlikely to be a peak time... - - workflow_dispatch: - -jobs: - update-npins: - runs-on: ubuntu-latest - - steps: - - name: Generate GitHub token for RoboPâtissière - uses: actions/create-github-app-token@v1 - id: generate-token - with: - app-id: ${{ secrets.CUSTOM_GITHUB_APP_ID }} - private-key: ${{ secrets.CUSTOM_GITHUB_APP_PRIVATE_KEY }} - - - uses: actions/checkout@v4 - - - name: Install Nix - uses: cachix/install-nix-action@526118121621777ccd86f79b04685a9319637641 - with: - extra_nix_config: "experimental-features = nix-command" - - - run: cd $GITHUB_WORKSPACE - - - name: Set up a cachix cache - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad - with: - # Name of a cachix cache to push and pull/substitute - name: "freshlybakedcake" - authToken: "${{ secrets.CACHIX_TOKEN }}" - - - name: Run npins update - run: nix-shell ./ci.nix -A shells.default.result.x86_64-linux --run 'npins update' - - - name: Create a pull request - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e - id: pull-request - with: - branch: auto/update-npins - commit-message: "chore: bump npins dependencies" - token: ${{ steps.generate-token.outputs.token }} - title: "chore: bump npins dependencies" - author: "RoboPâtissière[bot] <213641064+robopatissiere[bot]@users.noreply.github.com>" - committer: "RoboPâtissière[bot] <213641064+robopatissiere[bot]@users.noreply.github.com>" - body: | - This is an automated npins dependency bump - - - if: steps.pull-request.outputs.pull-request-operation == 'created' - name: Automerge pull request - run: gh pr merge --rebase --auto "${{ steps.pull-request.outputs.pull-request-number }}" - env: - GH_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/packetmix/systems/midnight/packetmix-update.nix b/packetmix/systems/midnight/packetmix-update.nix new file mode 100644 index 0000000..81badb4 --- /dev/null +++ b/packetmix/systems/midnight/packetmix-update.nix @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2025 FreshlyBakedCake +# +# SPDX-License-Identifier: MIT + +{ + systemd.services."update-packetmix-npins" = { + script = '' + export WORKING_DIR=mktemp -d + export GIT_SSH_COMMAND="ssh -i /etc/ssh/ssh_host_ed25519_key" + git clone git@tangled.sh:freshlybakedca.ke/patisserie $WORKING_DIR + cd $WORKING_DIR/packetmix + git checkout -b auto/update-npins + npins update + git add . + git commit -am "chore: bump npins dependencies" + git push + # TODO: Make web request to create PR + rm -rf $WORKING_DIR + ''; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + startAt = "*-*-* 00:00:00"; + }; +} diff --git a/packetmix/workspace.josh b/packetmix/workspace.josh index a1b06c1..2ebc803 100644 --- a/packetmix/workspace.josh +++ b/packetmix/workspace.josh @@ -1 +1,2 @@ +::.tangled/ ::LICENSES/ -- 2.43.0