Introducing GitHub Actions

Avatar of Sarah Drasner
Sarah Drasner on

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Eine häufige Situation: Sie erstellen eine Website, und sie ist bereit für den Einsatz. Alles ist auf GitHub. Aber Sie sind noch nicht *wirklich fertig*. Sie müssen die Bereitstellung einrichten. Sie müssen einen Prozess einrichten, der Ihre Tests für Sie ausführt, und Sie müssen nicht ständig manuell Befehle ausführen. Idealerweise läuft jedes Mal, wenn Sie auf „master“ pushen, alles für Sie: die Tests, die Bereitstellung... alles an einem Ort.

Zuvor gab es hier nur wenige Optionen, die dabei helfen konnten. Sie konnten andere Dienste zusammensetzen, sie einrichten und mit GitHub integrieren. Sie konnten auch Post-Commit-Hooks schreiben, die ebenfalls helfen.

Aber jetzt, **treten Sie ein in die GitHub Actions.**

Aktionen sind kleine Code-Schnipsel, die auf verschiedenen GitHub-Ereignissen ausgeführt werden können, wobei das häufigste das Pushen auf „master“ ist. Aber es ist nicht unbedingt darauf beschränkt. Sie sind alle direkt in GitHub integriert, was bedeutet, dass Sie keinen Middleware-Dienst mehr benötigen oder selbst eine Lösung schreiben müssen. Und es gibt bereits viele Optionen zur Auswahl. Zum Beispiel können Sie direkt auf npm veröffentlichen und auf eine Vielzahl von Cloud-Diensten (Azure, AWS, Google Cloud, Zeit... Sie nennen es) bereitstellen, um nur einige zu nennen.

Aber Aktionen sind mehr als nur Bereitstellung und Veröffentlichung. Das ist das Coole daran. Sie sind durchgehend Container, sodass Sie buchstäblich *so ziemlich alles* tun können – die Möglichkeiten sind endlos! Sie könnten sie verwenden, um CSS und JavaScript zu minifizieren und zu verketten, Informationen zu senden, wenn Leute Issues in Ihrem Repository erstellen, und mehr... der Himmel ist die Grenze.

Sie müssen die Container auch nicht selbst konfigurieren/erstellen. Aktionen ermöglichen es Ihnen, auf das Repository einer anderen Person, eine vorhandene Dockerfile oder einen Pfad zu verweisen, und die Aktion wird entsprechend reagieren. Dies ist eine ganz neue Büchse der Pandora für Open-Source-Möglichkeiten und Ökosysteme.

Einrichtung Ihrer ersten Aktion

Es gibt zwei Möglichkeiten, eine Aktion einzurichten: über die Workflow-GUI oder durch Schreiben und Übermitteln der Datei von Hand. Wir beginnen mit der GUI, da sie so einfach zu verstehen ist, und gehen dann zum Schreiben von Hand über, da dies die meiste Kontrolle bietet.

Zuerst melden wir uns für die Beta an, indem wir auf den großen blauen Button hier klicken. Es kann eine Weile dauern, bis sie Sie in die Beta aufnehmen, also bleiben Sie dran.

A screenshot of the GitHub Actions beta site showing a large blue button to click to join the beta.
Die GitHub Actions Beta-Seite.

Erstellen wir nun ein Repository. Ich habe ein kleines Demo-Repository mit einer winzigen Node.js-Beispiel-Website erstellt. Ich kann bereits bemerken, dass ich einen neuen Tab in meinem Repository habe, namens Actions

A screenshot of the sample repo showing the Actions tab in the menu.

Wenn ich auf den Tab „Actions“ klicke, erscheint dieser Bildschirm

screen that shows

Ich klicke auf „Create a New Workflow“ und dann wird mir der folgende Bildschirm angezeigt. Das sagt mir ein paar Dinge. Erstens erstelle ich einen versteckten Ordner namens .github und darin eine Datei namens main.workflow. Wenn Sie einen Workflow von Grund auf neu erstellen würden (was wir noch besprechen werden), müssten Sie dasselbe tun.

new workflow

Nun sehen wir in dieser GUI, dass wir einen neuen Workflow starten. Wenn wir eine Linie von diesem zu unserer ersten Aktion ziehen, erscheint eine Seitenleiste mit vielen Optionen.

show all of the action options in the sidebar

Es gibt Aktionen für npm, Filter, Google Cloud, Azure, Zeit, AWS, Docker Tags, Docker Registry und Heroku. Wie bereits erwähnt, sind Sie nicht auf diese Optionen beschränkt – es ist noch viel mehr möglich!

Ich arbeite für Azure, daher verwende ich das als Beispiel, aber jede Aktion bietet Ihnen die gleichen Optionen, die wir gemeinsam durchgehen werden.

shows options for azure in the sidebar

Oben, wo Sie die Überschrift „GitHub Action for Azure“ sehen, gibt es einen Link „View source“. Dieser führt Sie direkt zum Repository, das verwendet wird, um diese Aktion auszuführen. Das ist wirklich gut, denn Sie können auch einen Pull-Request einreichen, um eine dieser Aktionen zu verbessern, und die Flexibilität haben, die von Ihnen verwendete Aktion zu ändern, wenn Sie möchten, mit der Option „uses“ im Aktionen-Panel.

Hier ist eine Übersicht über die uns zur Verfügung gestellten Optionen

  • Label: Dies ist der Name der Aktion, wie Sie es erwarten würden. Dieser Name wird vom Workflow im resolves-Array referenziert – das ist es, was die Verbindung zwischen ihnen herstellt. Dieses Stück ist für Sie in der GUI abstrahiert, aber Sie werden im nächsten Abschnitt sehen, dass Sie, wenn Sie im Code arbeiten, die Referenzen gleich halten müssen, damit die Verkettung funktioniert.
  • Runs ermöglicht es Ihnen, den Einstiegspunkt zu überschreiben. Das ist großartig, denn wenn Sie etwas wie git in einem Container ausführen möchten, können Sie das tun!
  • Args: Dies ist, was Sie erwarten würden – es ermöglicht Ihnen, Argumente an den Container zu übergeben.
  • secrets und env: Diese sind beide sehr wichtig, da sie Ihnen ermöglichen, Passwörter zu verwenden und Daten zu schützen, ohne sie direkt in das Repository zu committen. Wenn Sie etwas verwenden, das ein Token zur Bereitstellung benötigt, würden Sie wahrscheinlich hier ein Secret verwenden, um es zu übergeben.

Viele dieser Aktionen haben Readmes, die Ihnen sagen, was Sie benötigen. Die Einrichtung für „secrets“ und „env“ sieht normalerweise so aus

action "deploy" {
  uses = ...
  secrets = [
    "THIS_IS_WHAT_YOU_NEED_TO_NAME_THE_SECRET",
  ]
}

Sie können auch mehrere Aktionen in dieser GUI miteinander verketten. Es ist sehr einfach, Dinge nacheinander oder parallel funktionieren zu lassen. Das bedeutet, dass Sie schön laufenden asynchronen Code haben können, indem Sie einfach die Dinge in der Benutzeroberfläche verketten.

Eine Aktion im Code schreiben

Was, wenn keine der hier gezeigten Aktionen genau das ist, was wir brauchen? Glücklicherweise ist das Schreiben von Aktionen wirklich ziemlich unterhaltsam! Ich habe eine Aktion geschrieben, um eine Node.js-Webanwendung nach Azure zu deployen, weil ich damit jederzeit deployen kann, wenn ich auf den Master-Branch des Repos pushe. Das hat super Spaß gemacht, weil ich es jetzt für meine anderen Webanwendungen wiederverwenden kann. Glückliche Sarah!

Erstellen Sie das App-Services-Konto

Wenn Sie andere Dienste verwenden, wird dieser Teil anders sein, aber Sie müssen einen bestehenden Dienst in dem von Ihnen verwendeten Dienst erstellen, um dort bereitstellen zu können.

Zuerst benötigen Sie Ihr kostenloses Azure-Konto. Ich verwende gerne die Azure CLI. Wenn Sie diese also noch nicht installiert haben, führen Sie Folgendes aus:

brew update && brew install azure-cli

Dann melden wir uns bei Azure an, indem wir Folgendes ausführen:

az login

Nun erstellen wir einen Service Principal, indem wir Folgendes ausführen:

az ad sp create-for-rbac --name ServicePrincipalName --password PASSWORD

Es wird uns dieser Teil der Ausgabe übergeben, den wir bei der Erstellung unserer Aktion verwenden werden

{
  "appId": "APP_ID",
  "displayName": "ServicePrincipalName",
  "name": "http://ServicePrincipalName",
  "password": ...,
  "tenant": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

Was ist in einer Aktion?

Hier ist ein grundlegendes Beispiel für einen Workflow und eine Aktion, damit Sie die Struktur dessen sehen können, woraus er besteht.

workflow "Name of Workflow" {
  on = "push"
  resolves = ["deploy"]
}

action "deploy" {
  uses = "actions/someaction"
  secrets = [
    "TOKEN",
  ]
}

Wir sehen, dass wir den Workflow starten und angeben, dass er beim Pushen ausgeführt werden soll (on = "push"). Es gibt auch viele andere Optionen, die Sie verwenden können. Die vollständige Liste finden Sie hier.

Die Zeile resolves unterhalb von resolves = ["deploy"] ist ein Array von Aktionen, die nach dem Workflow verkettet werden. Dies gibt nicht die Reihenfolge an, sondern ist eine vollständige Liste von allem. Sie können sehen, dass wir die Aktion nach „deploy“ aufgerufen haben – diese Zeichenketten müssen übereinstimmen, so referenzieren sie sich gegenseitig.

Als nächstes betrachten wir den action-Block. Die erste Zeile uses ist wirklich interessant: Von Anfang an können Sie jede der vordefinierten Aktionen verwenden, über die wir zuvor gesprochen haben (hier ist eine Liste aller davon). Aber Sie können auch das Repository einer anderen Person oder sogar auf Docker gehostete Dateien verwenden. Wenn wir zum Beispiel git in einem Container ausführen wollten, würden wir diesen verwenden. Ich könnte das tun mit: uses = "docker://alpine/git:latest". (Ein Dank an Matt Colyer, der mich in die richtige Richtung für die URL gewiesen hat.)

Möglicherweise müssen wir hier einige Secrets oder Umgebungsvariablen definieren, und wir würden sie wie folgt verwenden:

action "Deploy Webapp" {
  uses = ...
  args = "run some code here and use a $ENV_VARIABLE_NAME"
  secrets = ["SECRET_NAME"]
  env = {
    ENV_VARIABLE_NAME = "myEnvVariable"
  }
}

Erstellen einer benutzerdefinierten Aktion

Was wir mit unserer benutzerdefinierten Aktion tun werden, ist, die Befehle zu nehmen, die wir normalerweise ausführen, um eine Web-App nach Azure zu deployen und sie so zu schreiben, dass wir nur ein paar Werte übergeben können, damit die Aktion alles für uns ausführt. Die Dateien sehen komplizierter aus, als sie sind – wirklich nehmen wir die erste grundlegende Azure-Aktion, die Sie in der GUI gesehen haben, und bauen darauf auf.

In entrypoint.sh

#!/bin/sh

set -e

echo "Login"
az login --service-principal --username "${SERVICE_PRINCIPAL}" --password "${SERVICE_PASS}" --tenant "${TENANT_ID}"

echo "Creating resource group ${APPID}-group"
az group create -n ${APPID}-group -l westcentralus

echo "Creating app service plan ${APPID}-plan"
az appservice plan create -g ${APPID}-group -n ${APPID}-plan --sku FREE

echo "Creating webapp ${APPID}"
az webapp create -g ${APPID}-group -p ${APPID}-plan -n ${APPID} --deployment-local-git

echo "Getting username/password for deployment"
DEPLOYUSER=`az webapp deployment list-publishing-profiles -n ${APPID} -g ${APPID}-group --query '[0].userName' -o tsv`
DEPLOYPASS=`az webapp deployment list-publishing-profiles -n ${APPID} -g ${APPID}-group --query '[0].userPWD' -o tsv`

git remote add azure https://${DEPLOYUSER}:${DEPLOYPASS}@${APPID}.scm.azurewebsites.net/${APPID}.git

git push azure master

Ein paar interessante Dinge, die man zu dieser Datei beachten sollte

  • set -e in einem Shell-Skript stellt sicher, dass, wenn etwas fehlschlägt, der Rest der Datei nicht weiter ausgewertet wird.
  • Die Zeilen nach „Getting username/password“ sehen etwas knifflig aus – wirklich, was sie tun, ist, den Benutzernamen und das Passwort aus Azure's Publishing Profiles zu extrahieren. Wir können es dann für die folgende Codezeile verwenden, wo wir die Remote hinzufügen.
  • Sie bemerken vielleicht auch, dass wir in diesen Zeilen -o tsv übergeben haben. Das haben wir getan, um den Code zu formatieren, damit wir ihn direkt in eine Umgebungsvariable übergeben konnten, da TSV überschüssige Header usw. entfernt.

Jetzt können wir an unserer main.workflow-Datei arbeiten!

workflow "New workflow" {
  on = "push"
  resolves = ["Deploy to Azure"]
}

action "Deploy to Azure" {
  uses = "./.github/azdeploy"
  secrets = ["SERVICE_PASS"]
  env = {
    SERVICE_PRINCIPAL="http://sdrasApp",
    TENANT_ID="72f988bf-86f1-41af-91ab-2d7cd011db47",
    APPID="sdrasMoonshine"
  }
}

Das Workflow-Stück sollte Ihnen bekannt vorkommen – es wird beim Pushen ausgelöst und löst die Aktion „Deploy to Azure“ auf.

uses zeigt auf das Verzeichnis, in dem wir die andere Datei untergebracht haben. Wir müssen ein Secret hinzufügen, damit wir unser Passwort für die App speichern können. Wir haben diesen Dienst „pass“ genannt, und wir werden ihn konfigurieren, indem wir hierher gehen und ihn in den Einstellungen hinzufügen

adding a secret in settings

Schließlich haben wir alle Umgebungsvariablen, die wir zur Ausführung der Befehle benötigen. Wir haben all diese aus dem vorherigen Abschnitt bezogen, wo wir unser App-Services-Konto erstellt haben. Der tenant von früher wird zu TENANT_ID, name wird zum SERVICE_PRINCIPAL und die APPID ist tatsächlich das, was Sie sich nennen möchten :)

Sie können diese Aktion auch verwenden! Der gesamte Code ist Open Source in diesem Repository. Beachten Sie jedoch, dass Sie, da wir die main.workflow manuell erstellt haben, auch die Umgebungsvariablen manuell in der Datei main.workflow bearbeiten müssen – sobald Sie die GUI verlassen, funktioniert sie nicht mehr auf dieselbe Weise.

Hier sehen Sie, wie alles schön bereitgestellt wird, grün wird, und wir haben unsere wunderbare „Hello World“-App, die jedes Mal neu bereitgestellt wird, wenn wir auf Master pushen 🎉

successful workflow showing green
Hello Work app screenshot

Bahnbrechend

GitHub Actions drehen sich nicht nur um Websites, obwohl Sie sehen können, wie praktisch sie dafür sind. Es ist eine ganz neue Denkweise darüber, wie wir mit Infrastruktur, Ereignissen und sogar Hosting umgehen. Denken Sie an Docker in diesem Modell.

Normalerweise müssten Sie, wenn Sie eine Dockerfile erstellen, die Dockerfile schreiben, mit Docker das Image bauen und dann das Image irgendwo hochladen, damit es für andere Leute zum Herunterladen gehostet wird. In diesem Paradigma können Sie auf ein Git-Repository mit einer vorhandenen Dockerfile oder etwas verweisen, das direkt auf Docker gehostet wird.

Sie müssen das Image auch nirgendwo hosten, da GitHub es für Sie im Handumdrehen baut. Dies hält alles im GitHub-Ökosystem, was für Open Source riesig ist und das Forken und Teilen so viel einfacher ermöglicht. Sie können die Dockerfile auch direkt in Ihre Aktion einfügen, was bedeutet, dass Sie kein separates Repository für diese Dockerfiles pflegen müssen.

Alles in allem ist es ziemlich aufregend. Teils wegen der Flexibilität: Einerseits können Sie wählen, ob Sie viel Abstraktion wünschen und den benötigten Workflow mit einer GUI und einer bestehenden Aktion erstellen, und andererseits können Sie den Code selbst schreiben, alles innerhalb eines Containers erstellen und fein abstimmen und sogar mehrere wiederverwendbare benutzerdefinierte Aktionen miteinander verketten. Alles an demselben Ort, an dem Sie Ihren Code hosten.