正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

Moa式言語

Moaは、ジョブ実行中に動的に値を構築するための式言語です。式は${{ }}区切り文字で囲まれ、GitLab Functionsとジョブ入力で使用されます。

Moaは、文字列操作、算術、比較、論理演算、プロパティアクセス、および関数呼び出しをサポートしています。

CI/CD式との違い

GitLabには、パイプラインライフサイクルの異なるステージで異なる目的を果たす3つの式構文があります。

  • ルールは、rules:キーワード内で独自の式構文を使用して、ジョブのインクルージョンを制御します。これらはパイプライン作成中に評価され、CI/CD変数に対する比較とパターンマッチングをサポートしますが、算術演算を実行したり、ランタイム状態にアクセスしたりすることはできません。
  • CI/CD式は$[[ ]]構文を使用し、いずれかのジョブが実行される前にパイプライン作成中に評価されます。これらの式は、CI/CDインプットマトリックス値 、およびコンポーネント入力の値置換を実行します。これらは、算術、比較、または論理を実行できず、ランタイム状態にアクセスできません。詳細については、CI/CD式を参照してください。
  • Moaは${{ }}構文を使用し、ジョブ実行中にRunnerによって評価されます。Moaは、演算子、データ構造、関数呼び出しを備えた完全な式言語です。

3つのすべての構文は、同じパイプライン内に共存できます。GitLab Functionsを含むCI/CDコンポーネントは、3つすべてを使用する場合があります:

spec:
  inputs:
    echo_version:
      type: string
---

hi-job:
  # rules expression - evaluated when the pipeline is created
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  run:
    - name: say_hi
      # $[[ ]] - resolved when the pipeline is created
      step: registry.gitlab.com/gitlab-org/ci-cd/runner-tools/gitlab-functions-examples/echo@$[[ inputs.echo_version ]]
      inputs:
        # ${{ }} - resolved when the job runs
        message: "Hello, ${{ vars.CI_PROJECT_NAME }}"

GitLab Functionsがパイプライン作成時には利用できない機能を必要とするため、Moaは別の言語として存在します:

  • ランタイム評価: ステップ出力は、関数が実行されるまで存在しません。${{ steps.build.outputs.image_ref }}のような式は、実行中にのみ評価できます。
  • 型付き値: Moaはネイティブ型(数値、ブール値、配列、オブジェクト)を保持し、文字列に変換することなく関数間で渡します。
  • 演算子と論理: GitLab Functionsは、変数と出力からステップ入力を構築するために、算術演算(major_version + 1)、比較(vulnerabilities == 0)、および短絡論理(inputs.tag || "latest")を必要とします。
  • 機密値の追跡: Moaは、操作を通じて機密値を伝播させます。機密値を文字列に連結したり、関数呼び出しを通じて渡したりすると、結果も機密として扱われます。これにより、ログおよび出力におけるシークレットの偶発的な開示を防ぎます。

コンテキスト参照

式で使用できる値は、式がどこで使用されるかによって異なります。

コンテキスト利用可能評価済み説明
job.inputsジョブ設定: scriptbefore_scriptafter_scriptartifactscacheimageservicesオブジェクトRunnerがジョブを受信したときジョブに定義された入力値。job.inputs.<name>で個別の変数にアクセスします。
envGitLab Functionsオブジェクト関数実行前関数で利用可能な環境変数。env.<name>で個別の変数にアクセスします。
inputsGitLab Functionsオブジェクト関数実行前関数に渡された入力値。inputs.<name>で個別の入力にアクセスします。
varsGitLab Functionsオブジェクト関数実行前CIジョブから渡されたジョブ変数。vars.<name>で個別の変数にアクセスします。
stepsGitLab Functionsオブジェクト関数実行前現在の関数で以前に実行されたステップの結果。steps.<step_name>.outputs.<output_name>でステップの出力にアクセスします。
export_fileGitLab Functions文字列関数実行前関数が環境変数を後続のステップにエクスポートするために書き込めるファイルへのパス。
output_fileGitLab Functions文字列関数実行前関数が出力値を書き込むファイルへのパス。
func_dirGitLab Functions文字列関数実行前関数の定義ファイルを含むディレクトリへのパス。関数にバンドルされたファイルを参照するために使用します。
work_dirGitLab Functions文字列関数実行前現在の実行のための作業ディレクトリへのパス。

テンプレート構文

補間

式を評価するために${{ }}で囲みます:

script:
  - echo "Hello, ${{ job.inputs.name }}"

テキストが式を囲む場合、結果は常に文字列に変換されます。複数の式が単一の値に表示されることがあります:

script:
  - echo "${{ job.inputs.greeting }}, ${{ job.inputs.name }}!"

ネイティブ型パススルー

${{ expression }}が周囲にテキストのない完全な値である場合、式はネイティブ型を返します。数値、ブール値、配列、オブジェクトなどの非文字列値を、文字列に変換せずにステップ間で渡すには、ネイティブ型式を使用します。

inputs:
  count: ${{ steps.previous.outputs.total }}

この例では、totalが数値の場合、countは文字列表現ではなく数値を受け取ります。

Moa式のエスケープ

補間をトリガーせずにテキストにリテラル${{を含めるには、バックスラッシュでエスケープします:

script:
  - echo "Use \${{ to start an expression"

このコマンドは、評価なしでテキストUse ${{ to start an expressionを出力します。

リテラル

ヌル

キーワードnullは、値の不在を表します。

${{ null }}

ブール値

キーワードtruefalseは、ブール値を表します。

${{ true }}
${{ false }}

数値

数値は、53ビットの仮数精度を持つIEEE 754倍精度浮動小数点値です。整数、小数、および科学的表記がサポートされています。

${{ 42 }}
${{ 3.14 }}
${{ 1.5e3 }}
${{ 2E-4 }}

文字列

文字列はダブルクォートまたはシングルクォートで囲みます。2種類のクォートは、エスケープシーケンスとテンプレート式を異なる方法で処理します。

ダブルクォートされた文字列は、テンプレート式とすべてのエスケープシーケンスをサポートします:

シーケンス意味
\\バックスラッシュ
\"ダブルクォート
\n改行
\r復帰
\tタブ
\aアラート(ベル)
\bバックスペース
\fフォームフィード
\v垂直タブ
\/スラッシュ
\uXXXXUnicodeコードポイント
\${{リテラル${{(補間を防止)

ダブルクォートされた文字列内のテンプレート式(${{ }})は評価され、文字列に補間されます。

シングルクォートされた文字列は、最小限の解釈を伴うraw文字列リテラルです。シングルクォートされた文字列内のテンプレート式は評価されません。サポートされているエスケープシーケンスは2つだけです:

シーケンス意味
\\バックスラッシュ
\'シングルクォート
${{ "Hello\nWorld" }}
${{ 'It\'s a string' }}
${{ 'Literal ${{ not evaluated }}' }}

識別子

識別子は、式コンテキストから値を参照します。識別子は、文字またはアンダースコアで始まり、文字、数字、およびアンダースコアを含むことができます。識別子は、大文字と小文字を区別します。fooFoo、およびFOOは、3つの異なる識別子です。

${{ env }}
${{ my_variable }}

識別子は、利用可能なコンテキストに対して解決されます。各コンテキストで利用可能な値については、コンテキスト参照を参照してください。

識別子がコンテキストオブジェクトを参照する場合、オブジェクト全体が返されます。たとえば、${{ vars }}はすべてのジョブ変数をオブジェクトとして返します。

演算子

算術演算子

算術演算子は数値で機能します。+演算子は文字列も連結します。演算子は暗黙的な型変換を実行しないため、"hello" + 42はエラーになります。

Operator説明結果
+加算${{ 2 + 3 }}5
+連結${{ "a" + "b" }}"ab"
-減算${{ 10 - 4 }}6
*乗算${{ 3 * 4 }}12
/除算${{ 10 / 3 }}3.333...
%剰余(切り詰める除算)${{ 10 % 3 }}1

ゼロによる除算はエラーになります。

比較演算子

比較演算子はブール値を返します。

Operator説明結果
==等しい${{ 1 == 1 }}true
!=等しくない${{ 1 != 2 }}true
<未満${{ 1 < 2 }}true
<=以下${{ 2 <= 2 }}true
>より大きい${{ 3 > 2 }}true
>=以上${{ 3 >= 3 }}true

異なる型の値は型によって比較されるため、1 == "1"falseと評価されます。同じ型の値は、次の比較ルールに従います:

  • 数値: 数値比較。
  • 文字列: 辞書式比較(UTF-8バイト順)。
  • ブール値: falsetrue未満です。
  • 配列: 要素ごとの比較。
  • オブジェクト: 長さ、次にキー、次に値によって比較されます。キーの順序は関係ありません。
  • ヌル: nullnullに等しい。

論理演算子

論理演算子は短絡評価を使用し、必ずしもブール値ではなく、オペランドのいずれかを返します。この動作は、JavaScriptの&&および||演算子に似ています。

Operator説明動作
||論理OR左オペランドが真の場合、それを返し、そうでなければ右オペランドを評価して返します。
&&論理AND左オペランドが偽の場合、それを返し、そうでなければ右オペランドを評価して返します。
!論理NOTオペランドが偽の場合trueを返し、真の場合falseを返します。

||演算子は、デフォルト値を提供するために使用されます:

${{ inputs.name || "default" }}

inputs.nameが空でない文字列の場合、そのまま返されます。空またはヌルの場合、"default"が返されます。

単項演算子

Operator説明結果
+単項プラス${{ +5 }}5
-単項マイナス${{ -5 }}-5
!論理NOT${{ !true }}false

演算子の優先順位

演算子は、最も高い優先順位から最も低い優先順位までリストされています。同じ行の演算子は、同じ優先順位を持っています。すべての二項演算子は左結合です。

優先順位演算子
7(最高).[]()
6+-!
5*/%
4+-
3==!=<<=>>=
2&&
1(最低)||

優先順位をオーバーライドするには、括弧を使用します:

${{ (1 + 2) * 3 }}

データ構造

配列

ブラケット表記で配列を作成します。要素は任意の型にすることができ、型を混在させることができます。末尾のカンマを使用できます。

${{ [1, 2, 3] }}
${{ ["a", 1, true, null] }}
${{ [] }}

オブジェクト

ブレース表記でオブジェクトを作成します。キーは文字列に評価される必要があります。値は任意の型にすることができます。末尾のカンマは許可されています。

${{ {name: "runner", version: 1} }}
${{ {"string-key": true} }}
${{ {} }}

オブジェクトキーとして使用される裸の識別子は、変数参照ではなく、文字列リテラルとして扱われます。変数をキーとして使用するには、括弧で囲みます:

${{ {name: "Alice"} }}           # "name" is the string "name", not a variable reference
${{ {(obj.prop): "value"} }}     # key is the value of obj.prop, which must be a string

プロパティアクセス

ドット表記

ドット表記でオブジェクトプロパティにアクセスします:

${{ env.HOME }}
${{ steps.build.outputs.artifact_path }}

ブラケット表記

配列要素をインデックスで、またはオブジェクトプロパティを文字列キーでアクセスします:

${{ my_array[0] }}
${{ my_object["property-name"] }}

プロパティ名にハイフンなどの特殊文字が含まれる場合は、ブラケット表記が必要です。

チェイニング

プロパティアクセスと関数呼び出しをチェーンします:

${{ steps.build.outputs.items[0] }}

関数呼び出し

括弧を使用して関数を名前で呼び出します:

${{ str(42) }}
${{ num("3.14") }}

Truthy

論理演算子と!演算子は、次のtruthyルールを使用します:

Truthyの場合Falsyの場合
ブール値truefalse
文字列長さが0より大きい空の文字列""
数値0ではない0
配列長さが0より大きい空の配列[]
オブジェクト長さが0より大きい空のオブジェクト{}
ヌル常にない常時

組み込み関数

str(value)

任意の値をその文字列表現に変換します。

${{ str(42) }}       # "42"
${{ str(true) }}     # "true"
${{ str(null) }}     # "<null>"

num(value)

文字列を数値に変換します。文字列は有効な数値表現である必要があります。

${{ num("42") }}     # 42
${{ num("3.14") }}   # 3.14

bool(value)

そのtruthyに基づいて任意の値をブール値に変換します。

${{ bool("hello") }}  # true
${{ bool("") }}       # false
${{ bool(0) }}        # false
${{ bool(1) }}        # true

予約語

次の単語は予約されており、識別子として使用することはできません。これらは、将来の言語機能のために予約されています。

arrayasbreakcaseconstcontinuedefaultelsefallthroughfloatforfuncfunctiongotoifimportinintletloopmapnamespacenumberobjectpackagerangereturnstringstructswitchtypevarvoidwhile

キーワードnulltrue、およびfalseもリテラル値として予約されています。

戦略選択によるデプロイ

deploy job:
  when: manual
  inputs:
    environment:
      default: staging
      options: [staging, production]
      description: Target deployment environment
    strategy:
      default: rolling
      options: [rolling, blue-green, canary]
      description: Deployment strategy
    replicas:
      type: number
      default: 3
      description: Number of replicas to deploy
  image: ${{ job.inputs.environment == "production" && "deploy-tools:stable" || "deploy-tools:latest" }}
  script:
    - 'echo "Deploying to ${{ job.inputs.environment }} using ${{ job.inputs.strategy }}"'
    - deploy
        --env ${{ job.inputs.environment }}
        --strategy ${{ job.inputs.strategy }}
        --replicas ${{ str(job.inputs.replicas) }}

ブールジョブ入力からの条件付きフラグ

test_job:
  inputs:
    coverage:
      type: boolean
      default: false
    verbose:
      type: boolean
      default: false
  script:
    - pytest ${{ job.inputs.verbose && "-v" || "" }} ${{ job.inputs.coverage && "--cov=src" || "" }}

ジョブ変数からのイメージ参照のビルド

build_job:
  run:
    - name: build
      func: ./docker-build
      inputs:
        image: ${{ vars.CI_REGISTRY + "/" + vars.CI_PROJECT_PATH + ":" + vars.CI_PIPELINE_IID }}

続行ゲート

security_scan_job:
  run:
    - name: scan
      func: ./security-scan
    - name: gate
      func: ./quality-gate
      inputs:
        should_proceed: ${{ steps.scan.outputs.critical == 0 && steps.scan.outputs.high < 5 }}

バージョン管理

increment_version_job:
  run:
    - name: current
      func: ./find-version
    - name: bump
      func: ./bump-version
      inputs:
        new_version: ${{ str(steps.current.outputs.major + 1) + ".0.0" }}

環境固有の設定

deploy_job:
  run:
    - name: deploy
      func: ./deploy
      inputs:
        registry: ${{ (vars.CI_COMMIT_REF_NAME == "main" && "prod.registry.com") || "staging.registry.com" }}
        replicas: ${{ (vars.CI_COMMIT_REF_NAME == "main" && 5) || 2 }}

A/Bテストを設定する

configure_job:
  run:
    - name: configure_ab
      func: ./traffic-split
      inputs:
        variants: |
          ${{ [
            {name: "control", use_new_feature: false, weight: 90},
            {name: "experiment", use_new_feature: true, weight: 10}
          ] }}