Aggiungere l'integrazione continua alle build contenitore

L'integrazione continua è un processo di sviluppo software in cui un'applicazione viene mantenuta in uno stato continuamente releasable fornendo build automatizzate con ogni commit a una specifica code base. È possibile aggiungere l'integrazione continua praticamente a qualsiasi sistema di compilazione, ma due di essi particolarmente utili sono GitHub Actions e pipeline di Azure. In questo argomento verrà illustrato come usare GitHub Actions o Pipeline di Azure per automatizzare i passaggi della build di Docker descritti in Usare i contenitori per creare app Azure Sphere.

Usare GitHub Actions per creare automaticamente il contenitore

GitHub Actions consentono di automatizzare il processo di compilazione direttamente dai repository GitHub. Quindi, il primo passaggio nell'uso di GitHub Actions consiste nel creare o aprire un repository GitHub che contiene il codice dell'applicazione. Questo argomento presuppone che sia stato creato un repository GitHub contenente l'applicazione Blink generata in Tutorial: Creare un'applicazione di alto livello e che il progetto sia denominato "Blink". Come per qualsiasi progetto di integrazione continua, assicurarsi che il progetto venga compilato in locale e fornisca gli elementi previsti prima di tentare di automatizzare il processo. In questo esempio si presuppone che, dopo una compilazione riuscita, la out directory contenga un file Blink.imagepackage.

Nella directory principale del repository GitHub, crea una directory denominata .devcontainer e crea un file denominato Dockerfile nella directory con il contenuto seguente:

FROM mcr.microsoft.com/azurespheresdk:latest AS dev

FROM dev AS build
COPY ./ /src/
WORKDIR /out
RUN cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="/opt/azurespheresdk/CMakeFiles/AzureSphereToolchain.cmake" \
    -DAZURE_SPHERE_TARGET_API_SET="latest-lts" -DCMAKE_BUILD_TYPE="Release" "/src"
ENTRYPOINT [ "ninja" ]

La linea iniziale FROM specifica l'immagine standard di Azure Sphere Docker come contenitore di sviluppo di base e la seconda indica di usare tale contenitore di base come ambiente di compilazione. La COPY riga copia il contenuto del repository nella directory /src/ del contenitore. Specifica WORKDIR la directory di compilazione. Il RUN comando fornisce il comando CMake per generare i file di compilazione. Infine, specifica ENTRYPOINT che ninja deve essere richiamato per costruire effettivamente l'applicazione.

Nella directory principale del repository, crea la directory .github/workflows e aggiungi un file denominato ci.yml con il contenuto seguente:

# This is a basic workflow to help you get started with Actions

name: ContinuousIntegration

# Controls when the action will run. Triggers the workflow on push or pull request
# events, but including workflow_dispatch also allows manual execution
on:
  push:
  pull_request:
  workflow_dispatch:


jobs:
  build:
    runs-on: ubuntu-latest
    name: Build Azure Sphere Apps
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - name: Build image for az sphere builds and Start container from build image
      run: |
        docker build --target build -t hlbuildimage -f .devcontainer/Dockerfile .
        docker run --name hlbuildcontainer hlbuildimage
    - name: Copy container build output
      run:
        docker cp hlbuildcontainer:/out HLOutput
    - name: Publish HL imagepackage
      uses: actions/upload-artifact@v2
      with:
        name: HL imagepackage
        path: ${{ github.workspace }}/HLOutput/Blink.imagepackage

Questo flusso di lavoro ha un solo processo: creare l'applicazione; il lavoro viene eseguito su un GitHub Actions corridore, in questo caso ubuntu-latest, e ha quattro passaggi:

  1. Passaggio 1, Checkout, è un'azione standard di GitHub che estrae semplicemente il repository per l'ultimo corridore di ubuntu.

  2. Il passaggio 2 crea l'immagine (docker build) e avvia il contenitore (docker run).

  3. Il passaggio 3 copia l'output dal contenitore al corridore.

  4. Passaggio 4, Pubblicare pacchetto immagine HL, pubblica il pacchetto immagine applicazione di alto livello come elemento.

Esegui il commit di queste modifiche nel ramo principale e seleziona Azioni. Dovrebbe essere visualizzata una pagina denominata "Tutti i flussi di lavoro", con almeno un flusso di lavoro in esecuzione o completato. Se il flusso di lavoro viene completato correttamente, accanto al flusso di lavoro viene visualizzato un segno di spunta verde. Fare clic su un flusso di lavoro completato e dovrebbe essere visualizzata una casella denominata "Artefatti" contenente un elemento etichettato come "pacchetto di immagini HL". Scaricare questo elemento e disimballare il file imagepackage; puoi quindi creare una distribuzione o trasferire l'applicazione sul tuo dispositivo.

Usare pipeline di Azure per creare automaticamente il contenitore

Le pipeline di Azure consentono di automatizzare il processo di compilazione direttamente dai repository GitHub (e anche da molti altri repository di codice). Questo argomento presuppone che si appartenga già a un'organizzazione con un progetto Azure DevOps e che si abbia accesso alle pipeline di Azure. Il primo passaggio nell'uso di Pipeline di Azure consiste nel creare o aprire un repository contenente il codice dell'applicazione. Questo argomento presuppone che sia stato creato un repository GitHub contenente l'applicazione Blink generata in Tutorial: Creare un'applicazione di alto livello.

Nella directory di primo livello di questo repository, crea la directory .devcontainer e crea un file Dockerfile in tale directory con il contenuto seguente:

FROM mcr.microsoft.com/azurespheresdk:latest AS dev

FROM dev AS build
COPY ./ /src/
WORKDIR /out
RUN cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="/opt/azurespheresdk/CMakeFiles/AzureSphereToolchain.cmake" \
    -DAZURE_SPHERE_TARGET_API_SET="latest-lts" -DCMAKE_BUILD_TYPE="Release" "/src"
ENTRYPOINT [ "ninja" ]

La linea iniziale FROM specifica l'immagine standard di Azure Sphere Docker come contenitore di sviluppo di base e la seconda indica di usare tale contenitore di base come ambiente di compilazione. La COPY riga copia il contenuto del repository nella directory /src/ del contenitore. Specifica WORKDIR la directory di compilazione. Il RUN comando fornisce il comando CMake per generare i file di compilazione. Infine, specifica ENTRYPOINT che ninja deve essere richiamato per costruire effettivamente l'applicazione.

Per creare la pipeline:

  1. Accedere al progetto Azure DevOps e aprire Pipeline.
  2. Seleziona Nuovo pipeline, quindi seleziona GitHub quando ti viene chiesto dov'è il tuo codice? Potresti essere indirizzato a una pagina di autenticazione GitHub; completare l'autenticazione e passare alla pagina per selezionare il repository.
  3. Seleziona il repository Blink. Viene visualizzata una pagina denominata Configurare la pipeline.
  4. Selezionare Pipeline di partenza. Verrà aperto un file denominato azure-pipelines.yml nella directory di primo livello del repository con un'attività Hello, World.
  5. Seleziona Salva ed esegui. Accettare il messaggio di commit predefinito e selezionare di nuovo Salva ed esegui. Il file azure-pipelines.yml viene approvato nel repository GitHub e la pipeline viene creata.

Sostituire il contenuto del file azure-pipelines.yml con il contenuto seguente:

# Docker
# Build a Docker image
# /azure/devops/pipelines/languages/docker

trigger:
- main

resources:
- repo: self

variables:
  tag: '$(Build.BuildId)'

stages:
- stage: Build
  displayName: Build image
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - bash: docker build --target build -t hlbuildimage -f .devcontainer/Dockerfile . &&  docker run --name hlbuildcontainer hlbuildimage && docker cp hlbuildcontainer:/out $(Build.ArtifactStagingDirectory)/HLOutput
      displayName: Build high-level Azure Sphere application in a container and copy the output
    - task: PublishBuildArtifacts@1
      displayName: Publish build artifacts
      inputs:
        PathtoPublish: '$(Build.ArtifactStagingDirectory)/HLOutput/Blink.imagepackage'
        ArtifactName: 'BlinkSample.imagepackage'
        publishLocation: 'Container'

Questo flusso di lavoro ha un solo processo: creare l'applicazione; il processo viene eseguito su un agente Azure DevOps, in questo caso ubuntu-latest, e prevede due passaggi:

  1. Il passaggio 1 crea l'immagine (docker build), avvia il contenitore (docker run) e copia l'output dal contenitore all'agente.

  2. Passaggio 2, Pubblicare elementi della build, pubblica il pacchetto immagine dell'applicazione di livello elevato come elemento.

Esegui il commit di queste modifiche nel ramo principale. In Azure DevOps aprire di nuovo Pipeline. Dovrebbe essere visualizzata una pipeline in corso o appena completata. Se l'esecuzione mostra un segno di spunta verde, la build è riuscita. Selezionare l'esecuzione completata; nella colonna Correlati dovrebbe essere visualizzato 1 Pubblicato. Scaricare questo elemento e decomprimere il file imagepackage; puoi quindi creare una distribuzione o trasferire l'applicazione sul tuo dispositivo.

Aggiungere l'integrazione continua alle applicazioni di esempio Azure Sphere

GitHub Actions e pipeline di Azure sono pensati per automatizzare le build per un singolo progetto, ad esempio quelle scaricate dal browser di esempio Microsoft. Gli esempi di Azure Sphere in GitHub sono una raccolta di progetti con alcune risorse condivise. Per usare uno di questi esempi in un'integrazione continua, è necessario incorporare tutte le risorse condivise necessarie. In genere, ciò significa almeno creare una directory HardwareDefinitions nella directory di primo livello del progetto e modificare il file CMakeLists.txt in modo che punti alla copia locale. Ad esempio, se crei un progetto basato sull'esempio HelloWorld/HelloWorld_HighLevelApp, la directory di primo livello inizialmente ha questo aspetto:

.vscode
.gitignore
applibs_versions.h
app_manifest.json
CMakeLists.txt
CMakeSettings.json
launch.vs.json
LICENSE.txt
main.c
README.md

Il file CMakeLists.txt contiene la riga seguente che punta alla directory hardwareDefinitions condivisa nel repository Samples:

azsphere_target_hardware_definition(${PROJECT_NAME} TARGET_DIRECTORY "../../../HardwareDefinitions/mt3620_rdb" TARGET_DEFINITION "sample_appliance.json")

Per consentire la compilazione del progetto, copiare la cartella HardwareDefinitions nella directory di primo livello, quindi modificare il file di CMakeLists.txt in modo da usare la posizione locale:

azsphere_target_hardware_definition(${PROJECT_NAME} TARGET_DIRECTORY "HardwareDefinitions/mt3620_rdb" TARGET_DEFINITION "sample_appliance.json")

Anche in questo caso, verificare che il progetto sia compilato in locale prima di tentare di automatizzare con GitHub Actions.