Publier mes blogs sur plusieurs plateformes prend beaucoup de temps chaque semaine. Il devait y avoir un meilleur moyen
Je fais beaucoup d’écriture.
J’ai écrit et publié un article de blog chaque semaine au cours des 50 dernières semaines. C’est quelque chose que je fais parce que j’ai une passion pour l’écriture et le partage des choses que j’apprends avec les autres.
L’écriture me fournit non seulement un excellent moyen d’aider les autres, mais cela m’aide également à apprendre en m’assurant que je connais un sujet de haut en bas. Cela a grandement amélioré ma capacité d’écriture, ma compréhension et ma conscience de soi. Je pourrais continuer longtemps à ce sujet, mais nous sommes ici pour parler d’autre chose.
La partie la plus difficile des blogs est la publication croisée. La publication croisée est l’endroit où je prends le contenu de mes articles et le publie sur d’autres sites Web avec un lien vers mon blog. Je republie mon contenu sur Moyen, Dev.toet Hashtag.
En postant sur ces différentes plateformes, je suis en mesure de toucher un public plus large que si je ne publiais que du contenu sur mon blog.
Malheureusement, il ne s’agit pas d’un simple copier/coller sur ces plateformes. Je dois apporter quelques modifications au contenu qui varient en fonction du site sur lequel je publie.
- Mettre à jour les liens — mes articles font souvent référence à d’autres articles que j’ai écrits. Je mets à jour ces liens sur chaque plate-forme pour pointer vers la version croisée. Ainsi, tous mes articles Medium sont liés à mes autres articles Medium, tous les articles Dev pointent vers d’autres articles Dev, etc. Cela offre une expérience agréable et unifiée à mes lecteurs.
- Mettre à jour les intégrations — J’intègre régulièrement du code ou des tweets dans mes publications. Chaque plate-forme utilise un mécanisme différent pour intégrer du contenu dans une publication.
- Définir l’URL canonique – Chaque message doit pointer vers l’article d’origine hébergé sur mon blog. S’ils ne le font pas, Robots d’exploration de référencement détectera le contenu en double et réduira le classement des moteurs de recherche.
Comme vous pouvez l’imaginer, cela prend beaucoup de temps chaque semaine. Analyser les liens et les mettre à jour avec les bonnes références, remplacer le contenu intégré et définir des URL canoniques pour trois sites différents s’additionnent rapidement.
J’ai donc décidé de réparer ça. J’ai créé une application sans serveur qui mettra à jour et publiera mon contenu chaque fois que je publierai quelque chose de nouveau.
Nous allons jeter un coup d’oeil.
Mon blog est construit avec le générateur de site statique Hugo et hébergé dans Amplifier AWS. Si vous êtes intéressé par la façon dont je l’ai construit, J’ai écrit un article de blog à ce sujet.
J’écris des articles en Markdown et je les pousse vers la branche principale de mon référentiel. Une génération Amplify est déclenchée, qui exécute Hugo pour compiler le démarquage en HTML, puis il publie le contenu sur S3, qui fait face à CloudFront.
Pour mon application, je voulais déclencher un processus asynchrone à exécuter chaque fois que la construction se terminait avec succès. Ce processus récupèrerait le fichier de GitHub, transformerait le démarquage au format approprié et le publierait sur toutes les différentes plates-formes.
Le déclenchement d’un processus après une construction Amplify réussie était quelque chose que j’ai cherché dans la documentation mais que je n’ai pas trouvé. J’étais sur le point de déclencher une fonction Lambda directement depuis mon build lorsque j’ai décidé de demander michel lindo s’il connaissait des trucs.
Heureusement, j’ai piqué sa curiosité. Il a creusé profondément et a découvert une fonctionnalité soignée sans papiers.
J’ai donc pu déclencher une fonction Lambda avec un EventBridge
règle sur une construction réussie!
Cette fonction Lambda appelle GitHub et recherche les commits au cours des cinq dernières minutes [new post]
dans le message de validation. Il récupère ensuite tous les nouveaux fichiers du répertoire de mon blog à partir du commit et démarre une exécution de la machine d’état qui transforme et publie le contenu sur les différentes plates-formes.
S’il n’y a pas de commit avec [new post]
dans le message ou aucun nouveau fichier dans le répertoire blog de mon référentiel, l’exécution de la fonction Lambda s’arrête sans déclencher la machine d’état.
Le flux de travail de la machine d’état ressemble à ceci :
Pour éviter que les articles ne soient accidentellement publiés plus d’une fois, cela commence par une vérification d’idempotence, efface le nom du fichier et valide sha
. Si plusieurs exécutions sont déclenchées avec la même combinaison nom de fichier/validation et que l’exécution d’origine est en cours ou a réussi, l’exécution est abandonnée. Si l’exécution d’origine a échoué, il réessaye en toute sécurité de traiter l’article.
Après la vérification d’idempotence, il utilise une intégration directe à DynamoDB pour charger tous les articles existants et leurs mappages (plus d’informations à ce sujet dans une minute). Une fois les articles chargés, il les transforme et les publie sur les trois plateformes en parallèle.
En cas de succès, il enregistre les URL de publication croisée et met à jour l’enregistrement d’idempotence. Alors c’est en direct !
Examinons de plus près les composants de transformation et de publication.
Lorsque je mets à jour manuellement des liens pour pointer vers mes versions croisées, je dois faire défiler ma page de liste d’histoires sur la plate-forme sur laquelle je publie. Je trouve le lien vers l’article que j’ai référencé, puis je mets à jour le contenu en conséquence.
Mais je ne peux pas faire cela avec un processus backend. Je ne peux pas « cliquer et faire défiler » et trouver le bon article.
J’ai donc construit un catalogue de tous mes articles dans DynamoDB.
Chaque article obtient un enregistrement dans DynamoDB qui l’identifie de manière unique par le limace de poste. Le dossier contient un links
objet qui contient l’URL de la version postée sur Medium, Dev et Hashnode.
{
"pk": "/blog/allen.helton/infrastructure-from-code-benchmark",
"sk": "article",
"GSI1PK": "article",
"GSI1SK": "The Current State of Infrastructure From Code",
"links": {
"devUrl": "https://dev.to/aws-heroes/the-current-state-of-infrastructure-from-code-1fjc",
"mediumUrl": "https://betterprogramming.pub/the-current-state-of-infrastructure-from-code-cbd3469ecdc5",
"url": "/blog/allen.helton/infrastructure-from-code-benchmark",
"hashnodeUrl": "https://allenheltondev.hashnode.dev/the-current-state-of-infrastructure-from-code"
},
"title": "The Current State of Infrastructure From Code"
}
Pour identifier les liens dans mon message, j’ai utilisé une expression régulière pour correspondre au format de lien Markdown. Tous les liens internes (c’est-à-dire les références à d’autres articles que j’ai écrits) commencent par /blog/allen.helton/
j’ai donc inclus cela pour identifier les liens qui devaient être mis à jour rapidement.
Une fois que j’ai pu saisir tous les liens internes, j’ai dû les parcourir, en remplaçant la valeur de mon URL par la valeur mappée dans le links
objet de la notice d’article.
Lorsque vous voyez du contenu riche dans une publication, c’est généralement le résultat d’une intégration. Il s’agit d’un contenu spécial présenté d’une manière qui semble plus naturelle pour les lecteurs.
L’intégration la plus courante que j’utilise dans mes messages est pour Twitter. Il met un tweet directement dans le contenu, de sorte que le lecteur obtient la vue exactement comme s’il était sur le site. Mais le format d’une intégration diffère sur toutes les plateformes sur lesquelles je poste. Par exemple, voici les différentes structures pour intégrer un tweet.
My Blog: {<tweet user="<username>" id="<tweet id>">}
Dev: {% twitter <url to tweet> %}
Medium: <url to tweet>
Hashnode: %[<url to tweet>]
Comme vous pouvez le voir, la structure est très différente, j’ai donc dû utiliser une autre expression régulière pour correspondre au format de tweet de mon blog, composer l’URL Twitter complète, puis la transformer en plate-forme spécifique.
Dans l’ensemble, ce n’était pas une partie très difficile du projet, mais l’incohérence me tuait !
Une fois les données transformées de manière appropriée, j’utilise l’API de la plate-forme respective pour publier. Cette partie était étonnamment difficile. C’est aussi le bon moment pour parler du développement axé sur l’API.
Disposer d’un ensemble solide et intuitif de documents d’API est essentiel si vous vous attendez à ce que les gens s’intègrent à votre logiciel. Si vous ne le faites pas, seuls les intégrateurs persistants s’y tiendront pour lancer leur automatisation. J’aurais peut-être abandonné ce projet sans cet article.
Sur les trois plates-formes avec lesquelles j’ai intégré, seul Dev avait une documentation décente – et même celle-là était incertaine. La documentation indique que leur version d’API d’origine est obsolète, mais la nouvelle version n’a que deux points de terminaison implémentés. J’étais méfiant à l’idée de créer une intégration avec une version obsolète, mais j’ai décidé de l’accepter. Heureusement, leur API fonctionne très bien et je l’ai fait fonctionner en quelques minutes seulement.
Medium et Hashnode étaient des histoires complètement différentes.
Medium avait ce qui ressemblait à une écriture longue pour sa documentation et l’a hébergée dans GitHub dans un fichier README. Toutes les informations dont j’avais besoin étaient là, mais je devais les chercher.
Hashnode utilise GraphQL pour son API et fournit un outil de test avec des définitions d’objets et aucune explication. Je devais me fier aux articles de blog pour comprendre ce qui se passait là-bas.
Mais avec des essais et des erreurs, j’ai réussi à trouver les bons points de terminaison et j’ai demandé aux organismes de publier mon contenu.
Je me suis légèrement éloigné des sentiers battus pour Medium et Dev. Lorsque je publie sur Dev, je lie toujours mon contenu au Collection Héros AWS. De même, sur Medium, j’ajoute mon contenu à la publication Better Programming. J’ai donc dû trouver comment leur soumettre le contenu directement pour optimiser le flux.
En fin de compte, j’ai pu les faire fonctionner tous, et le contenu lié correctement et présenté dans le bon format.
La dernière partie de la publication des articles consiste à obtenir le slug de publication du nouvel article pour chaque plate-forme et à créer l’entrée DynamoDB pour l’histoire afin qu’elle puisse être référencée dans les futurs articles.
Heureusement, l’URL complète est renvoyée dans le message de réponse de réussite de chaque publication, afin que je puisse les saisir et enregistrer les données dans DynamoDB.
C’était une petite application amusante à construire qui était bien plus complexe que ce à quoi je m’attendais au départ. Maintenant que c’est fait, je vais passer un peu de temps à peaufiner et à paramétrer l’IaC afin qu’il puisse être open source.
Cela prendra énormément de temps à l’avenir. Non seulement cela, mais cela devrait également rendre mes publications moins sujettes aux erreurs. Les humains font des erreurs tout le temps. Il y a eu de nombreuses fois où j’ai raté un lien ou oublié de mettre à jour une intégration. Avec l’automatisation, il ne sera jamais manqué.
Prenez toutes les chances que vous avez pour éliminer l’élément humain d’un processus.
Si vous lisez ceci sur Dev, Medium ou Hashnode, j’espère que tous les liens ont fonctionné pour vous. Ce poste était mon premier test de production.
J’espère que cet article vous incitera à construire quelque chose pour vous faciliter la vie. Quelles tâches répétitives faites-vous qui pourraient être automatisées ? De nos jours, il existe une API pour à peu près tout ce avec quoi nous interagissons – presque rien n’est hors de propos.
Si vous construisez quelque chose, dites-le moi ! J’aimerais voir ce que vous avez fait !
Bon codage !