もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

github actionで環境変数を動的に設定する

はじめに

こんばんは。

インフラ素人ながら頑張って構築を頑張っています。

今回はその際にちょっと学んだめちゃめちゃかんたんなtips

本題

リリースするとき、masterにマージされた段階で github action からデプロイをしたいなと思って、ある操作をしたかったんですが、その際にある値をgithub action の環境変数に代入したい欲求が出てきました。

そんなこと動的にできるのかなぁ?と思って調べてたんですが、ありました。

https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable

こんな感じで簡単にできました。

      - name: Set ENV For API_VERSION
        run: echo "API_VERSION=1.0.1" >> $GITHUB_ENV
        # ${{ env.API_VERSION }} で使える

終わりに

awsでいちから構築したのですが、今は結構やりやすくなってますね。

それでもけっこう大変ですが...

terraformとか使いたかったけど、そこまできちっとやる時間もなかったので、次やるときはトライしてみたいですね。

現場からは以上です。

flutterはじめてみた

はじめに

こんばんは。

今回はflutter触り始めてみました。

教材はこちら

とりあえず動かすところまで。

本題

インストール

自分はmacなので公式ページの言うとおりに落としました。

バージョンは以下

$ flutter --version
Flutter 3.3.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision eb6d86ee27 (9 weeks ago) • 2022-10-04 22:31:45 -0700
Engine • revision c08d7d5efc
Tools • Dart 2.18.2 • DevTools 2.15.0

事前にandroid studio等は入れてるので flutter doctorもこの通り。

$ flutter doctor
[✓] Flutter (Channel stable, 3.3.4, on macOS 13.0.1 22A400 darwin-arm, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] VS Code (version 1.72.2)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

• No issues found!

教材では cocoapods なるものが必要だと書いてたのでそれもインストールしました。

$ sudo gem install cocoapods

プロジェクト作成

android studio 起動後、flutterのパスを設定します。

projectの作成をします。

できた。

android simを動かしてみる。

ios simを動かしてみる。

これだけなのにめっちゃおもしれぇぇ!!!

終わりに

ただただ面白いの一言

webじゃない開発ってワクワクするなぁ。

教材見てもっとやってみて、終わったら次の教材も買ってみよう。

現場からは以上です。

grepで対象が見つからなかったときに終了させたくない

はじめに

こんにちは。 今日も簡単な備忘録です。

最近案件で複数のレポジトリ(10個)を扱うプロジェクトを触っています。

ただ、ジョインしたのはつい最近でまだまだ各レポジトリのことを知りません。

レポジトリのボリュームもそれぞれなかなかのものです。

なので「ここの文言〇〇から✗✗に変更してください」

と言われても探すのが大変。

プロジェクトごとに毎回git grepとか打つのはとても面倒。

なので Makefile作って make grep ○○ とかで全プロジェクト git grepしたいと思って作ったんですが、 grep は見つからなかったとき エラーステータスを返してきます。

これをなんとかエラーステータス受け取らず全プロジェクト再帰的に探し続けてほしい。

参考

qiita.com

本題

簡単なので、結果だけ載せときます。

STRING=string
BASE_DIR=/Users/kojirock/projects

grep:
        cd $(BASE_DIR)/repo_1 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_2 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_3 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_4 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_5 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_6 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_7 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_8 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_9 && git grep $(STRING) || exit $$(($$? - 1))
        cd $(BASE_DIR)/repo_10 && git grep $(STRING) || exit $$(($$? - 1))

exit $$(($$? - 1)) の部分で無視してくれています。

終わりに

レポジトリ多すぎ、、、

簡単ですが以上です。

playwrightをgithub actionで動かす

はじめに

こんにちは。

前回からplaywrightのかんたんなネタです。

kojirooooocks.hatenablog.com

今回はgithub actionで動かすのをやってみました。

本題

最小の構成はこんな感じ?

name: Test

on:
  pull_request:
    types: [opened]

jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '16'
      - uses: microsoft/playwright-github-action@v1

      - name: Get Node Cache Directory
        id: node-cache
        uses: actions/cache@v3
        with:
          path: ${{ github.workspace }}/node_modules
          key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
          restore-keys: ${{ runner.os }}-node-
      - name: Install Dependencies
        if: steps.node-cache.outputs.cache-hit != 'true'
        run: yarn install

      - name: Setup Playwright
        id: playwright-cache
        uses: actions/cache@v3
        with:
          path: /home/runner/.cache
          key: ${{ runner.os }}-playwright-cache-${{ hashFiles('**/playwright.config.ts') }}
          restore-keys: ${{ runner.os }}-playwright-cache-
      - name: Install Playwright
        if: steps.playwright-cache.outputs.cache-hit != 'true'
        run: |
          npm install && \
          npx playwright install --with-deps && \
          npx playwright install msedge

      - name: Execute Playwright
        run: npx playwright test

これでOKだと思います。

ただ、バックエンドも開発している場合、API先がないと playwrightでE2Eテストを実行することが出来ません。

僕がやってた案件でもバックエンドはlaravelで開発しており、そことの通信が必要です。

そのさい、僕がやった対応はCI上で ビルトインサーバを立ち上げてそことフロントを通信させるという感じで対応させました。

      - name: Clone For Backend
        run: |
          git clone https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/xxxx/xxxxx backend

      - name: Exec Serve
        run: |
          cd ${{ github.workspace }}/backend && php artisan serve &

これでサーバを立ち上げつつ フロント側は dotenv等を使って、通信先を立ち上げたビルトインサーバに向けて通信させて、テストを実行させることが出来ます。

終わりに

playwrightって劇作家って意味があるんですね。 

次はVRTも試してみます。

playwrightでE2Eテスト

はじめに

こんばんは。

最近 playwright というテストツールを使って E2Eテストを触っています。

設定はとてもかんたんだったので、備忘録として残しておきます。

playwright.dev

本番

install

playwrightのインストール

$ npm i -D @playwright/test

ブラウザのインストール

$ npx playwright install --with-deps ← chrome, safari, firefox
$ npx playwright install msedge        ← microsoft edge

テストコード

import { test, expect } from '@playwright/test'

test.describe('ユーザープロフィールページ', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto(`/user/1`)
  })

  test('名前が表示されている', async ({ page }) => {
    const name = await page.locator(`.profile-block .name`)
    await expect(name).toContainText('kojirock')
  })

  test('名前が変更できる', async ({ page }) => {
    const name = await page.locator(`.profile-block .name`)
    await page.fill(".name-form", 'kojirock-edit')
    await page.click('.save-button')
    await page.waitForTimeout(1000) // 雑に1秒まつ

    const name = await page.locator(`.profile-block .name`)
    await expect(name).toContainText('kojirock-edit')
  })
})

実行

$ playwright test

Running 8 tests using 1 worker
········

  8 passed (1m)
Done in 30.10s.

テストが2個なのになんで8回実行されているのかは 設定ファイルを見ればわかります。

設定ファイル(project部分のみ抜粋)

  projects: [
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome'],
      },
    },
    {
      name: 'webkit',
      use: {
        ...devices['Desktop Safari'],
      },
    },
    {
      name: 'Microsoft Edge',
      use: {
        channel: 'msedge',
      },
    },
    {
      name: 'firefox',
      use: {
        ...devices['Desktop Firefox'],
      },
    },
  ]

ブラウザ4種類でテストケース2個を実行しているから 4 * 2で8回実行されているという感じです。

設定ファイルは他にも細かに設定できます。

1. テスト実行時に同時にサーバを立ち上げたいとき

  webServer: {
    command: 'yarn dev', ← 任意のコマンド
    url: 'http://localhost:3300', ← 任意のURL
    reuseExistingServer: !process.env.CI,
  }

2. テスト実行時にログイン状態にしたい

  globalSetup: './global-setup',
  use: {
    storageState: './cache/storageState.json',
  },
import { chromium, FullConfig } from '@playwright/test'

async function globalSetup(config: FullConfig): Promise<void> {
  const browser = await chromium.launch()
  const page = await browser.newPage()

  await page.goto('http://localhost:3300/login')
  await page.fill("input[name='email']", 'example@example.com')
  await page.fill("input[name='password']", 'passwordpassword')
  await Promise.all([page.waitForNavigation(), page.click('.button')])

  await page.context().storageState({ path: '.cache/storageState.json' })
  await browser.close()
}

export default globalSetup

終わりに

なかなか楽しいです。

CIで実行するときや、VRT(Visual Regression Testing)というスナップショットテストもできるみたいなので、今後また試してみます。

現場からは以上です。

BigQueryの分割テーブル作成

はじめに

こんばんは。

案件でBigQueryを触ることがあり、分割テーブルを作ることがあったので、備忘録として残しておきます。

cloud.google.com

本題

時間分割テーブル

こんな感じのテーブルを作ります。

重要なのはテーブル名に YYYYMMDDのフォーマット で名前をつけています。

今回は 20221113 で付けています。

そして、次の日の 20221114 でテーブルを作成します。

するとUI上に下記のような選択できる箇所ができます。

そこで日付別のテーブルにアクセスできるようになります。

今回作ったテーブルは、クエリで一気にアクセスできます。

それぞれのテーブルに1件だけデータを入れます。

そしてSelect文を実行します。

ポイントはアスタリスクでアクセスさせるところくらいです。

パーティショニングテーブル

次はテーブルごとに分けるんではなくパーティショニング機能をつかった分割テーブルです。

テーブル作成時に下記のように設定します。

createdカラムを基準に1日ごとにパーティショニングします。

WHERE句の設定は「今回は」オンにしていますが、どちらでもいいです。

そして適当にデータを入れます。

そして、下記のようにSELECT文を使ってデータを引っ張ります。

WHERE句指定をONにしているので、今回のようなSQLになります。

終わりに

最近かんたんなものしか上げてませんが、一旦続いている自分を褒めたいなと。

誰も褒めないんだから自分は褒めてあげないとね。

えらい!

現場からは以上です。

LaravelでMailファサードでMailableを使わずにメール送信

はじめに

こんばんは。

またまたLaravelの知らなかったんかい!ネタです。

Mailファサードでメールを送る際にMailableを使わずに送る場合の対応です。

本題

普通にやる場合は以下。

Mail::to($user->email)->send(new TestMail($subject, $user));

Mailableを使わずに送信する場合は以下。

Mail::raw($body, static fn (Message $message) => $message->to($user->email)->subject($subject));

知らなかったです...

終わりに

Laravel結構使ってますが、知らないことがいっぱい出てくる...

現場からは以上です。