add new post about this repo packaging.
added: new post folder about how i've packaged this repository with ad hoc env and pdf build process with nix updated: src/configs/presnterm.yaml, modified to handle additional arguments in front matter
This commit is contained in:
parent
438582a21b
commit
b8b8324b10
@ -1,5 +1,5 @@
|
||||
{
|
||||
description = "An empty flake template that you can adapt to your own environment";
|
||||
description = "An flake to provide dev and build environnement for presenterm post production";
|
||||
|
||||
# Flake inputs
|
||||
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
options:
|
||||
strict_front_matter_parsing: false
|
||||
export:
|
||||
dimensions:
|
||||
columns: 108
|
||||
|
||||
BIN
src/posts/general_nix/post_packaging/cover.jpg
Normal file
BIN
src/posts/general_nix/post_packaging/cover.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
src/posts/general_nix/post_packaging/flake_schema.png
Normal file
BIN
src/posts/general_nix/post_packaging/flake_schema.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 312 KiB |
42
src/posts/general_nix/post_packaging/packaging.nix
Normal file
42
src/posts/general_nix/post_packaging/packaging.nix
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
description = "An flake to provide dev and build environnement for presenterm post production";
|
||||
|
||||
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
|
||||
|
||||
outputs = inputs: {
|
||||
devShells = forEachSupportedSystem ( { pkgs }: {
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
presenterm
|
||||
python313Packages.weasyprint
|
||||
];
|
||||
};
|
||||
} );
|
||||
|
||||
packages = forEachSupportedSystem ( { pkgs }: {
|
||||
default = pkgs.stdenv.mkDerivation {
|
||||
inherit (pkgs) system;
|
||||
name = "linkedin-shoblog-posts";
|
||||
src = ./src;
|
||||
buildInputs = with pkgs; [
|
||||
presenterm
|
||||
python313Packages.weasyprint
|
||||
];
|
||||
buildPhase =
|
||||
let
|
||||
font_dir = pkgs.nerd-fonts.jetbrains-mono;
|
||||
config = pkgs.writeTextFile {
|
||||
name = "presenterm.conf";
|
||||
text = ''
|
||||
# presenterm configuration
|
||||
'';
|
||||
};
|
||||
in
|
||||
''
|
||||
export PRES_CONFIG=${config}
|
||||
python scripts/build.py
|
||||
'';
|
||||
};
|
||||
} );
|
||||
};
|
||||
}
|
||||
251
src/posts/general_nix/post_packaging/post_packaging.md
Normal file
251
src/posts/general_nix/post_packaging/post_packaging.md
Normal file
@ -0,0 +1,251 @@
|
||||
---
|
||||
options:
|
||||
command_prefix: "pr:"
|
||||
strict_front_matter_parsing: false
|
||||
theme:
|
||||
name: tokyonight-storm
|
||||
override:
|
||||
default:
|
||||
# colors:
|
||||
# foreground: "4c4f69"
|
||||
# background: "ffffff"
|
||||
code:
|
||||
alignment: center
|
||||
palette:
|
||||
colors:
|
||||
base00: "24283B"
|
||||
base01: "16161E"
|
||||
base02: "343A52"
|
||||
base03: "444B6A"
|
||||
base04: "787C99"
|
||||
base05: "A9B1D6"
|
||||
base06: "CBCCD1"
|
||||
base07: "D5D6DB"
|
||||
base08: "C0CAF5"
|
||||
base09: "A9B1D6"
|
||||
base0A: "0DB9D7"
|
||||
base0B: "9ECE6A"
|
||||
base0C: "B4F9F8"
|
||||
base0D: "2AC3DE"
|
||||
base0E: "BB9AF7"
|
||||
base0F: "F7768E"
|
||||
lang: fr
|
||||
---
|
||||
presenterm build process with nix
|
||||
===
|
||||
```file +line_numbers
|
||||
path: packaging.nix
|
||||
language: nix
|
||||
```
|
||||
Hier je me suis dit que j'allais faire un petit repo avec les différents posts de
|
||||
cette série, histoire de rendre les textes source accessible entre autre pour les
|
||||
personnes malvoyantes ou juste pour ceux ne souhaitant pas lire des images en 24px * 24px.
|
||||
Problème, mon cerveau un peu mal fichu, c'est aussi dit "tient, et si tu en profitais
|
||||
pour faire un flake avec un environnement dev pour qui voudrait preview tes slides
|
||||
sans avoir à installer presenterm puis "hey mais attend, tu pourrais aussi faire
|
||||
en sorte de générer un package avec nix qui contient tous les PDF", ce qui inclut
|
||||
donc de les générer au moment du packaging.
|
||||
Et donc après quelques heures de trifouillage, me voici pour vous présenter mes
|
||||
bêtises.
|
||||
Vous connaissez la routine, lancez spotify et c'est parti pour un peu de lecture
|
||||
# album du jour
|
||||
## American idiot - Green day
|
||||

|
||||
<!-- pr:end_slide -->
|
||||
OK, comment ça marche ?
|
||||
===
|
||||
Avant de parler de ce que sont les flakes et de leur intérêt dans l'écosystème
|
||||
de nix, commençons par la base, qu'est-ce qu'un package en nix ? "Simplement",
|
||||
une fonction qui décrit un process de build, pour reprendre les exemples des articles
|
||||
précédents, pour le packaging des assets de mon site avec **Vue**, nous avons une
|
||||
fonction prenant en entrée les dépendances nécessaires pour le process de build,
|
||||
puis décrivant ce dernier, puis retournant uniquement les assets builder sous la
|
||||
la forme d'un path dans le store nix. Grossièrement, en terme de code cela donnerais
|
||||
quelque chose du style:
|
||||
```nix
|
||||
# package.nix
|
||||
{ pkgs }: pkgs.stdenv.mkDerivation {
|
||||
pname = "mon super website";
|
||||
version = "3.14";
|
||||
src = pkgs.fetchgit {
|
||||
url = "http://git.shobu.fr/shoblog/front";
|
||||
rev = "069d2a5bfa4c4024063c25551d5201aeaf921cb3";
|
||||
sha256 = "sha256-MlqJOoMSRuYeG+jl8DFgcNnpEyeRgDCK2JlN9pOqBWA=";
|
||||
};
|
||||
buildInputs = with pkgs; [
|
||||
node
|
||||
yarn
|
||||
];
|
||||
buildPhase = ''yarn build'';
|
||||
installPHase = ''
|
||||
mkdir -p $out/dist
|
||||
cp dist $out
|
||||
'';
|
||||
}
|
||||
```
|
||||
L'exemple est bien sûr quelque peu simplifié, mais dans les grandes lignes :
|
||||
* `{ pkgs }: {}`: constitue notre fonction, avec en argument *pkgs* qui correspond
|
||||
à une instance de nixpkgs.
|
||||
* `pkgs.stdenv.mkDerivation`: est la fonction la plus basique nous permettant de créer
|
||||
un package, les autres fonction, comme mkYarnPackage, étendent cette dernière.
|
||||
Cette fonction prend elle aussi plusieurs arguments qu'elle vas utiliser pour builder
|
||||
notre package
|
||||
* `pname` et `version`: le nom de notre package et sa version
|
||||
* `src`: les fichiers qui serons accessible dans notre environnement de build et
|
||||
qui constituent la source de notre package.
|
||||
* `buildInputs`: les paquets qui serons accessibles dans notre environnement
|
||||
de build.
|
||||
* `buildPhase` et `installPhase`: Les hook qui décrivent comment builder et installer
|
||||
notre paquet. Il existe d'autre hooks pour d'autres usages décris dans la documentation.
|
||||
|
||||
Vous aurez remarqué de votre œil attentif que la fonction s'appelle `mkDerivation`,
|
||||
et non pas `mkPackage` par exemple comme on aurait pu s'y attendre. Pourquoi ça ?
|
||||
Dans nix, la dérivation est le bloc fondamental du système de build de nix, un
|
||||
package n'étant qu'une forme de dérivation. Pour rester simple, je resterais sur
|
||||
l'appellation plus classique de "package".
|
||||
Un souci de cette approche, c'est que le type du retour de notre fonction n'est pas
|
||||
spécialement défini, on pourrait avoir un package comme ici, mais aussi une shell avec
|
||||
mkShell, ou un host dans le cas d'une configuration nixos. Le seul moyen de le savoir,
|
||||
c'est d'avoir une sémantique propre sur ses noms de fichiers. De même, les outils autour
|
||||
de nix vont s'attendre à un certain type de retour, mais vont quand même builder la dérivation
|
||||
avant de pouvoir déterminer celui-ci. Par exemple, nix-shell vas s'attendre à avoir le résultat
|
||||
d'un mkShell pour fonctionner, mais n'aura pas de moyen de le savoir avant d'avoir interprété
|
||||
la fonction fourni.
|
||||
C'est ainsi que pour résoudre ce problème d'uniformité (et quelques autres raisons), les **flakes**
|
||||
on ete mis en place.
|
||||
<!-- pr:end_slide -->
|
||||
les flakes c'est quoi ?
|
||||
===
|
||||
```nix
|
||||
{
|
||||
description = "";
|
||||
inputs = {};
|
||||
outputs = inputs: {};
|
||||
}
|
||||
```
|
||||
Simplement, un flake est un dossier dans lequel se trouve un fichier `flake.nix`
|
||||
contenant un attribut set avec les attributs suivants :
|
||||
* `description`: la description de ce que fait le flake.
|
||||
* `inputs`: un attribut set contenant les dépendances du flake, typiquement une instance
|
||||
de nixpkgs. Classiquement, chaque input est un repo contenant un autre flake, sur github,
|
||||
gitlab ou en local et peut être pin sur une branche ou un commit specifique.
|
||||
* `outputs`: une fonction ayant pour parametre le résultat de l'interprétation des inputs
|
||||
et retournant un attribut set ou chaque attribut est un résultat possible retourné par
|
||||
notre flake, bien qu'il existe des attributs standard utilisé par les outils de nix
|
||||
(nix build, nix shell, nix develop), le développeur est libre de retourner ce qu'il veut,
|
||||
ce qui permet à des outils comme *colmena* de créer leur propres standards.
|
||||
Pour un package, on vas ainsi retrouver l'attribut `packages.<architecture>.<paquet>` indiquant
|
||||
que le flake peut fournir un ou plusieurs packages pour une architecture donnée.
|
||||
Ainsi, le flake suivant
|
||||
```nix
|
||||
{
|
||||
description = "un flake d'exemple";
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
|
||||
};
|
||||
outputs = inputs: {
|
||||
packages."x86_64-linux".default =
|
||||
with import inputs.nixpkgs {system = "x86_64-linux";};
|
||||
writeShellScriptBin "hello" "echo 'world hello'";
|
||||
}
|
||||
}
|
||||
```
|
||||
On donne ici en input la dernière version stable de nixpkgs. Dans notre fonction
|
||||
d'output, on déclare un package nommé "default" et on fait appel à la fonction
|
||||
`writeShellScriptBin` pour le créer, cette fonction prend en argument un nom
|
||||
de fichier et une chaine de caractère et créer un fichier exécutable contenant
|
||||
le code du deuxième argument, utilisant `sh` pour l'exécution.
|
||||
Une fois notre package builder avec `nix build`, on se retrouve avec notre
|
||||
exécutable rangé dans un `./results/bin/hello`. On peut aussi directement lancer
|
||||
ce dernier avec `nix run`. Ces nouvelles commandes, différentes des classiques
|
||||
`nix-shell` et `nix-build` sont intimement liés aux flakes.
|
||||
En effet, contrairement aux commandes classiques qui lisent juste l'output et tentent de l'interpréter,
|
||||
ces dernières vont plutôt chercher si une output spécifique est présente.
|
||||
Ainsi, un simple `nix build` vas chercher s'il y à une output
|
||||
`packages.<system>`.default, et le cas échéant, builder cette dernière. `<system>`
|
||||
étant l'architecture courante du système, et il est bien sur possible de remplacer
|
||||
**default** par un nom spécifique de paquet dans le cas où la flake expose plusieurs paquets.
|
||||
Quand à `nix run`, elle va d'abord chercher au niveau de l'output
|
||||
`apps.<system>.default`, et si cette dernière n'est pas présente,
|
||||
`packages.<system>.default`.
|
||||
Il existe tout une variété d'output standard dont il est possible de retrouver
|
||||
la liste dans le manuel de nix.
|
||||

|
||||
<!-- pr:end_slide -->
|
||||
Et donc dans notre cas ?
|
||||
===
|
||||
```file +line_numbers {2-4}
|
||||
path: packaging.nix
|
||||
language: nix
|
||||
```
|
||||
Passons rapidement sur les deux premières lignes, on déclare une jolie description
|
||||
ainsi qu'une input nommée `nixpkgs` dont l'url pointera vers le dernier commit
|
||||
de la branche unstable de nixpgks. Une syntaxe plus standard aurait été
|
||||
`github:Nixos/nixpkgs/nixos-unstable`, ici on utilise flakehub qui est un host
|
||||
centralisé pour toute sorte de flakes.
|
||||
<!-- pr:end_slide -->
|
||||
```file +line_numbers {7-14}
|
||||
path: packaging.nix
|
||||
language: nix
|
||||
```
|
||||
Tout d'abord, on déclare une devShell, qui est le système d'environnement temporaire
|
||||
de nix, fournissant presenterm ainsi que la librairie weasyprint permettant
|
||||
d'exporter les slides au format PDF.
|
||||
La fonction `mkShell` peut prendre plusieurs options dont voici les plus courantes:
|
||||
```nix
|
||||
pkgs.mkShell {
|
||||
# Les packages que vous fournissez à votre environnement
|
||||
packages = with pkgs; [ ];
|
||||
|
||||
# Pour set vos variable d'environnement
|
||||
env = { };
|
||||
|
||||
# Et ici vous pouvez définir un bout de code qui sera exécuter au lancement
|
||||
# de l'environnement.
|
||||
shellHook = '''';
|
||||
};
|
||||
```
|
||||
<!-- pr:end_slide -->
|
||||
|
||||
```file +line_numbers {17-24}
|
||||
path: packaging.nix
|
||||
language: nix
|
||||
```
|
||||
Avant de définir le build process, voyons la configuration de notre paquet.
|
||||
Si vous avez déjà lu les articles précédents, cela ne devrait pas avoir trop
|
||||
de secrets !
|
||||
`inherit (pkgs) system;`: Juste du sucre syntaxique pour ne pas taper
|
||||
`system = pkgs.system;`, oui bon dans le cas présent on gagne pas des masses de
|
||||
temps, mais c'est une bonne pratique à avoir >w<.
|
||||
`name`, `src`, `buildInputs`: Le nom de notre paquet, les sources à fournir lors
|
||||
du build, et les paquets que l'ont fournis à ce dernier, rien de neuf !
|
||||
<!-- pr:end_slide -->
|
||||
```file +line_numbers {25-39}
|
||||
path: packaging.nix
|
||||
language: nix
|
||||
```
|
||||
Bon, ici, j'ai omis quelque lignes histoire de garder l'essentiel.
|
||||
Un problème rencontré lors de l'export des slides en PDF est que le process de
|
||||
build se passe dans un environnement "neutre", créer par nix spécifiquement pour
|
||||
cette tâche et avec le moins possible de variable provenant de l'extérieur, ce
|
||||
afin d'assurer la reproductibilité du process. Ainsi, contrairement au fait de
|
||||
juste lancer la commande `presenterm -e machin.md`, lors de l'exécution de la phase
|
||||
de build, l'exécutable de presenterm n'a ni accès à la police de caractère
|
||||
habituellement fournis par l'émulateur de terminal, ainsi qu'à la taille de ce
|
||||
dernier. Heureusement, presenterm nous permet de fournir une taille statique pour
|
||||
l'export en PDF via un fichier de configuration, ainsi que de définir une police
|
||||
de caractère.
|
||||
Le premier est assez simple, on hardcode juste les options correspondantes
|
||||
(pour le moment) dans le fichier de conf que l'on génère avec writeTextFile.
|
||||
pour la police, ont créé une variable qui pointera vers notre police dans le store,
|
||||
puis on interpolera cette dernière à l'option correspondante dans la config.
|
||||
Pour finir, notre **buildPhase** consiste à définir une variable d'environnement
|
||||
pointant vers la config que l'on a générée afin qu'elle puisse être lue par notre
|
||||
script, puis en l'exécution de ce dernier dont le rôle est d'aller crawler chaque
|
||||
dossier contenant nos posts et d'appeler la commande `presenterm -e` dessus.
|
||||
Je n'inclus pas le dit script ici car je compte le refactorer un peu plus tard
|
||||
pour le rendre plus flexible et donner la possibilité de build un post précis au
|
||||
lieu de tous. Mais globalement voila la magie ! Sur des projets plus complexe on
|
||||
peut utiliser ce genre de mécanisme pour pousser nos packages sur un cache binaire
|
||||
afin d'accélérer les déploiements, ou juste dans le cadre d'une CI. Ici, j'avais
|
||||
juste envie d'expérimenter un peu sur ce mécanisme.
|
||||
2
src/posts/general_nix/post_packaging/presenterm.yml
Normal file
2
src/posts/general_nix/post_packaging/presenterm.yml
Normal file
@ -0,0 +1,2 @@
|
||||
options:
|
||||
strict_front_matter_parsing: false
|
||||
Loading…
x
Reference in New Issue
Block a user