お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。
投稿日:
開発::自動化サービス::GitHub::GitHub Actions

About custom actionsに書いてあることほぼそのままですが、読みづらいのでメモがてら
どうもカスタムアクションからjsを呼び出して使うの、バンドルする必要があるようでかなりだるそうなので実用性は微妙かも…

フォルダ構成

この説明ではtest.yamlをworkflowとし、index.jsを蹴るためのサンプルで説明します

└─.github/
   └─workflows/
       ├─.actions/
       │   ├─action.yaml
       │   └─index.js
       └─test.yaml

サンプルコード

test.yaml

workflow本体です

name: test
on:
  workflow_dispatch:
jobs:
  example:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ./.github/workflows/actions
        with:
          param1: 'xxx'

action.yaml

custom actionです。
ファイル名はaction.ymlないしaction.yamlである必要があります。
これ以外のファイル名の場合、実行時に次のエラーが出ます。

Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under '/home/runner/work/ci-test/ci-test/.github/workflows/actions'. Did you forget to run actions/checkout before running your local action?
name: test actions
description: test
runs:
  using: 'node16'
  main: 'index.js'

index.js

console.log(123);
投稿日:
サービス::GitHub::GitHub Actions開発::自動化

GitHub Actionsで前のジョブの結果を後続で利用したい時に使えるやつ

サンプルコード

  • 適当な文字列を変数にセットして、各ジョブで出力する例
name: outputs sharing example
on:
  pull_request:
jobs:
  first:
    runs-on: ubuntu-latest
    outputs:
      # <out-job-name>: ${{ steps.<step-id>.outputs.<in-job-name> }}
      baz: ${{ steps.foo.outputs.bar }}
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      - id: foo
        # この場合、FOO-BARという値がセットされる
        run: echo "::set-output name=bar::$(echo FOO-BAR)"
      - id: test
        # steps.<step-id>.outputs.<in-job-name>
        run: echo "${{ steps.foo.outputs.bar }}"
  second:
    needs: [first]
    runs-on: ubuntu-latest
    steps:
      - id: test
        # needs.<job-id>.outputs.<out-job-name>
        run: echo "${{ needs.first.outputs.baz }}"

参考

投稿日:
ソフトウェア::Git開発::設計開発::自動化

これは、かつて参画したGitHubを利用したプロジェクトでブランチフローが悪く事故が多発したので考案し、運用した内容です。
基本的には後々の運用を考えた時に情報源になり、かつGit操作に極力手間を取られることがなく、CI/CDを回しながら品質を維持できる内容で考えています。

フローの要件として考えたこと

取り回しが単純明快であること

開発以外の要素に振り回されないように単純なフローにしていて、世に言われる履歴の綺麗さとか言うのは個人的には関心が薄いので重視していません。その代わりコミットが壊れないことや、インデックスとして見やすくなるような部分を重視しています。

GitHubとの相性が良いこと

まず個々の開発タスクをIssueベースで管理し、Pull Requestベースで取り込む運用としました。
Pull Requestの取り込み方式はSquash Mergeとし、メインブランチのコミット履歴がPull Requestのマージコミットになるようにしました。
これはメインブランチのコミット履歴はPull Requestのマージコミットだけあれば後から追えるというのと、メインブランチのコミットログを単純にする意味でこの方式にしています。

CI/CDを活用しやすいこと

これは割とどこでもやっていると思いますが、ブランチ名にdevelopとかstaging, productionとか付けて管理することで、自動的に環境を識別できるようにしました。

実際に運用したフロー

フロー図

運用したブランチフロー

フローの運用内容

  • develop/mainブランチを最新ブランチとする運用
    • develop/mainブランチ相当のものが複数ある状態というのが世の中にあると思いますが、管理が非常に大変なのでそれはしない方向にしました
  • 機能ブランチをdevelop/mainブランチに取り込むのはSquash Merge
    • 基本的に変更履歴を見る時はGitLensやblameで変更行からPull Requestを当てて、そこを見に行くという運用にしていました
  • 機能ブランチにdevelop/mainブランチを取り込むのはmerge
    • 一般的にはrebaseが多いと思いますが、次の観点から採用しませんでした
      • どのポイントで取り込んだのかわからない
      • mergeと比較した場合にコンフリクト対応に手を取られる
        • 経験上ここで事故が頻発する
      • 素直にpush出来ない
    • mergeであれば以下のように単純な流れに出来ますし、push前に差分確認して事故を防ぐことも容易です
      • git switch develop/main
      • git pull
      • git switch -
      • git merge -
      • コンフリクトがあれば解消
      • git push
  • デプロイ方式によるルートブランチ分割
    • ルートブランチ名によってデプロイ先を変更できるようにしました
    • GitHub Actionsでブランチ名を拾って環境変数を差し替えることでデプロイするワークフローを組んでいます
    • staging/production/ブランチはdevelop/mainからcheckoutする運用です
      • これらはデプロイするためだけの使い捨てブランチなので毎回生えます

あとがき

このフローの利点としてはマージでコンフリクトが起きても基本的にCurrentとIncomingを一回比較するだけで済むのでコンフリクトの解消が簡単で、コンフリクト時はIncomingが壊れないようにCurrentを直すのが基本になり、Currentを優先する場合は適宜上書きするといった内容です。

ブランチの合流はmergeだとマージコミット分一回の解消だけでいいので事故の発生要因が低いのがrebaseと比較した時の利点です。rebaseだとコミット回数分再帰的に合流させる必要があるのでブランチの寿命が長かったりすると苦行になってきます。

このフローができた経緯としては元々はGitHub Flowをベースにしていたのですが、色々やっていくうちにこうしたらもっと良くなるのではないか?というのを試行錯誤していてこの形に落ち着いたのですが、後から調べたらGitLab Flowに近い形式に見えたので、似た内容は既に誰かが考えているものだなと感じました。

上で挙げた内容の他にもGitHubのリポジトリ設定でブランチ保護のルールを設定したり、Pull Requestのマージ設定でSquash mergingだけ許可したり、ヘッドブランチの自動削除をするなど、基本的に面倒なことを考えたり、しなくて良い様にするなど、開発に注力しやすいように環境を整えると心理的な抵抗が少なく運用できて便利だなと感じています。

投稿日:
開発::自動化サービス::GitHub

Issueの中にあるTasksの進捗状況集計したい。したくない?したいですよね!
実はGitHubのREST APIを叩いてもTasks情報を素直に取れません
仕方がないので雑に取得するためのシェルスクリプトを書きました

自作するまでの経緯

GH CLI では出来ない

GitHub CLI使ったら簡単に出来るやろ、そう思っていた時代が私にもありました
なんとできません
検索クエリ投げないとProjectで絞れないようなかったり、痒いところに手が届かない子ですし、まぁ許しましょう

REST APIでもできない

でも REST APIなら流石に…なかった

ちょっと待ってほしい、画面上表示されてるのにAPIとしては提供されてないの?
そんなのある?

そんなデータを提供している機能はない

2016年には問題提起されていたようですが絶賛放置中

仕方ないので自作した

API叩いてIssue本文からTasksの情報を雑に抜いて集計するだけのやつです
超雑なのでインデントとかコードフェンスの中とか何も考慮してません

投稿日:
開発::自動化サービス::GitHub::GitHub Actions

pull_requestイベントの公式リファレンスが手薄くイベントの意味を明示してないので動きを実際に確認したものをメモ程度に。基本は意味のままだと思いますが…

opened: PRが開いたとき
reopened: PRが開き直されたとき
synchronize: PRに対してPushが走ったとき

特定ブランチから特定ブランチへのPRを阻止する

  • サンプルで作っただけなので中身は適当
    • pull_requestbranchesを先頭に書かないと、指定ブランチ以外でも走るので注意
name: testing on opend PR to main
on:
  pull_request:
    branches:
      - main
    types:
      - opened
      - reopened
      - synchronize
jobs:
  # 事前ブランチチェック
  before-check:
    runs-on: ubuntu-latest
    steps:
      - name: fail case
        if: startsWith(github.head_ref, 'test/') && github.base_ref == 'main'
        # test/* ブランチから main ブランチ宛である場合
        # exit 1で終了することで Workflow を failure 扱いにする
        # https://docs.github.com/ja/actions/creating-actions/setting-exit-codes-for-actions
        run: exit 1
        # 前の if に入らなければ、そのまま次のジョブにつながる
  after-exec:
    # 指定されたジョブの成功を要求、失敗している場合、このジョブを実行しない
    # 必然的に線形実行になる(並列では走らない)
    needs: [before-check]
    runs-on: ubuntu-latest
    steps:
      - name: TEST!
        run: echo "RUN after-exec"