0
0

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.

GitHubActionsでDanger JSを使用する

Last updated at Posted at 2022-11-02

概要

  • DangerとはPull Request(以下PR)の自動チェックを行えるツールです。
  • 今回はGitHubActionsを使って、PRを行ったときにDangerでそのPRの自動チェックを走らせてみます。
image

GitHub

参考

// ブランチ名の取得例
warn("base: " + danger.github.pr.base.ref);  // develop
warn("head: " + danger.github.pr.head.ref);  // feature/hoge

導入例

  • リポジトリに./.github/workflows/actions.ymlを作成。
  • GitHubActionsでPR時にDangerが走るように設定します。
  • danger-js@xxxのバージョンは適宜置換します
name: Danger JS
on: [pull_request]

jobs:
  build:
    name: Danger JS
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Danger
      uses: danger/danger-js@11.0.2
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        DANGER_DISABLE_TRANSPILATION: true
  • 続いてリポジトリ直下にdangerfile.jsを作成します。
  • 大半の設定はその他記事からの参考ですが、checkBranchNamesの箇所は自分で書いてみました。jsは知らないので雰囲気ですが。
  • messageは単純にコメントを書き込むDSL。定型文を返す時など。
  • fail() を呼び出すと ci は失敗し、マージできないようになります。
  • warn() の場合は警告を表示しますが、マージは可能です。
// ===== Functions =====

function checkBranchNames(head_branch, base_branch) {
  // head(例: feature) -> base(例: develop)
  const template_branches = ["release", "master", "main", "develop", "feature/", "revert/", "hotfix/"];

  // ブランチ名が想定する名称かどうかの確認
  is_valid_head_branch_name = false;
  for (const template_branch of template_branches) {
    if (head_branch.startsWith(template_branch)) {
      is_valid_head_branch_name = true;
      break;
    }
  }

  if (!is_valid_head_branch_name) {
    // warn(`ブランチ名が不正です: ${head_branch}\n次のいずれかの名称を使用してください: \n${template_branch_names.join(' ')}`);
    fail(`ブランチ名が不正です: ${head_branch}\n次のいずれかの名称を使用してください: \n${template_branches.join(' ')}`);
  }

  // ブランチ名とマージの整合性確認
  // 仮に誤ってdevelop -> featureとしてしまったときに検出させるとか。
  // TODO...
}

// ===== Entry Point =====


let isAllCheckPassed = true;

// ===== Title =====

// PRのタイトルに[WIP]が含まれる場合は、作業中なのでfailさせる
if (danger.github.pr.title.includes('[WIP]')) {
  fail("Should NOT inclued 'WIP' in your PR title");
}

// PRのタイトルに課題番号が含まれているかどうか(DEV_1-XXX)
const hasIssuesNumber = /DEV_1-[0-9]/.test(danger.github.pr.title);
if (!hasIssuesNumber) {
  warn("Should include issues number in your PR title");
  isAllCheckPassed = false;
}

// ===== Settings =====

// PRにレビュアーが指定されているかどうか
if (!danger.github.pr.reviews) {
  warn("Should select PR reviewer");
  isAllCheckPassed = false;
}

// PRにassigneesが指定されているかどうか
if (!danger.github.pr.assignee) {
  warn("Should select PR assignees");
  isAllCheckPassed = false;
}

// ===== Changing amount =====

// 500行以上の追加・削除の変更があったかどうか
const diffSize = Math.max(danger.github.pr.additions, danger.github.pr.deletions);
if (diffSize > 500) {
  warn("Should reduce diffs less than 500");
  isAllCheckPassed = false;
}

// 変更したファイルの数が10より多いかどうか
if (danger.github.pr.changed_files > 10 ) {
  warn("Should reduce change files less than 10");
  isAllCheckPassed = false;
}

// ===== Branch =====

checkBranchNames(danger.github.pr.head.ref, danger.github.pr.base.ref)

// ===== Result =====

if (isAllCheckPassed) {
  markdown('## All checkes have passed :tada:');
}
  • 以上の内容をmainブランチにプッシュしてPRを作ってやると、GitHubActionsによってDanger JSが動作しPRの自動チェックが走ってくれます。
image
  • PRを更新して再度チェックする場合は以下をクリック(多分)
image

その他チェック項目の例

  • Dangerで実現できることを把握したかったので、他の方の事例で行っているをいくつか抜粋しています。

Danger (JS) を GitHub Actions で導入する

  • CHANGELOG.md が変更されていないと怒られるやつです。
dangerfile.js
const hasChangelog = danger.git.modified_files.includes('CHANGELOG.md')
const isTrivial = (danger.github.pr.body + danger.github.pr.title).includes(
  '#trivial'
)

if (!hasChangelog && !isTrivial) {
  warn('Please add a changelog entry for your changes.')
}

コードレビューの機械的な指摘はDangerに任せる

各リポジトリでDangerfileを用意してチェック項目を記述していますが、組織独自のルールなど共通する処理は専用リポジトリで管理して参照するようにしています。
例えば、danger-lclというリポジトリを用意して共通のチェック項目を記述したDangerfileを管理します。 そして別のリポジトリのDangerfileで下記を追加することで、そのリポジトリのDangerfileの内容を読み込むことができます。

# dangerfile.js内
# danger-lclを読み込み
danger.import_dangerfile(github: "XXX/danger-lcl")
dangerfile.js
# ===== Description =====

# 本文が1行以上書かれているか10行以下の軽微な変更は考慮
warn "作業内容について本文に1行以上の説明を記載してください。" if github.pr_body.length < 1 && git.lines_of_code > 10

...

# ===== Label =====

labels = github.pr_labels

# ラベルが付いていなかったらwipラベルを付ける
add_label "wip", 'fbca04' if labels.empty?

Dangerで始めるPull Requestチェック自動化

  • ライブラリの更新があった場合にテストを書くことをチェック
  • ブランチの運用確認
dangerfile.js
has_lib_changes = !git.modified_files.grep(/^lib/).empty?
has_test_changes = !git.modified_files.grep(/^(features|spec)/).empty?
has_changelog_changes = git.modified_files.include?("CHANGELOG.md")
if has_lib_changes && !has_test_changes
  warn("There are code changes, but no corresponding tests. "\
       "Please include tests if this PR introduces any modifications in "\
       "#{project_name}'s behavior.",
       :sticky => false)
end
# --------------------
# base branch
# --------------------
is_to_master = github.branch_for_base == 'master'
is_to_release = !!github.branch_for_base.match(/release-[0-9]+\.[0-9]+\.[0-9]/)
is_from_release = !!github.branch_for_head.match(/release-[0-9]+\.[0-9]+\.[0-9]/)

if is_to_master && !is_from_release
  warn('masterへmerge出来るのはrelease branchのみです。')
end

if is_to_release
  warn('release branchに対してPRを向けないで下さい。develop branchに向けてPRを作成し、develop branchをrelease branchにmergeしてください。')
end

アプリ開発を支える10個のDangerレシピ

dangerfile.js
  • githubの更新があった箇所のみ指摘する
github.dismiss_out_of_range_messages
  • PR担当者を該当PRの起票者に割り当てたい
## assigneeが未割り当てかのチェック
if github.pr_json['assignee'] == nil
  ## github.api 経由で GitHubの操作可能
  github.api.add_assignees(
    github.pr_json['base']['repo']['full_name'],
    github.pr_json['number'],
    [github.pr_author] ## <- 起票者は github.pr_author
  )
end

レシピ4:JIRAのリンクを掲載したい

git.commits.each do |commit|
  # コミットメッセージからJIRAの番号を抜き出しています"MIR-"の部分は自社でお使いのJIRA IDに置き換えてください
  match = commit.message.match /(MIR-\d+)/ 
  if match
    message(
      ":paperclip: <a href='https://xxx.atlassian.net/browse/#{match[1]}'>#{match[1]}</a>"
    )
  end
end

所感

  • PRのメッセージのテンプレートを設定することに加えて、自動チェックを走らせられることでより快適にPR運用ができる。
  • GitHubActions自体に言えることですが、リポジトリのプログラムとは独立して設定できるのは気楽で良いですね。
  • Dangerfileの言語にはRuby,TypeScript,JavaScriptといろいろ使えるので、ネットで検索する際は混同しないように注意。
  • actions.ymldangerfile.jsの設定はデフォルトブランチのみ有効になります。
    • そのためDangerの設定でいろいろ試す際は別のリポジトリで試したり、(お行儀は良くないですが)mainブランチでrebaseしてコミット履歴をきれいにする、もしくはローカルでDangerを動かすといいかなと思っています。
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?