Aller au contenu
Point Rouge
Retour

Comment utiliser Git Hooks pour définir les dates de création et de modification

Mis à jour:

Dans cet article, je vais expliquer comment utiliser le hook Git de pré-commit pour automatiser la saisie des éléments créés (pubDatetime) et modifié (modDatetime) dans le thème du blog Point Rouge

Table des matières

Ayez-les partout

Crochets Git sont parfaits pour automatiser des tâches comme ajout ou vérification le nom de la branche à vos messages de commit ou vous empêcher de commettre des secrets en texte brut. Leur plus gros défaut est que les hooks côté client sont par machine.

Vous pouvez contourner ce problème en ayant un hooks répertoire et copiez-les manuellement dans le répertoire .git/hooks répertoire ou configurer un lien symbolique, mais tout cela nécessite que vous n’oubliez pas de le configurer, et ce n’est pas quelque chose que je suis doué pour faire.

Comme ce projet utilise npm, nous pouvons utiliser un package appelé Husky (ceci est déjà installé dans Point Rouge) pour installer automatiquement les hooks pour nous.

Mise à jour ! Dans Point Rouge v4.3.0, le hook de pré-commit a été supprimé au profit des actions GitHub. Cependant, vous pouvez facilement installer Husky vous-même.

Le crochet

Comme nous voulons que ce hook s’exécute lorsque nous validons le code pour mettre à jour les dates et que cela fasse ensuite partie de notre changement, nous allons utiliser le pre-commit crochet. Cela a déjà été configuré par ce projet Point Rouge, mais si ce n’était pas le cas, vous exécuteriez npx husky add .husky/pre-commit 'echo "This is our new pre-commit hook"'.

Navigation vers le hooks/pre-commit fichier, nous allons ajouter l’un ou les deux extraits suivants.

Mise à jour de la date de modification lorsqu’un fichier est édité


MISE À JOUR :

Cette section a été mise à jour avec une nouvelle version du hook plus intelligente. Cela n’augmentera plus le modDatetime jusqu’à ce que le message soit publié. Lors de la première publication, définissez le statut de brouillon sur first et regardez la magie opérer.


# Modified files, update the modDatetime
git diff --cached --name-status |
grep -i '^M.*\.md$' |
while read _ file; do
  filecontent=$(cat "$file")
  frontmatter=$(echo "$filecontent" | awk -v RS='---' 'NR==2{print}')
  draft=$(echo "$frontmatter" | awk '/^draft: /{print $2}')
  if [ "$draft" = "false" ]; then
    echo "$file modDateTime updated"
    cat $file | sed "/---.*/,/---.*/s/^modDatetime:.*$/modDatetime: $(date -u "+%Y-%m-%dT%H:%M:%SZ")/" > tmp
    mv tmp $file
    git add $file
  fi
  if [ "$draft" = "first" ]; then
    echo "First release of $file, draft set to false and modDateTime removed"
    cat $file | sed "/---.*/,/---.*/s/^modDatetime:.*$/modDatetime:/" | sed "/---.*/,/---.*/s/^draft:.*$/draft: false/" > tmp
    mv tmp $file
    git add $file
  fi
done

git diff --cached --name-status récupère les fichiers de git qui ont été préparés pour la validation. Le résultat ressemble à :

A       src/content/blog/setting-dates-via-git-hooks.md

La lettre au début indique quelle action a été entreprise, dans l’exemple ci-dessus, le fichier a été ajouté. Les fichiers modifiés ont M

Nous transmettons cette sortie à la commande grep où nous examinons chaque ligne pour trouver celles qui ont été modifiées. La ligne doit commencer par M (^(M)), avoir n’importe quel nombre de caractères après cela (.*) et terminer par le .md extension de fichier (.(md)$).Cela va filtrer les lignes qui ne sont pas des fichiers de Markdown modifiés egrep -i "^(M).*\.(md)$".


Amélioration - Plus explicite

Cela pourrait être ajouté pour rechercher uniquement les fichiers que nous démarquons dans le blog répertoire, car ce sont les seuls qui auront le bon contenu


L’expression régulière capturera les deux parties, la lettre et le chemin du fichier. Nous allons diriger cette liste dans une boucle while pour parcourir les lignes correspondantes et attribuer la lettre à a et le chemin vers b. Nous allons ignorer a pour l’instant.

Pour connaître l’état d’avancement du dossier, nous avons besoin de sa première partie. Dans le code suivant, nous utilisons cat pour obtenir le contenu du fichier, puis en utilisant awk pour diviser le fichier sur le séparateur frontal (---) et en prenant le deuxième bloc (la fonmtmatter, le bit entre le ---). De là, nous utilisons awk encore une fois pour trouver le brouillon de clé et imprimer la valeur.

  filecontent=$(cat "$file")
  frontmatter=$(echo "$filecontent" | awk -v RS='---' 'NR==2{print}')
  draft=$(echo "$frontmatter" | awk '/^draft: /{print $2}')

Nous avons maintenant la valeur de draft nous allons faire 1 des 3 choses, définissez le modDatetime sur maintenant (lorsque le brouillon est faux if [ "$draft" = "false" ]; then), effacez le modDatetime et définissez draft sur false (lorsque draft est défini sur first if [ "$draft" = "first" ]; then), ou rien (dans tous les autres cas).

La partie suivante avec la commande sed est un peu magique pour moi car je ne l’utilise pas souvent, elle a été copiée de un autre article de blog sur la façon de faire quelque chose de similaire. Essentiellement, il s’agit de regarder à l’intérieur des balises frontmatter (---) du fichier pour trouver le pubDatetime: clé, obtenir la ligne complète et la remplacer par la pubDatetime: $(date -u "+%Y-%m-%dT%H:%M:%SZ")/" à nouveau la même clé et la date/heure actuelle correctement formatée.

Ce remplacement s’effectue dans le contexte de l’ensemble du fichier, nous le mettons donc dans un fichier temporaire (> tmp), puis on se déplace (mv) le nouveau fichier à l’emplacement de l’ancien fichier, en l’écrasant. Ceci est ensuite ajouté à git prêt à être validé comme si nous avions effectué le changement nous-mêmes.


REMARQUE

Pour le sed pour fonctionner, le frontmatter doit déjà avoir le modDatetime clé dans le sujet. Vous devrez apporter d’autres modifications pour que l’application soit créée avec une date vide, voir plus bas


Ajout de la date pour les nouveaux fichiers

L’ajout de la date d’un nouveau fichier est le même processus que ci-dessus, mais cette fois nous recherchons les lignes qui ont été ajoutées (A) et nous allons remplacer le pubDatetime valeur.

# New files, add/update the pubDatetime
git diff --cached --name-status | egrep -i "^(A).*\.(md)$" | while read a b; do
  cat $b | sed "/---.*/,/---.*/s/^pubDatetime:.*$/pubDatetime: $(date -u "+%Y-%m-%dT%H:%M:%SZ")/" > tmp
  mv tmp $b
  git add $b
done

Amélioration - Une seule boucle

Nous pourrions utiliser le a variable pour basculer à l’intérieur de la boucle et soit mettre à jour la modDatetime ou ajoutez le pubDatetime en une seule boucle.


Remplir le frontmatter

Si votre IDE prend en charge les extraits de code, vous avez la possibilité de créer un extrait personnalisé pour remplir le frontmatter.Dans Point Rouge v4, il en sera fourni un pour VSCode par défaut.

Vide modDatetime changements

Pour permettre à Astro de compiler la Markdown et de faire son travail, il doit savoir ce qui est attendu en premier lieu. Il le fait via la configuration dans src/content/config.ts

Pour permettre à la clé d’être là sans valeur, nous devons éditer la ligne 10 pour ajouter le .nullable() fonction.

const blog = defineCollection({
  type: "content",
  schema: ({ image }) =>
    z.object({
      author: z.string().default(SITE.author),
      pubDatetime: z.date(),
      modDatetime: z.date().optional(),
      modDatetime: z.date().optional().nullable(),
      title: z.string(),
      featured: z.boolean().optional(),
      draft: z.boolean().optional(),
      tags: z.array(z.string()).default(["others"]),
      ogImage: image().or(z.string()).optional(),
      description: z.string(),
      canonicalURL: z.string().optional(),
      readingTime: z.string().optional(),
    }),
});

Pour empêcher l’EDI de se plaindre dans les fichiers du moteur de blog, j’ai également effectué les opérations suivantes :

  1. ajouté | null à la ligne 15 dans src/layouts/Layout.astro pour que ça ressemble

    export interface Props {
      title?: string;
      author?: string;
      description?: string;
      ogImage?: string;
      canonicalURL?: string;
      pubDatetime?: Date;
      modDatetime?: Date | null;
    }
  2. ajouté | null à la ligne 5 dans src/components/Datetime.tsx pour que ça ressemble

    interface DatetimesProps {
      pubDatetime: string | Date;
      modDatetime: string | Date | undefined | null;
    }

Partager cet article :

Article précédent
Point Rouge 5.0
Article suivant
Point Rouge 4.0