もりはやメモφ(・ω・ )

ITとか読書感想文とか

GitHub Actionsでサーバからファイルを差分があったときだけ更新して取得

以下の要求をみたすGitHub Actionsを書いたので備忘でメモ

  • 取得したいファイルは各サーバのローカルに保存される
  • ファイルをサーバ名ごとのディレクトリの下へ取得し、GitHubのプライベートリポジトリにプッシュ
  • そのファイルは不定期に更新される
  • 取得を定期的に行うが、更新が行われていない場合はファイルを取得しない
  • サーバ名は 固定文字 + 2桁の連番

f:id:morihaya:20210430113011p:plain
Retrieving files with Github actions
そしてActions用のコードが以下です。 ポイントは

  • サーバへssh(rsync)するため self-hosted ランナーを利用
  • ログ名をつけるときに date コマンドを使うので TZ: "Asia/Tokyo" を指定
  • SSH秘密鍵はGitHubのシークレットに設定
  • 仮にサーバが10台あるとして、 for へ seq -f '%02g' 1 10 で数字を0埋めしつつ渡す
  • git diff --exit-code で差分があった場合のリターンコードを変更*1
  • 差分があった場合にHEADから git show を利用してファイルを取り出し
name: get_file

on:
  schedule:
    - cron:  '0 * * * *'
  workflow_dispatch:
jobs:
  build:
    runs-on: self-hosted
    steps:
    - uses: actions/checkout@v2
    - name: Deploy
      env:
        servername: "target"
        domain: "morihaya.local"
        sshuser: "github-actions"
        TZ: "Asia/Tokyo"
      run: |
        hostname
        date
        pwd
        ls -l
        # RSYNCの準備
        sudo apt-get install -y rsync
        echo "${{secrets.SSH_PRIVATE_KEY_ANSIBLE}}" > /tmp/sshkey
        chmod 400 /tmp/sshkey
        # 高速化のためにstrategy matrixを利用しない
        for number in $(seq -f '%02g' 1 10)
        do
          echo "# ${servername}${number}.${domain}"
          [[ ! -d ${servername}${number}.${domain} ]] && mkdir ${servername}${number}.${domain}
          rsync --rsync-path="sudo rsync" -e "ssh -i /tmp/sshkey -o StrictHostKeyChecking=no" -av \
            ${sshuser}@${servername}${number}.${domain}:/var/log/hoge.log \
            ${servername}${number}.${domain}/
          # ファイルの更新が発生した場合、HEADから別名として取り出す
          git diff --exit-code ||  git show HEAD:${servername}${number}.${domain}/hoge.log > ${servername}${number}.${domain}/hoge-$(date +%Y%m%d-%H%M).log
          ls -l ${servername}${number}.${domain}/*
        done
        ls -l
    - name: Commit files
      run: |
        git config --local user.email "morihaya@localhost"
        git config --local user.name "github-actions"
        git add .
        git commit -m "Add changes" -a
    - name: Push changes
      uses: ad-m/github-push-action@master
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        branch: ${{ github.ref }}        

今回は特定ファイルが対象でしたが、ディレクトリ配下まるごとを取得対象にし、その中で差分があったファイルのみ更新とかだともう少し複雑になりそうです。

*1:これをしないと基本的に 0 がリターンされる