メインコンテンツまでスキップ

· 約3分
山田 哲也

こんにちは!山田です。

年度末も終わりますがみなさんはこの一年いかがでしたか?

自分自身を振り返ってみると、今年度は SRE チームを立ち上げや MVP 開発、初めてのメンバーマネジメントなど新しいことに挑戦することが多かった年になりました。

新しいことにチャレンジすることが好きなタイプの人間なので、とても充実した一年だったなと感じています。

ただ、反省点も多く残った一年でもありました。

例えば MVP 開発では成果物となるアウトプットは出せたものの、自社の MVP 開発のプロセスを標準化することまではできませんでしたし、メンバーのマネジメントに関しても、信頼関係の構築や適切なフィードバックなど先輩たちと比べて自分はまだまだできていないことがあるなと感じました。

他にもたくさんありますが、この一年で浮き彫りになった反省点を改善しながら来年度も突っ走って行けたらと思っています。

来年度も忙しい一年になりそうですが、人々が自己実現できる社会を作り上げるために、自分ができることを精一杯やっていきたいと思います。

本年度もお世話になりました。来年度もよろしくお願いいたします!

· 約13分
櫻田 亮太

はじめに

はじめまして。 新規事業開発チームのエンジニア櫻田です。
私たちのチームではGitHub ActionsとGitHub apiを活用して色んな作業を自動化しているので少しずつ紹介していきたいと思います。
今回はプルリクエスト開設時にレビュワーを自動設定する方法を紹介します。
初回なので構文の解説も行なっていきます!

実現すること

  • プルリクエスト開設時にレビュワーを自動設定する
  • チームメンバーが変わってもコードを変更せずに対応する

急いでいる人向け 完成ファイル

name: PR Reviewer Auto Assignment

on:
pull_request:
types: [opened, reopened, ready_for_review]

jobs:
reviewer-assign:
if: |
# お好きな条件分を設定ください
github.event.pull_request.base.ref != 'main' && startsWith(github.head_ref, 'feature')
runs-on: ubuntu-latest
env:
API_BASE_URL: "https://api.github.com"
ACCEPT_HEADER: "Accept: application/vnd.github+json"
VERSION_HEADER: "X-GitHub-Api-Version: 2022-11-28"
AUTH_HEADER: "Authorization: Bearer ${{ secrets.PULL_REQUEST_API_TOKEN }}"
ORG: "organization" # githubの組織名を設定してください
TEAM: "team" # レビュワーに設定したいチーム名を設定してください
steps:
- name: Get Members List
id: get-members-list
run: |
response=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/orgs/$ORG/teams/$TEAM/members)
members=$(echo $response | jq '[.[].login | select(. != "${{ github.actor }}")]')
echo ::set-output name=members::$members

- name: Set Reviewers
id: set-reviewers
run: |
reviewers=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers)
reviewr_count=$(echo $reviewers | jq '.users | length')

if [ $reviewr_count -eq 0 ]; then
curl -X POST \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers \
-d '{ "reviewers": ${{ steps.get-members-list.outputs.members }} }'
fi

ワークフローの設定

.github/workflows 配下にymlファイルを作成します。
まずはnameとonまで記載します。

name: PR Reviewer Auto Assignment

on:
pull_request:
types: [opened, reopened, ready_for_review]

公式ドキュメント

name

ワークフローの名前
リポジトリの[アクション]タブに表示される。
省略するとファイルのパスになる

on

ワークフロー実行のトリガーとなるイベントを定義する。
設定できるイベント一覧
今回はプルリクエストを開設した時に実行したいのでpull_requestを設定しています。
types のデフォルトは[ opened(PRオープン), synchronize(PRオープン後push), reopened(PR再オープン) ] ですが今回はdraftで開設後readyにした場合も実行したい&PRオープン後pushでは実行したくない為明示的に指定しています。




続いてjobsを設定していきます。

jobs:
reviewer-assign:
if: |
github.event.pull_request.base.ref != 'main' && startsWith(github.head_ref, 'feature')
runs-on: ubuntu-latest
env:
API_BASE_URL: "https://api.github.com"
ACCEPT_HEADER: "Accept: application/vnd.github+json"
VERSION_HEADER: "X-GitHub-Api-Version: 2022-11-28"
AUTH_HEADER: "Authorization: Bearer ${{ secrets.PULL_REQUEST_API_TOKEN }}"
ORG: "organization" # githubの組織名を設定してください
TEAM: "team" # レビュワーに設定したいチーム名を設定してください

jobs

ワークフローで実行される一連の処理
必ず一つは設定する必要があり複数作成することもできる。

jobs.id

ジョブの一意の識別子
今回はreviewer-assign とします。

jobs.id.name

ジョブに名前を分かりやすいつけることができる。
省略すると実行時にはidが表示されます。今回は省略しています。

jobs.id.if

条件文を使って、条件が満たされなければジョブを実行しないようにできる。
設定できる条件
今回はbaseブランチがmain以外かつheadブランチがfeatureから始まるブランチのみに限定する条件式を書いています。
startsWithなどを使用すれば部分一致なども実現することができます。
使用できる演算子やリテラル
また、ワークフローの中では様々な情報を取得することができます。(今回のbaseブランチ名やheadブランチ名など)頻繁に使用するので知っておくと便利です。
取得できるコンテキスト

jobs.id.runs-on

ジョブを実行するマシンの種類を定義できる。
今回はubuntu を指定しています。

jobs.id.env

ジョブ中のすべてのステップで使うことができる変数を設定できる。
今回は以下を設定しています。

  • API_BASE_URL
    • github apiのurl
  • ACCEPT_HEADER
  • VERSION_HEADER
  • AUTH_HEADER
    • 共通のヘッダー。${{ secrets.PULL_REQUEST_API_TOKEN }}の解説は後で行います
  • ORG
    • 所属している組織名
  • TEAM
    • レビュワーに設定したいチーム名。チームの設定の解説は後で行います。



続いてstepsを設定していきます。

    steps: 
- name: Get Members List
id: get-members-list
run: |
response=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/orgs/$ORG/teams/$TEAM/members)
members=$(echo $response | jq '[.[].login | select(. != "${{ github.actor }}")]')
echo ::set-output name=members::$members

- name: Set Reviewers
id: set-reviewers
run: |
reviewers=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers)
reviewr_count=$(echo $reviewers | jq '.users | length')

if [ $reviewr_count -eq 0 ]; then
curl -X POST \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers \
-d '{ "reviewers": ${{ steps.get-members-list.outputs.members }} }'
fi

jobs.id.steps

ジョブで実行される一連のタスクを定義できる。
複数設定することもできる。
様々な設定を行えます。公式ドキュメント

Get Members List

stepsの中のGet Members Listについて解説していきます。
run内の以下の部分でgithub apiを使用してチームメンバーを取得しています。
api ドキュメント

response=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/orgs/$ORG/teams/$TEAM/members)

そして以下の部分でjqを使用しresponseからメンバーのusernameを整形し取り出しています。その中でpr開設者は省いています。

members=$(echo $response | jq '[.[].login | select(. != "${{ github.actor }}")]')

最後に以下の部分でメンバーのusername配列をoutputしています。outputすることで次のステップで値を参照できるようになります。

echo ::set-output name=members::$members

Set Reviewers

最後になりますがstepsの中のSet Reviewersについて解説していきます。
以下の部分で現在のレビュワーに設定されている人数を取得しています。たまに手動で設定したい場合があるので既に設定されている場合は自動設定をスキップする為に取得しています。
api ドキュメント

reviewers=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers)
reviewr_count=$(echo $reviewers | jq '.users | length')

以下の部分でレビュワーを設定しています。上に書いたように一人以上レビュワーが設定済みならスキップするようにしています。

if [ $reviewr_count  -eq 0 ]; then
curl -X POST \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers \
-d '{ "reviewers": ${{ steps.get-members-list.outputs.members }} }'
fi

やっと完成しました!

name: PR Reviewer Auto Assignment

on:
pull_request:
types: [opened, reopened, ready_for_review]

jobs:
reviewer-assign:
if: |
# お好きな条件分を設定ください
github.event.pull_request.base.ref != 'main' && startsWith(github.head_ref, 'feature')
runs-on: ubuntu-latest
env:
API_BASE_URL: "https://api.github.com"
ACCEPT_HEADER: "Accept: application/vnd.github+json"
VERSION_HEADER: "X-GitHub-Api-Version: 2022-11-28"
AUTH_HEADER: "Authorization: Bearer ${{ secrets.PULL_REQUEST_API_TOKEN }}"
ORG: "organization" # githubの組織名を設定してください
TEAM: "team" # レビュワーに設定したいチーム名を設定してください
steps:
- name: Get Members List
id: get-members-list
run: |
response=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/orgs/$ORG/teams/$TEAM/members)
members=$(echo $response | jq '[.[].login | select(. != "${{ github.actor }}")]')
echo ::set-output name=members::$members

- name: Set Reviewers
id: set-reviewers
run: |
reviewers=$(curl -X GET \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers)
reviewr_count=$(echo $reviewers | jq '.users | length')

if [ $reviewr_count -eq 0 ]; then
curl -X POST \
-H "$ACCEPT_HEADER" \
-H "$VERSION_HEADER" \
-H "$AUTH_HEADER" \
$API_BASE_URL/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/requested_reviewers \
-d '{ "reviewers": ${{ steps.get-members-list.outputs.members }} }'
fi

Tokenの設定

github apiを使用する為にtokenを設定します。

Fine-grained personal access tokensを生成

Fine-grained personal access tokensとは詳細に権限を設定できるbeta版の機能にです。ですが今後はこちらがメインになる可能性が高い?ようです。
参考

手順1

以下へアクセスします。
https://github.com/settings/tokens?type=beta

手順2

このような画面が表示されるのでお好きなToken nameとExpirationとDescriptionを設定してください。
github

手順3

Github Actionsを実行するリポジトリを選択してください。 github

手順4

Permissionsを設定していきます。
Repository permissionsの中からPull requestsRead and writeに設定します。
Organization permissionsの中からMembersRead and writeに設定します。 Overviewが以下のような表示になっていればokです。 github Generate tokenを押下してください。
Tokenが生成されるので忘れないようにコピーしてください。

Actions secretsの設定

Github Actions内で使用できるように設定をしていきます。
以下へアクセスします。orgsは各自置き換えてください
https://github.com/{orgs}/mikiwame/settings/secrets/actions
New repository secretを押下すると以下画面になるのでお好きなnameを設定し先ほど生成したtokenをペーストしてください。 github これでactions内で${{ secrets.PULL_REQUEST_API_TOKEN }}のように使用できるようになりました!tokenの設定は以上です。

チームの設定

最後にチームを設定していきます。
公式ドキュメント
以下へアクセスします。orgsは各自置き換えてください
https://github.com/orgs/{orgs}/teams
New teamを押下すると以下のような画面になるのでお好きなnameとdesctiptionを設定しCreate teamを押下します。 github
最後にレビュワーに設定したいチームメンバーを追加すれば完了です!

最後に

長くなりましたがGitHub ActionsとGitHub apiでレビュワーを自動設定する方法は以上になります。
Github Actionsを活用すると様々なことを自動化できて便利なので是非活用していきましょう! (※使いすぎると無料枠超えてしまうので注意)
また機会があれば別の活用方法も紹介していきますのでお待ちください。

· 約6分
山田 哲也

みなさん、こんにちは! 山田です。

前回の記事で Figma を使ってボタンコンポーネントを作ってみました。
今回はそのデザインを元に React と Tailwind CSS で実装していきたいと思います。

開発環境の準備

今回開発環境に Nextjs を選びました。
Next.js はセットアップ時に Tailwind CSS のインストールを選択できるので、すぐに開発を始められます。

セットアップ時の質問は全てデフォルトで進めていきます。

> npx create-next-app@latest
Need to install the following packages:
create-next-app@14.0.4
Ok to proceed? (y) y
✔ What is your project named? … button-ui-example
✔ Would you like to use TypeScript? … No / Yes # Yesを選択
✔ Would you like to use ESLint? … No / Yes # Yesを選択
✔ Would you like to use Tailwind CSS? … No / Yes # Yesを選択
✔ Would you like to use `src/` directory? … No / Yes # Noを選択
✔ Would you like to use App Router? (recommended) … No / Yes # Yesを選択
✔ Would you like to customize the default import alias (@/*)? … No / Yes # Noを選択

Next.js のセットアップが完了したら、プロジェクトのディレクトリに移動しておきます。

UI の確認は Storybook で行うので、こちらもセットアップします。

npx storybook@latest init

セットアップが完了すると、自動的に Storybook が起動します。

Storybook

プリセットでいくつかコンポーネントが用意されていますが、不要なので削除しておきます。

rm -rf stories/*

Storybook の設定

次に Storybook の設定を行います。

簡単なボタンコンポーネントのファイルを作成し、以下の内容で保存します。

// app/components/Button.tsx
import { ReactNode, FC } from "react";

type Props = {
children: ReactNode;
};

export const Button: FC<Props> = ({ children }) => {
return <button>{children}</button>;
};

次に、このコンポーネントを Storybook で確認できるようにします。

// stories/Button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "../app/components/Button";

const meta = {
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
args: {
children: "ボタン",
},
};

Storybook を確認すると、ボタンコンポーネントが表示されます。

meta オブジェクトの tags に autodocs を指定することで、コンポーネントのドキュメントを自動生成することができます。
また、parameters に layout: "centered"を指定することで、コンポーネントを中央に表示することができるので覚えておくと便利です。

Storybook

最後に preview.js に globals.css を読み込ませます。
この時 globals.css に記載されている@tailwind xxxx以外の内容は不要なので削除しておきます。

// .storybook/preview.js
import type { Preview } from "@storybook/react";
import "../app/globals.css";

(省略)

これで Tailwind CSS によるスタイルが Storybook に反映されるようになりました。

ボタンコンポーネントの実装

Figma でデザインしたボタンコンポーネントにはいくつかのバリアントがありました。
ボタンコンポーネントに渡すプロパティの値によってバリアントを変化させるのが一般的かと思いますが、プロパティの数が多くなってくると、条件分岐を独自に実装するのはかなり面倒です。

そこで、「Class Variance Authority」というライブラリを使って、複数のバリアントを持つコンポーネントを簡単に実装できるようにします。

まずはライブラリをインストールします。

npm install class-variance-authority

次に、Button コンポーネントを以下のように修正します。

// app/components/Button.tsx
import { cva, type VariantProps } from "class-variance-authority";
import { ButtonHTMLAttributes, FC } from "react";

const button = cva("text-white rounded-md", {
variants: {
intent: {
primary: "bg-blue-500 hover:bg-blue-600",
secondary: "bg-pink-500 hover:bg-pink-600",
},
size: {
sm: "px-2 py-1 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
},
},
defaultVariants: {
intent: "primary",
size: "md",
},
});

export interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof button> {}

export const Button: FC<ButtonProps> = ({
className,
intent,
size,
children,
...props
}) => {
return (
<button className={button({ intent, size, className })} {...props}>
{children}
</button>
);
};

cva メソッド利用してバリアントの型を構築していきます。
第一引数に共通で適用されるクラス、第二引数にバリアントとそのバリアントに適用されるクラスを指定することができます。
また、defaultVariants を追加することで、デフォルトで表示されるバリアントを指定することができます。

(なんて便利なんだ...)

では、最後に Storybook でコンポーネントを確認してみましょう。

Storybook

うまく切り替えができているようですね 🎉

以上でボタンコンポーネントの実装は完了です。
複数のバリアントを持つコンポーネントを実装する際は、ぜひこのライブラリを使ってみてください。

それではまた次回!

· 約5分
山田 哲也

みなさん、こんにちは! 山田です。

今回は Figma でボタンコンポーネントを作ってみようと思います!

「あれ、お前 SRE エンジニアじゃなかった?」🤔 と思われるかもしれませんが、実は Figma や React などフロント周りの技術も好きで触っていたりします。

あと、社内で Figma 部というコミュニティを作って勉強会を開いたりもしてるんです。
こちらもどんな雰囲気でやっているのか今度記事にしてみようと思ってますのでお楽しみに!

さて、前置きが長くなっちゃいましたが、早速作っていきましょう!

ボタンコンポーネントの仕様

今回作成するボタンコンポーネントの仕様は以下の通りです。

種類サイズテキスト色背景色ホバー時の背景色角丸パディングフォントサイズテキストの高さ
プライマリsm#FFFFFF#3B82F6#2563EB6px横: 8px, 縦: 4px14px20px
プライマリmd#FFFFFF#3B82F6#2563EB6px横: 16px, 縦: 8px16px24px
プライマリlg#FFFFFF#3B82F6#2563EB6px横: 24px, 縦: 12px18px28px
セカンダリsm#FFFFFF#EC4899#DB27776px横: 8px, 縦: 4px14px20px
セカンダリmd#FFFFFF#EC4899#DB27776px横: 16px, 縦: 8px16px24px
セカンダリlg#FFFFFF#EC4899#DB27776px横: 24px, 縦: 12px18px28px

ボタンコンポーネントの作成

まずは sm サイズのプライマリボタンから作ってみましょう。

  1. テキストツールでボタンという内容のテキストを作成 → フレーム化。
  2. 背景を#3B82F6に設定して、角丸を 6px 、パディングを横: 8px, 縦: 4px に設定。
  3. テキストを選択して、テキスト色を#FFFFFF、フォントサイズを 14px 、テキストの高さを 20px に設定。

するとこんな感じのボタンができ上がります。

smサイズのプライマリボタン

これをコンポーネント化します。

コンポーネント化

これで sm サイズのプライマリボタンが作成できました!

他のサイズのボタンも作りたいので、Variant という機能を使って、サイズや背景色などのプロパティを変更できるようにします。

コンポーネントを選択した状態で右クリック ▶︎ Main Component ▶︎ Add Variant で Variant を追加することができます。

Variantの追加

Variant を使って、md と lg サイズのボタンを作成していきます。

そうしてできたのがこちら。プロパティ名を size にして、sm, md, lg という値を設定しています。

mdとlgのサイズのボタン

次にホバー時の Variant を作成して、マウスオーバーした時に背景色が変わるようにします。

  1. 現在の 3 つの Variant をコピペして、コピーした Variant の背景色を#2563EBに変更
  2. hover プロパティを追加して、true, false という値を設定。
  3. ホバー前のボタンの選択し、prototype からホバー時にコピーした Variant に遷移するように設定

設定が完了するとこんな感じになります。

ホバー時のVariant

プレビュー画面で動作を確認してみると...

ホバー時のVariant

お、いい感じです 😊

さて、あとはセカンダリボタンを作るだけですね。

  1. プライマリボタンのコンポーネントをコピーして、背景色を#EC4899に変更、ホバー時の背景色を#DB2777に変更。
  2. intent プロパティを追加して、primary, secondary という値を設定。

するとこんな感じに。

セカンダリボタン

これでボタンの見た目を自由に変更できるようになりました ✌️

ボタンのプロパティ

次回はこのボタンコンポーネントを React で実装してみたいと思います!お楽しみに〜

· 約3分
山田 哲也

みなさん、こんにちは!株式会社リーディングマークの山田です。

ついに、弊社のテックブログが開設されました!

これから、技術情報や社内の取り組みなどをこちらで共有していきますが、まずはなぜこのブログを始めたのか、その背景をお話ししたいと思います。

認知度向上とアウトプット文化の醸成

私たちのサービス「ミキワメ」は多くの方に利用され、導入企業もますます増えています。しかし、まだ十分に世間に知られていないと感じています。

たくさんの人たちに私たちのことを知ってもらうために、エンジニアとデザイナーが集まる組織として何ができるか考えました。 プロダクトを開発していく中で得られた知見や取り組みを共有することが認知度を高める一つの方法だと思い、このブログを始めることにしました。

目標は認知度を上げることだけではないです。メンバーが学んだことを外に発信する文化を作ることも大切だと考えています。 開発の過程で新しい技術を導入したり、難しい課題に取り組んだりすることは、個人の成長につながります。こういった経験は共有することで、他のメンバーや同じ問題に直面している人たちにも役立つ知識になると思っています。

最後に

個人的にも、チームリーダーとしてメンバーがチャレンジできる機会をたくさん作っていきたいという想いがあったので、その一つとしてこのブログを立ち上げることができて非常に嬉しく思います。

まだまだアウトプットする文化が根付いているとは言えない状況ですが、この活動をきっかけに変化が生まれたらと思っています。

暖かい目で見守っていただけると嬉しいです。これからどうぞよろしくお願いします!