Zum Inhalt springen

GitHub Actions Expression Tester · CI/CD

Testen Sie Ihre if:-Bedingungen und Trigger, bevor Sie pushen.

Werten Sie ${{ }}-Ausdrücke gegen einen bearbeitbaren Mock-Kontext aus, fangen Sie das if: ab, das stillschweigend immer wahr ist, und simulieren Sie, welche Jobs für ein push, einen PR oder ein Tag laufen — sofort, in Ihrem Browser. Keine commit-push-pray-Schleife.

Läuft in Ihrem Browser — nichts, was Sie einfügen, verlässt diese Seite. Wie wir das belegen

Läuft in Ihrem Browser Keine Anmeldung Exakte GitHub-Semantik Aktualisiert am 29.07.2026

GitHub Actions Expression- und Trigger-Playground

if-condition
context (editable mock)

Results update as you type — press ⌘/Ctrl + Enter to run now. Press Esc to release the editor. Your input never leaves the browser.

Result

Load an example or write an if: condition, then Evaluate to see whether it is true, the returned value, and a token-by-token breakdown.

.github/workflows/ci.yml
Event scenario

Results update as you type — press ⌘/Ctrl + Enter to run now. Press Esc to release the editor. Nothing is uploaded.

Decision

Load an example or paste a workflow, set an event, then Simulate to see which jobs run or are skipped — and why.

100% in your browser · no signup

Die Lücke

Hören Sie auf, durch Pushen zu debuggen.

Jeder hat es schon getan: ein if: zu einem Schritt hinzufügen, pushen, zusehen, wie es läuft, obwohl es das nicht sollte, anpassen, erneut pushen — zwanzig Dummy-Commits später stellen Sie fest, dass die Bedingung die ganze Zeit eine literale Zeichenkette war. GitHub wertet nur das aus, was innerhalb von ${{ }} steht; alles außerhalb ist literaler Text, und eine nicht leere Zeichenkette ist immer truthy.

Die Trigger-Seite ist genauso undurchsichtig: ein Workflow, der nicht läuft, erzeugt überhaupt keine Ausgabe — die Entscheidung fällt im Event-Filtering von GitHub, bevor irgendein Runner startet. Branch- und Pfad-Filter werden mit AND kombiniert, Tag-Pushes werden ausgeschlossen, wenn Sie branches, aber nicht tags setzen, und ** verhält sich anders als *.

Dieses Tool wertet beides aus — einen einzelnen Ausdruck oder einen ganzen Workflow gegen ein Event — und nutzt dabei GitHubs exakte Regeln, sodass Sie die Antwort im Browser erhalten. Siehe GitHubs expressions- und workflow-trigger-Dokumentation sowie das „immer wahr“-Fallen-Issue.

Springen Sie zum Cheat-Sheet oder zum Live-Playground oben.

Die Pipeline

So funktioniert es.

Fünf deterministische Schritte laufen bei jeder Auswertung von Anfang bis Ende durch — jedes Mal komplett in Ihrem Browser-Tab.

  1. Wählen Sie einen Tab.

    Werten Sie ein einzelnes if: / einen Ausdruck aus, oder wechseln Sie zum Trigger Simulator, um einen ganzen Workflow gegen ein Event zu testen.

  2. Setzen Sie den Kontext.

    Bearbeiten Sie das Mock-JSON github/env/matrix/steps/needs (oder beschreiben Sie das Event: Typ, Ref, geänderte Dateien), sodass es dem Lauf entspricht, der Sie interessiert.

  3. Mit GitHubs Grammatik parsen.

    Der Ausdruck wird mit derselben Operator-Präzedenz und demselben Funktionssatz tokenisiert und geparst, die der Runner verwendet — kein Shell-Aufruf, kein Netzwerk.

  4. Die exakten Semantiken anwenden.

    Coercion, case-insensitive Gleichheit, operandenliefernde && / ||, Glob-Filter und die branch+path-UND-Regel werden gegen einen versionierten Konformitäts-Korpus repliziert.

  5. Das Urteil + das Warum zeigen.

    Sie erhalten das truthy/falsy-Ergebnis und den zurückgegebenen Wert, die „immer wahr“-Fallenwarnung dort, wo sie zutrifft, sowie eine RUNS/SKIPPED-Tabelle pro Job mit dem ausschlaggebenden Grund.

Cheat-Sheet

Die Regeln, über die Leute stolpern.

Die Falle, die Coercion-Überraschungen, die Funktionen und die Trigger-Globs — jeweils mit einem ausführbaren Beispiel, das Sie in das Playground einfügen können.

Die „immer wahr“-Falle

Am häufigsten

GitHub wertet nur das aus, was innerhalb von ${{ }} steht. Außerhalb belassene Operatoren werden nach der Substitution zu literalem Text — einer nicht leeren Zeichenkette, die immer truthy ist. Der Evaluator markiert dies (actions/runner#1173).

Immer wahr

.github/workflows/ci.yml
# ALWAYS TRUE — operators sit OUTSIDE ${{ }}
jobs:
  deploy:
    if: ${{ github.ref }} == 'refs/heads/main'
    # after substitution this is the literal string
    #   refs/heads/main == 'refs/heads/main'
    # a non-empty string => truthy => runs on EVERY branch

Behoben

.github/workflows/ci.yml
# CORRECT — wrap the WHOLE condition in one ${{ }}
jobs:
  deploy:
    if: ${{ github.ref == 'refs/heads/main' }}
    # now GitHub evaluates the comparison, not a literal string

Operatoren & Coercion

YAML
# GitHub's coercion is JS-like and case-insensitive:
${{ 'ABC' == 'abc' }}      # true  (strings compare case-insensitively)
${{ null == 0 }}           # true  (both coerce to the number 0)
${{ '' || 'fallback' }}    # 'fallback'  (|| returns an OPERAND, not a bool)
${{ github.x && 'yes' }}   # 'yes' when github.x is truthy
${{ 'true' == true }}      # false (string 'true' coerces to NaN)

Funktionen

YAML
${{ contains('refs/heads/main', 'main') }}     # true (substring, case-insensitive)
${{ startsWith(github.ref, 'refs/tags/') }}    # is this a tag push?
${{ format('{0}-{1}', 'app', github.sha) }}    # 'app-d6cd1e2…'
${{ fromJSON('["a","b"]') }}                   # a real array
${{ always() }}  ${{ success() }}  ${{ failure() }}  # status checks

Trigger, branches & paths

YAML
on:
  push:
    branches: [main]      # AND
    paths: ['src/**']     # — both must match to trigger
# feature/* matches feature/a but NOT feature/a/b
# feature/** matches both (** crosses '/')

Genauigkeit & Umfang

Dies ist ein Semantik-Playground, kein Runner. Es repliziert GitHubs dokumentiertes Ausdrucks- und Trigger-Verhalten gegen einen versionierten Konformitäts-Korpus (im Tool als semantics:-Label angezeigt), aber es führt keine Jobs aus, ruft nicht die Live-Inhalte referenzierter Actions ab und berechnet kein echtes hashFiles() — das benötigt Dateien, die nur der Runner sehen kann, daher wird es als Platzhalter angezeigt. Das vollständige github.event-Payload ist als bearbeitbarer Mock modelliert, den Sie kontrollieren. Behandeln Sie ein sauberes Ergebnis als starke Sicherheit vor dem Push, und kombinieren Sie es dennoch mit actionlint für die Syntax.

FAQ

Fragen, beantwortet.

Tippen Sie auf eine Frage, um die Antwort aufzuklappen.

Er hat zwei Tabs. Der Expression Evaluator führt Ihre ${{ }}-Ausdrücke gegen einen bearbeitbaren Mock-Kontext (github, env, matrix, steps, needs) aus und nutzt dabei die exakten Semantiken von GitHub Actions — die Operatoren, das case-insensitive String-==, die JS-ähnlichen Coercion-Regeln und dokumentierte Funktionen wie contains, startsWith, endsWith, format, join, toJSON, fromJSON, success(), failure(), always() und cancelled(). Der Trigger Simulator lässt Sie ein push-, pull_request- oder tag-Event beschreiben und zeigt eine RUN- oder SKIPPED-Tabelle pro Job, die genau erklärt, welcher on:-Filter aus branches, tags, paths oder paths-ignore über das Ergebnis entschieden hat. Zusammen beantworten sie „wird dieses if: wahr sein?“ und „wird dieser Workflow überhaupt ausgelöst?“, bevor Sie pushen.

Fast immer, weil das if: literalen Text außerhalb von ${{ }} enthält — zum Beispiel if: "${{ github.event_name }}" == 'push' oder if: always-deploy. GitHub wertet nicht die ganze Zeile als einen einzigen Ausdruck aus; die literalen Zeichen machen die Bedingung zu einer nicht leeren Zeichenkette, und eine nicht leere Zeichenkette ist truthy, sodass der Schritt jedes Mal läuft. Schließen Sie die gesamte Bedingung in ein einziges ${{ }} ein (z. B. if: ${{ github.event_name == 'push' }}), und der Expression Evaluator markiert die Falle (actions/runner#1173) und zeigt Ihnen das korrigierte, truthy- oder falsy-Ergebnis.

Fügen Sie den Ausdruck in den Tab „Expression Evaluator“ ein und bearbeiten Sie den Mock-Kontext github/env/matrix/steps/needs so, dass er dem Lauf entspricht, der Sie interessiert — ohne Commit, ohne Push, ohne auf einen Runner zu warten. Sie erhalten den ausgewerteten Wert sofort, plus eine Warnung, falls die Syntax stillschweigend zu „immer wahr“ verfälscht würde. Es ist der schnellste Weg, eine if:-Bedingung oder eine ${{ }}-Interpolation zu überprüfen, bevor sie jemals GitHub Actions erreicht.

Das sind Status-Check-Funktionen, die Sie in einem if: verwenden. success() ist nur dann wahr, wenn jeder vorherige Schritt oder benötigte Job erfolgreich war (es ist der implizite Standard in dem Moment, in dem Sie kein if: schreiben), failure() ist wahr, wenn einer von ihnen fehlgeschlagen ist, cancelled() ist wahr, wenn der Workflow abgebrochen wurde, und always() erzwingt, dass der Schritt unabhängig vom vorherigen Status läuft — auch bei einem Abbruch. Der Haken ist, dass das Schreiben eines beliebigen eigenen if: den impliziten success()-Schutz entfernt, sodass if: env.DEPLOY == 'true' auch dann läuft, wenn ein vorheriger Schritt fehlgeschlagen ist, sofern Sie nicht && success() hinzufügen. Der Evaluator lässt Sie den Mock-Status umschalten und jede Funktion auflösen sehen.

Die üblichen Ursachen sind eine Ref, die nicht zu Ihrem on:-Glob für branches oder tags passt, eine Workflow-Datei, die auf dem Ziel-Branch noch nicht existiert, oder ein paths-Filter, der jede geänderte Datei ausschließt. Eine subtile Ursache: Wenn Sie unter demselben Event sowohl branches als auch paths setzen, werden sie mit UND kombiniert — das Event muss zu beidem passen, nicht zu einem von beiden. Beschreiben Sie Ihr Event im Trigger Simulator, und er spielt die on:-Filter erneut ab und nennt Ihnen den ausschlaggebenden Grund für jeden Job.

Innerhalb eines einzelnen Events werden branches (oder tags) und paths mit UND verknüpft: ein push muss auf einem passenden Branch erfolgen und einen passenden Pfad berühren, damit der Workflow läuft. Innerhalb eines einzelnen Filters werden die Muster mit ODER verknüpft — ein einziger passender branch-Glob oder ein einziger passender geänderter Pfad genügt. Der Trigger Simulator macht dies explizit, indem er die Branch-Entscheidung und die Pfad-Entscheidung separat anzeigt und danach das kombinierte RUN- oder SKIPPED-Urteil.

* passt auf beliebige Zeichen außer dem Pfadtrenner /, während ** über Trenner hinweg passt, einschließlich /, sodass feature/** auf feature/a/b passt, feature/* aber nur auf feature/a. Die Glob-Engine berücksichtigt außerdem +, ?, ! als Negation und \ als Escape genauso, wie GitHub es tut. Der Trigger Simulator verwendet eine getreue Neuimplementierung dieser Regeln, sodass Sie ein Muster wie 'release/**' oder '!**/*.md' gegen eine echte Ref oder Dateiliste testen und sehen können, was passt.

Im Trigger Simulator geben Sie den Event-Typ, den Ref-Namen und die Liste der geänderten Dateien an; das Tool wertet dann die on:-Filter jedes Jobs und jedes if: auf Job-Ebene gegen dieses simulierte Event aus und rendert eine RUN- oder SKIPPED-Zeile mit dem ausschlaggebenden Grund — „Branch passte, aber Pfad nicht“, „kein paths-Filter“, „if: wurde zu falsch ausgewertet“ und so weiter. Es spiegelt die Entscheidungsreihenfolge von GitHub Actions wider, statt zu raten, sodass das Urteil dem entspricht, was der echte Runner für dieses Event tun würde.

actionlint ist ein statischer Linter für Workflow-Syntax und Ausdruckstypisierung, und act führt Ihre Jobs tatsächlich in lokalen Docker-Containern aus — beide sind großartig und einen Einsatz wert. Dieses Tool tut keines von beidem: Es führt Ihre Schritte nicht aus und ist kein Typprüfer. Es ist ein Semantik-Playground, der einen einzelnen ${{ }}-Ausdruck auswertet oder das Trigger-Filtern gegen einen von Ihnen kontrollierten Kontext simuliert, im Browser, sodass Sie nachvollziehen können, warum ein if: truthy ist oder warum ein Workflow ausgelöst wurde oder nicht — ohne Container hochzufahren oder Commits zu pushen.

Alles, was von echtem Runner-Zustand abhängt. hashFiles() benötigt die tatsächlichen Dateien auf der Festplatte, daher behandelt der Evaluator es als undurchsichtigen Platzhalter, statt einen echten Hash zu berechnen; das vollständige Webhook-Payload ist weit größer als der Mock-github-Kontext, den wir bereitstellen; und Live-Action-Inhalte, Secrets und Runner-Labels werden nicht aufgelöst. Behandeln Sie ein sauberes Ergebnis als starke Sicherheit vor dem Push hinsichtlich Ausdrucks- und Trigger-Logik — nicht als Garantie für das Datei-Hashing oder das vollständige Event-Payload.

Nein. Beide Tabs laufen zu 100 % clientseitig. Die Ausdrücke, der Mock-Kontext, die Workflow-Filter und die Event-Payloads, die Sie eingeben, werden in Ihrem Browser-Tab ausgewertet — nichts wird hochgeladen, es gibt kein Konto und keine Anmeldung. Sie können bedenkenlos interne oder proprietäre Workflows einfügen, einschließlich Secret-Namen, privater Runner-Labels und echter Branch- und Pfadlisten.

Nein. Dies ist ein unabhängiges Community-Tool und steht in keiner Verbindung zu GitHub, Inc., wird von diesem nicht unterstützt oder gesponsert. „GitHub“ und „GitHub Actions“ werden hier ausschließlich beschreibend verwendet, um das Ausdrucks- und Workflow-Trigger-Format zu kennzeichnen, das das Tool auswertet.

More free, private DevOps tools.

Der GitHub Actions Expression Tester ist eines von vielen Tools in OpsCanopy — einem wachsenden Schirm browserbasierter Validatoren, Konverter und Tester, die niemals einen Server berühren.

39 kostenlose Tools, jedes einzelne offlinefähig — opscanopy.com funktioniert ohne Registrierung, und nichts wird hochgeladen.

Verwandte Tools: der GitHub Actions Validator und AlertLint, der Loki-Regel-Tester. Durchsuchen Sie das vollständige Tools-Verzeichnis.

Nicht verbunden mit, unterstützt von oder gesponsert durch GitHub, Inc. GitHub und GitHub Actions sind Marken von GitHub, Inc., hier ausschließlich beschreibend verwendet, um das Ausdrucks- und Workflow-Trigger-Format zu kennzeichnen, das dieses Tool auswertet.