DevOps pipeline variabele aanpassen voor de volgende build

Koen van Zeijl
October 21, 2020 5 min lezen
Koen van Zeijl
https://images.unsplash.com/photo-1507823690283-48b0929e727b

Introductie

In mijn vorige blog 'Plaats je Instagram feed op je website in 2020' liep ik tegen een probleem aan dat ik om de 60 dagen mijn Instagram token dien te verversen. Een nieuw token kan gemakkelijk worden opgehaald vanuit het Facebook portaal, echter is het niet efficiënt om elke 2 maanden een nieuwe commit te doen met daarin het nieuwe access token. Om deze reden ben ik opzoek gegaan naar een manier om het token tijdens de build te verversen zodat deze na elke update of build opnieuw 60 dagen geldig is.

Een nadeel van deze methode is dat het token dat wordt teruggegeven vanuit het Facebook portaal moet worden opgeslagen, aangezien deze weer gebruikt moet worden om het volgende (nieuwe) token op te halen. Het huidige geldige token kan immers na 60 dagen niet meer gebruikt worden om een nieuw token te genereren.

In dit blog leg ik uit hoe je Azure DevOps pipeline variabelen kan aanpassen vanuit de pipeline. Hiervoor zal ik gebruik maken van het Instagram voorbeeld dat ik hierboven heb beschreven.

Wat hebben we nodig?

Om dit blog te volgen heb je alleen een Azure DevOps pipeline nodig. In deze pipeline zullen we wel gebruik maken van de tool dotnet-json voor het in en uitlezen van JSON.

Pipeline variabele

Heb je je variabele al in de pipeline staan? Dan kun je deze stap overslaan en doorgaan naar het volgende hoofdstuk.

Druk tijdens het aanpassen van de pipeline op de knop variabelen rechts bovenin om het overzicht met variabelen te openen. Klik vervolgens op variabele toevoegen om een nieuwe variabele toe te voegen. Je krijgt het volgende formulier te zien:

Create a variable

Onthoud de naam van de variabele goed, deze zul je later namelijk nodig hebben.

Pipeline aanpassen

In de pipeline zullen we gebruik maken van een bash taak. De hosted agents van Azure DevOps hebben standaard deze taak ingebouwd zitten zonder dat je hiervoor iets hoeft te doen. Host je zelf een agent? Dan is het mogelijk dat je eerst bash dient te installeren.

Aanpassingen aan de pipeline:

azure-pipelines.yml
- task: Bash@3
  inputs:
    targetType: 'inline'
    script: |
      dotnet tool update -g dotnet-json
      access_token=$(curl -s "https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=$(instatoken)" | dotnet json get - access_token)
      pipeline=$(curl -H "Authorization: Bearer $(System.AccessToken)" "$(System.TeamFoundationCollectionUri)/$(System.TeamProject)/_apis/build/definitions/$(System.DefinitionId)?api-version=5.0" | dotnet json set - variables:instatoken:value $access_token)
      curl -X PUT -H "Authorization: Bearer $(System.AccessToken)" -H "Content-Type: application/json" --data "$pipeline" "$(System.TeamFoundationCollectionUri)/$(System.TeamProject)/_apis/build/definitions/$(System.DefinitionId)?api-version=5.0"
      sed -i "s/placeholder_token/$access_token/" '$(Build.SourcesDirectory)/nuxt.config.js'

De uitleg

Maar wat doet het nou allemaal precies? Hieronder leg ik elke stap uit.

De opzet

De eerste 4 regels geven aan dat er een bash script gedraaid dient te worden hierna wordt na de pipe | aangegeven welke script dit is.

dotnet-json installeren

dotnet tool update -g dotnet-json: zorgt ervoor dat de laatste versie van dotnet-json wordt geïnstalleerd.

Variabele ophalen

De volgende regel wordt gebruikt om de nieuwe variabele op te halen.

curl -s "https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=$(instatoken) wordt gebruikt om een curl request naar de Instagram api te doen. Hieraan wordt de pipeline variabele meegegeven door middel van $(instatoken).

Vervolgens maak ik gebruik van dotnet json get om een waarde uit het result te lezen. Door een - achter de get te plaatsen wordt de default input gebruikt. Omdat er een | staat achter het curl request word dit gezien als de default input. Als laatste geef je aan welke waarde van het json result je wilt hebben, in mijn geval was dit access_token.

Om het makkelijker te maken sla ik deze waarde op in een bash variabele access_token door de curl request en het parsen van het result te plaatsen binnen $().

Huidige pipeline ophalen

De huidige pipeline kan gemakkelijk opgehaald worden doormiddel van een url waarbij het token van de pipeline ($(System.AccessToken), dit is een standaard DevOps variable) wordt gebruikt voor de autorisatie. Ook de andere variabelen in de volgende string zijn standaard voor elk project curl -H "Authorization: Bearer $(System.AccessToken)" "$(System.TeamFoundationCollectionUri)/$(System.TeamProject)/_apis/build/definitions/$(System.DefinitionId)?api-version=5.0".

Vervolgens pas ik deze pipeline aan door de huidige variabele te vervangen met mijn nieuwe token. Dit doe ik met behulp van dotnet-json. Hiervoor gebruik je dotnet json set - variables:instatoken:value $access_token. In mijn geval is instatoken de naam van mijn variabele. Opnieuw sla ik mijn nieuwe pipeline op door gebruik te maken van een bash variabele.

Updaten van de pipeline

Nu dient de nieuwe pipeline alleen nog maar opgeslagen te worden binnen Azure DevOps. Hiervoor maak ik gebruik van een curl PUT request. curl -X PUT -H "Authorization: Bearer $(System.AccessToken)" -H "Content-Type: application/json" --data "$pipeline" "$(System.TeamFoundationCollectionUri)/$(System.TeamProject)/_apis/build/definitions/$(System.DefinitionId)?api-version=5.0".

De variable $(System.AccessToken) wordt meegegeven om het request te autoriseren. Vervolgens wordt met Content-Type: application/json aangegeven dat er json wordt opgestuurd. Aan --data wordt nieuwe json van de pipeline meegegeven die ingesteld dient te worden. Als laatste wordt de url beschreven waar het PUT request naar toegestuurd wordt.

Gebruiken van je variabele

In de laatste regel van mijn script maak ik gebruik van mijn nieuw verkregen token door hem in een bestand aan te passen zodat hij met de build verder mee kan gaan. Dit is natuurlijk niet voor iedereen het doel, dus plaats hier het script dat je zelf nodig hebt voor je pipeline.

Conclusie

Het is dus mogelijk om je pipeline aan te passen vanuit de pipeline zelf. Mocht je het zelf aan het aanpassen zijn en loop je tegen problemen aan? Laat het gerust even weten en wie weet kan ik je verder helpen.

Is het wel gelukt? Super gaaf laat in de comments even weten waar jij het voor gebruikt hebt.