3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GitHub ActionsAdvent Calendar 2023

Day 14

はじめてのCustom Action作成

Last updated at Posted at 2023-12-11

取り組んだきっかけ

先月末から今月の上旬にかけて、Github Actionsに浸かっています。
色々触っている中で、Custom Actionが気になり始めました。

あるworkflowを作成時、AWS Lambda更新のため、以下を利用しました。

どんなことをしているか、大雑把にはわかりましたが、
まずは、一通りリリースまでやってみよう!
ということで、より初歩的なCustom Actionを探しました。

Custom Actionとは?

Custom Actionは、workflow内のuses:で記述したアクションのことです。

actions/checkoutがその一例です。

steps:
  - uses: actions/checkout@v4

アクションとしての作り方として、以下の3種類あるようです。

  • Docker コンテナー(linuxのみ対応)
  • JavaScript
  • 複合アクション

初歩的なCustom Actionをマネる

gitの基本的な操作(Push、PR)はご存知の前提で進めます。

以下の動画が、Custom Action駆け出しの私にはピッタリでした。
この動画に沿って進めて作業をします。
先ほどお話した3種類の作り方の中では、JavaScriptに分類されます。

主なスタックですが、TypescriptとJestをです。
前提知識はなくても作業は進められる、と思います。

土台作成

Custom Action作成で基本的には必要なファイルから用意します。

action.yml、package.json

action.ymlの記載項目です。

  • name:作成するアクションの名前を設定します。マーケットプレイスに公開するために、この値は他の公開されたアクションと重複してはいけません。
  • description:何ができるアクションか、説明を記載します。
  • inputs:実行時にどのようなパラメータを必要とするか記載します。
  • outputs:以降のworkflowで使用できるパラメータと設定値を記載します。
  • runs:実行環境と実行ファイルを指定します。

他の項目について、詳細はこちらに記載されています。

hello.yml
name: "Label new pull requests Try"
description: "Add a label when a new PR is opened Try."
author: "eno-conan"

runs:
  using: "node16"
  main: "dist/index.js"

以下を実行すると、package.jsonが生成されます。

npm init -y
gitignore

この段階では、コマンド実行のみでOKです。

npx gitignore node
tsconfig.json

typescriptのインストール・初期化を実施します。

npm i -D typescript
npx tsc --init

コンパイル設定は以下の通りです。

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2019",
    "module": "commonjs",
    "outDir": "dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
}
src/index.ts

最初はこれだけでいきます。

index.ts
console.log("Hello My World!!");

package.jsonを以下のようにして、buildを実行し、jsファイルを生成します。

package.json
"scripts": {
    "build":"tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
}
npm run build
.github/workflows/XXX.yml

最初は手動でworkflowを実行できるようにします。

ymlの内容
name: "Hello"

on:
    workflow_dispatch:

jobs:
  hello:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ./

コードをpushします。
Run workflowをクリックします。成功が確認できましたら、次に進みましょう。
image.png

Github Actionsの動作確認ですが、nektos/actを使うと、ローカルでも行えます。
気になる方は、自分の記事で恐縮ですが、ご覧ください!

githubとの連携実装

必要なライブラリをインストールします。

npm install @actions/core @actions/github
npm install -D ts-node
src/index.ts更新

適切なパラメータが与えられれば、
パラメータlabelの値で、PRのLabelsにその値を設定するworkflowです。

更新される箇所(PR画面)
image.png

index.tsの内容
index.ts
import { getInput, setFailed } from "@actions/core";
import { context, getOctokit } from "@actions/github";

export async function run() {
    const token = getInput("gh-token");
    const label = getInput("label");

    const octokit = getOctokit(token);
    const pullRequest = context.payload.pull_request;

    try {
        if (!pullRequest) {
            throw new Error("This action can only be run on Pull Requests");
        }

        await octokit.rest.issues.addLabels({
            owner: context.repo.owner,
            repo: context.repo.repo,
            issue_number: pullRequest.number,
            labels: [label],
        });
    } catch (error) {
        setFailed((error as Error)?.message ?? "Unknown error");
    }
}

if (!process.env.JEST_WORKER_ID) {
    run();
}
.github/workflows/XXX.yml更新

PRがopenedまたはreopenedをトリガーに、実行します。

name: "Hello"

on:
  pull_request:
    types: [opened, reopened]
jobs:
  hello:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ./
        with:
          gh-token: ${{ secrets.GITHUB_TOKEN }}
          label: "needs-review"

build、pushと行います。main以外のブランチでテキトーにファイル作成して、
PRを作成します。workflowが実行されますが、失敗します。

Error: Cannot find module '@actions/core'

@vercel/ncc導入

動画内の説明より

TypeScriptでコードを書いている場合、tscコンパイル後のコードは自動的にはNode.js互換形式にはなりません。

これを解決するために、@vercel/nccを使います。

nccはTypeScriptのコードをCommonJSに変換して1つのファイルにbundleしてくれます。import/export文を解決し、Node.jsのモジュールシステムと互換性を持たせることで、先ほどのエラーを解消します。

npm i @vercel/ncc
package.jsontsconfig.json.gitignore更新
package.json
- "build": "tsc",
+ "build": "tsc && ncc build lib/index.js",
tsconfig.json
- "outDir": "dist",
+ "outDir": "lib",
.gitignore
.pnp.*

+ lib

libを追加した理由(動画内の説明より)

ビルド結果のアーティファクトであり、ソースコードではありません。
Gitではソースコードのみ追跡するのが、望ましいはずです。
distが公開されるべき最終成果物で、libは中間生成物的な位置づけです。
Gitに含める必要性が低いため除外します。

これでbuild、pushで完成!といきたいですが、
もう1つ修正が必要です。

リポジトリの権限変更

push後、PRをclosedreopenedとして、workflowを確認すると、
以下エラーが表示されます。

Resource not accessible by integration

特定のLabelsを付与する、つまり書き込み(更新)権限が必要です。
Settings(※)から以下画像の通り修正し、保存して完了です。

image.png
※以下URLの一番下の項目
https://github.com/{username}/{repo_name}/settings/actions

テストコード

必要なライブラリをインストールします。

npm i -D jest ts-jest @types/jest

動画では、Github Copilotでテストコードを生成していました。
以下のテストを実施しています。

  • should throw an error if not run on a pull request
    • PRで実行されてない場合にエラーを出力すること
  • should add label to the pull request
    • PRでlabelが設定されていること
  • should handle error and set failed
    • Error時にステータスが失敗になること

詳細は以下の通りです。

Market Placeに公開

青い部分のボタンをクリックします。規約の承認後、必要事項の設定をします。
image.png

image.png

See list of avaliable XXXというリンクから、IconとColorを選んで、action.ymlに設定します。

action.yml
runs:
  using: "node16"
  main: "dist/index.js"

+ branding:
+  icon: "anchor"
+  color: "blue"

Push後、README.mdを追加して、Commitします。

以下状態になったら、Publish Releaseをクリックします。
二段階認証の対応があるので、それが終われば、リリース完了です!!!
image.png

image.png

赤線部分、MarketPlaceをクリックすると、以下のように表示されます。
また、Use latest Versionをクリックすると、workflowでの記述を内容をコピーできます。
image.png
image.png

他リポジトリから利用

リリースできました。
他リポジトリから利用してみます。新しい/既存リポジトリはお任せします。
name: Label new pull requests Tryの部分に、作成したCustomアクションの名前とパラメータを設定します。

name: act-sample

on:
  # push:
  pull_request:
    types: [opened, reopened]

jobs:
  echo_text:
    runs-on: ubuntu-latest
    steps:
      - name: echo Hello world
        run: echo "Hello world!!"
      - name: Label new pull requests Try
        uses: eno-conan/ga-label-issue-try@v1.0.0
        with:
          label: "needs-infra-member-review"
          gh-token: ${{secrets.GITHUB_TOKEN}}

PRを作成して実行すると、labelの文言がLabelsに設定できました!

image.png

残り作業と補足

この後、huskyやLinterの設定などを行う部分が残っていますが、この記事ではその内容はスキップします。

また、作業が一通り終わってから気付いたのですが、テンプレートが用意されていました。(JS/TS)

LICENSE周りの理解

動画では登場しませんでしたが、より本格的になったときに、避けて通れない内容です。しかし、全く触れてきておらず、マズイかも・・といった気持ちも持ちつつこの文章を書いています。
公式ドキュメントや皆さまが書かれた記事の情報をお借りして、超基本的な部分だけかもしれませんが、学んでいる最中です。。。

自分のソースコードを広く提供し、自由に利用してもらいたいという場合は「MIT License」が最適だとのこと。

確かに、MIT Licenseは見覚えがあります。

OSSライセンスとは、OSSの使用許諾条件のことであり、著作権に基づいてOSSの利用条件を定義するものとなります。逆に言えばOSSとは、OSSライセンスを遵守することを条件に使用が許諾されていると言うことができます。

まとめと今後

初歩的な内容ですしたが、Custom Actionの公開、利用まで実施できました。
以前npmのライブラリ公開の初歩を学んだときがありましたが、
何かを便利に柔軟に、といった考え方に基づいて自作するのは、面白いと感じます。

今後は、OSSライセンスの話も勉強しながら、
githubのPRに関係する別のActionや、AWSサービスが関係するActionの作成をしていきたいと思います!

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?