TECH PLAY

ニフティ株式会社

ニフティ株式会社 の技術ブログ

500

こんにちは、新卒1年目の江口と西根です! 新人研修の一環としてニフティ2023年度新卒入社の10名がAWS JumpStart 2023 for NewGradsに参加しました! AWS JumpStart 2023 for NewGrads 設計編とは? 23卒の新卒1年目エンジニアを対象とした、AWS活用をリードする人材になるための入り口として提供されている実践的なAWS研修プログラムです。 AWSサービスについての学習のみならず、要件に沿った適切なアーキテクチャの検討・設計をする経験ができる内容になっています。 プログラムの到達目標 一般的なリファレンスアーキテクチャを理解できる AWSのコアサービスの概要や選定基準を理解できる AWSのアーキテクチャ図を作成する流れを知る 参加するまでにやること AWS JumpStart事前学習コンテンツ AWSに関する知識を少し身に着けておくために、以下の事前学習動画が用意されていました。 1. はじめてのアーキテクティング(60分) 2. AWS Solution Architect Associate資格勉強会(講義パート)(180分) ニフティでは内製の研修として先輩エンジニアが講義を行うエンジニア定例という制度があります。AWS JumpStart参加前にエンジニア定例でAWSの基礎について学んでおり、クラウドやAWSについて触れたことがあるという状態で参加しました。 内容 講義 事前学習動画の内容を、より初学者向けにかみ砕いた内容にして講義形式で学ぶ ハンズオン 実際にAWSサービスを使用して、アーキテクチャとリソースの構築方法について学ぶ アーキテクチャ検討 1. まずは課題に対して個人ワークとしてアーキテクチャを検討する 2. その後チームで最適なアーキテクチャを再度検討する 3. 要件が増えたらそれに対応するように、それぞれの要件にあったアーキテクチャを検討する 開催方法 オンライン ニフティは新入社員で同じ会議室で参加しましたが、他社だと在宅の方、執務室らしき場所で参加している方など様々でした! お菓子、飲み物の持ち込み自由とのことだったので、会議室にスターバックスのコーヒーのポットサービスを用意しました 参加人数 ニフティからは10名 5人1チーム×2 全体では400名以上 SIer、Web、ゲームなど様々な業種からの参加 使用したツール Slack アナウンスや質問、成果物の共有など Zoom 講義やブレイクアウトルームでのチーム別作業 Miro アーキテクチャ図の作成 AWSアカウント ハンズオン スケジュール 5/31(水) ~ 6/2(金)の3日間 ※6/3(day3)とありますが、正しくは6/2(day3)になります。 活動内容 1日目 1日目は、事前学習で学んできたことの振り返りをしつつ、ハンズオンを進めていくという流れで、Amazon ECS, AWS Fargate, Amazon RDSなどのサービスを使って、ToDoアプリを作るという内容でした。 スケーラブルハンズオンということで、システムに問題が発生した際の挙動の再現を行いました。Amazon ECSでは、2つ稼働しているタスクのうち1つを停止させ、自動で復旧していく様子を確認しました。そしてAmazon RDSでは、用意した2つのDBインスタンスのうちライターインスタンスに対してフェイルオーバーを行い、ライターとリーダーが自動で入れ替わる様子を確認しました。 これらのハンズオンを通じて、Design for Failureの考えに基づく可用性の高いシステムの魅力を体感することが出来たと思います。 2日目 2日目はAmazon EC2を使った簡単なハンズオンと、今回のイベントの目玉であるアーキテクティング課題に取り組みました。詳細について詳しくは説明できませんが、とあるサービスの可用性やスケーラビリティなどの観点を意識したアーキテクチャ設計を行うという課題で、私たちの班はこのような設計を考えました。 AWSに関することを調べていると必ず出てくるアーキテクチャ図ですが、実際に自分たちで作るとなるとかなり難しかったです。どこまでをパブリックサブネット配下にしたらいいだろうか、ロードバランサーはどこに置くのが正解か、といったような会話をしながら、手探りで形にしていきました。他班が作っているアーキテクチャ図の共有もあり、その設計が何を大事にしようとしているのかというのを、少しずつ読み取れるようになっていきました。 3日目 3日目はAWS Lambdaを使ったサーバーレスなサービスのハンズオンと、アーキテクティング課題の追加課題に取り組みました。 午前のハンズオンでは、AWS LambdaのトリガーをAmazon API Gatewayに設定しAmazon Translateを使って受け取った内容を翻訳させ、その内容をAmazon DynamoDBに流す、というようなサービスを作っていきました。 午後のアーキテクティング課題では、昨日作成したものにいくつかの機能追加を行っていきました。これらの機能に関しても詳細には語れませんが、私たちの班は最終的にこのような構成になりました。 AWS CodePipelineの流れや、Amazon ECSとAmazon ECRの繋がりなどを理解するのに苦労しました。同じサービスでも様々な形のアーキテクチャがあり、自分たちがやろうとしていることを実現させるにはどの構成が最適だろうかといった議論が白熱していました。 感想・学び 江口 ハンズオンやアーキテクティング課題を通じて、AWSのサービスに対する理解が深まっただけでなく、ユースケースに応じた最適な構成を作るためにはどのようなことを考慮するべきなのかといったような、実際の業務に活かせる視点を伸ばすことが出来たと思います。 また設計を進めていく中で様々なサービスが登場し、それらを理解するための情報を調べていく中で、それ以外の技術的なことにも触れることが出来ました。色々な分野の知識をつまんで、それをグループで話し合って噛み砕いていくといったようなことが出来て、非常に良い学びになりました。 西根 このプログラムに参加するまでは、AWSはニフティ内の研修で少し触ったことがあるだけで、アーキテクチャ図を見ても何が何だかわからない…という状態でした。3日間のプログラムを終えて、実際に自分でアーキテクチャを検討したり、他の人が書いたアーキテクチャ図を理解することができるようになりました。実際の業務でもアーキテクチャを検討したり、既存のサービスのアーキテクチャを理解するのに非常に役立ちました。 3日間という短い時間でしたが、難しくて怖いものだったAWSが、便利でおもしろいものに変わりました。ニフティには、社員が学習目的で利用できるAWSアカウントを提供する制度があり、個人のスキルアップに活用できるようになっています。こういった制度も利用しつつ、さらにAWSのサービスへの理解や活用を進めていければと思います! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
こんにちは、宮本です。最近は Astroフレームワーク を触っています。今まではReactのNext.jsしか触ってこなかったので、なかなか新鮮な気持ちです。……が、残念ながら本文はAstroは関係ないです。そのうちAstroの記事も書きたいですね。 はじめに さて、今回はGitHubのプルリク作成時のちょっと便利なGitHub Actionの紹介です。 プルリク作成時に地味にこんな悩みがありました。 「たまにプルリクを作成したマージ先のブランチで、masterとdevelopを間違える」 ……あまりに初歩的すぎて何も言葉が出ないかもしれませんが、それでも極々稀に、本当に稀にやらかします。今のところは流石に作った後で気づいて直したり、レビュー内で指摘が入って本当にやらかしたことはまだないですが、もしかするといずれやらかすかもしれません。CI/CDを完備していた場合には、そのままうっかり本番環境に……なんて目も当てられません。 というわけで、以下のような感じでプルリクを作成したら自動で主張激しくbotにコメントをしてもらっています。 GitHub Actionsを利用したbotのコメント投稿 実装 仕掛けているワークフローは以下の通りです。 name: Pull Request Comment on: pull_request: types: [opened] jobs: post_comment: runs-on: ubuntu-latest timeout-minutes: 5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout uses: actions/checkout@v3 - name: Check Base Branch name # 設定ファイルを取得し、コメント投稿対象のプルリクか判定 working-directory: .github/workflows/conf run: | BRANCH_ACTION=`cat pull_request_comment.json | jq '.["${{ github.base_ref }}"]' -r` if [ "$BRANCH_ACTION" != "null" ]; then echo "IS_COMMENT_POST=true" >> $GITHUB_ENV COMMENT_FILE_PATH=`echo $BRANCH_ACTION | jq '.["comment-file-path"]' -r` echo "COMMENT_FILE_PATH=$COMMENT_FILE_PATH" >> $GITHUB_ENV fi - name: Create comment # ghコマンドを利用してコメントを投稿 working-directory: .github/workflows/conf if: ${{ contains( env.IS_COMMENT_POST, 'true') }} env: URL: ${{ github.event.pull_request.html_url }} run: | gh pr comment -F ${{ env.COMMENT_FILE_PATH }} "${URL}" 設定ファイルとして、 .github/workflows/conf/pull_request_comment.json を定義しています。 { "master": { "comment-file-path": "comment_files/master.md" }, "develop": { "comment-file-path": "comment_files/develop.md" } } このjsonには、キーにプルリクエスト作成時にコメントを投稿したいheadブランチを指定しています。 そしてこのjsonファイルで指定したパス(.github/workflows/conf/comment_files/master.md)には、プルリク作成時に投稿したいコメントを書いたmdファイルを配置します。mdファイルにコメント内容を分離して、コメントの編集は気楽にできるようにしています。 # masterブランチへのマージ 本番環境へのリリースを行うPRです。 さいごに さて、プルリク作成時に、ブランチごとに任意のコメントを投稿するワークフローの紹介でした。 今回の例ではただブランチ名とリリース用のプルリクだと教えてくれるだけですが、投稿するコメント内容を編集すれば、開発時のプルリクには不要だけどリリース前に必要なチェック項目(リリース日の調整、GTMの設定変更の確認など)を自動で投稿するようなこともできます。逆もまた然り。プルリクテンプレートに記述しておくこともできますが、この項目はリリース時にしかいらないのに行が多くて邪魔だし毎回消すのも面倒、と思った場合は入れてみるのもありかもしれません。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは、会員システムグループの上原です。 先日、社内ISUCONを開催し、参加者から好評の声をいただくことができました。 当日どんな感じだったのか気になる方は以下のブログ記事をご覧ください。 https://engineering.nifty.co.jp/blog/21057 本イベントでは参加者にハンズオンで使用するサーバーを配布しました。参加者の人数とクォータ制限の観点から、数百台のサーバーをマルチアカウント・マルチリージョンで展開する必要があったのですが、手動でやるのは面倒だったので、可能な限り自動化してみました。 目標 数百台の同じ設定を入れ込んだサーバーを複数のAWSアカウント・複数のリージョンで簡単に立ち上げたい 従来の方法 同じ設定のサーバーを大量に立ち上げるためにまずはAMIを作成し、そのAMIを元にサーバーを起動する方法が思いつきます。 具体的には以下の手順になります。 UbuntuやAmazon LinuxなどのOSが入っているAMIからEC2インスタンスを立ち上げる sshやセッションマネージャなどでサーバにログインし、EC2インスタンスに必要なソフトウェア・設定を入れ込む EC2インスタンスをAMI化する 作成したカスタムAMIを使って複数アカウント・複数リージョンにサーバーを立てる 従来の方法の問題点とその解決策 従来の方法の問題は、AMIを作成するためだけにEC2インスタンスを起動しコマンドを打ちこみイメージを作成する必要があるところです。 ですが、手作業だと抜け漏れやミスが発生しやすく、何しろ面倒です。 そこで、AMIを自動的に作成する方法はないかどうか探してみたところ見つけたのが、Amazon EC2 Image Builderというサービスです! Amazon EC2 Image Builderとは? Amazon EC2 Image BuilderとはAWSのフルマネージドサービスで、AMIを自動で生成・検証・配布してくれるサービスです。 手順をYAMLファイルに書いておけばその手順をもとにAMIを作成・検証し、AMIを他リージョン・他アカウントにも共有・コピーして使えるようにしてくれます。 より詳しく知りたい方は以下のBlack Beltのpdfがわかりやすいので参考にしてください。 https://pages.awscloud.com/rs/112-TZM-766/images/20200825_BlackBelt_EC2imagebuilder.pdf ハンズオン 今回はお試しとしてslコマンドを入れたサーバーを5台同時に立ててみます 使用するOSはUbuntu 22.04 公式のAMI(ami-0d52744d6551d851e)を使用する AMIは自アカウントのap-northeast-1とus-east-1に展開します ちなみに、今回のterraformのコードをいじると別のアカウントにも展開できるようにすることもできます 作成したAMIを使ってEC2インスタンスをap-northeastに5台起動します 今回使うコードはこちらのレポジトリに配置しています。 https://github.com/Penpen7/ec2-image-builder-test Amazon EC2 Image Builderでパイプラインを作成する ここではAWS EC2 Image Builderをterraformを使って立ててみます レポジトリをcloneします git clone https://github.com/Penpen7/ec2-image-builder-test.git terraform実行に必要なS3バケットや認証情報を入れてください cd ec2-image-builder-test vim ec2/providers.tf vim image-builder/providers.tf terraform initで初期化、terraform applyでAWS環境に反映します cd image-builder terraform init terraform apply 実行が終わればEC2 Image Builderのパイプラインが作られた状態になります コンソールに入って設定を見てみる AWS コンソールにログインし、EC2 Image Builderでイメージパイプラインを表示します 以下のように作成したパイプラインが表示されるはずです パイプラインの中を見ると、パイプラインで出力したイメージ(AMI)・作成手順・配布設定・トリガーの設定を見ることができます レシピはどのようにAMIを構築するか指定します ベースとなるイメージをUbuntuに指定し、slコマンドをインストールする手順をコンポーネントに記述します ディストリビューション設定をクリックし、image-builder-testの中身を見ると以下の通りになっています ap-northeast-1とus-east-1に作成したAMIを展開するように設定されています パイプラインを実行し、AMIを作成する 手動でパイプラインを実行します。イメージパイプラインからimage-builder-testにチェックを入れてパイプラインを実行するをクリックします パイプラインの出力イメージに作成中のイメージが追加されます 出力イメージをクリックすると作成状況がわかります 作成中はEC2 Image BuilderがEC2を起動して作業をしています 完了になればAMIがap-northeast-1とus-east-1に作成されているはずです EC2を起動する terraformコードで今回作成したAMIを参照してEC2を5台起動できるようにしているので、ec2ディレクトリに移動しterraform applyで反映させます cd ../ec2 terraform init terraform apply EC2コンソールでサーバーが5台起動していることがわかります セッションマネージャでログインするとslコマンドがインストールされてることがわかります このようにAMIの作成手順や設定を記述しパイプラインを実行することで、AMIの作成・配布を自動化できます 設定を変更し、もう一度パイプラインを実行すればAMIを更新してくれます お片付け terraform destroyでEC2 Image BuilderとEC2を破棄します cd ../ec2 terraform destroy cd ../image-builder terraform destroy コンソール画面でバージニア北部と東京リージョンに作成されたAMIの登録解除を行い、スナップショットを削除します EC2 Image Builderのterraformのコード説明 もし気になる方向けにterraformのコードの中身を簡単に説明します Image Pipeline AMIを生成・配布するための自動実行されるパイプラインです CodePipelineのPipelineと同じやつです 1つのパイプラインから1つのAMIができます terraformの設定の中身はレシピとインフラ設定、配布設定のarnを指定しているだけです その他スケジュールで定期的にパイプラインを実行することもできます resource "aws_imagebuilder_image_pipeline" "this" { name = var.name # AMIを作成するためのレシピ image_recipe_arn = aws_imagebuilder_image_recipe.this.arn # AMIを作成するためのインフラ構成 infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.this.arn # AMIを作成した後の配布設定 distribution_configuration_arn = aws_imagebuilder_distribution_configuration.this.arn } https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_pipeline Recipes レシピはAMIをどのように作っていくか記述していきます ここでslをインストールするように指示する自作のコンポーネントを指定します resource "aws_imagebuilder_image_recipe" "this" { name = var.name # ベースとなるAMI parent_image = var.parent_image working_directory = "/tmp" version = "1.0.0" block_device_mapping { device_name = "/dev/sda1" no_device = false ebs { delete_on_termination = true encrypted = false volume_size = 16 volume_type = "gp2" } } # slをインストールするよう指示するコンポーネントのarnを指定 component { component_arn = aws_imagebuilder_component.this.arn } # SSMを配布するAMIから削除するかどうか # defaultだとtrueのはず systems_manager_agent { uninstall_after_build = false } } https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_image_recipe Components コンポーネントはAMIを作成するためにどのようなコマンドを実行するかを記述します resource "aws_imagebuilder_component" "this" { name = var.name platform = "Linux" version = "1.0.0" data = file( var.component_build_path ) } AWSが公式に出しているコンポーネントもあります 他のレシピからも参照できる再利用可能なコンポーネントです 中身はYAMLで記述します ビルドフェーズでaptを使ってslをインストールしますテストフェーズで正常動作するか検証することができ、今回はwhichを使ってslコマンドが存在するか検証します yamlに記述するnameにスペースがあるとエラーになるので注意してください 引数を受け取って処理させることも可能です(今回は引数を受け取りません) name: install_sl description: install sl schemaVersion: 1.0 phases: - name: build steps: - name: install_sl action: ExecuteBash inputs: commands: - sudo apt update - sudo apt install sl - name: test steps: - name: run_sl action: ExecuteBash inputs: commands: - which sl https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_component infrastructure Configuration Image BuilderがAMIを作成するために立ち上げるEC2の設定を記述します Image Builderが起動するEC2には以下のポリシーが必要です arn:aws:iam::aws:policy/EC2InstanceProfileForImageBuilder arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore SSM agentとSSMが疎通できる環境でないとImage Builderは使えないです セキュリティグループでインターネットへの外向きのアクセスを全開放にして、サブネットをパブリックに、起動時にパブリックIPが自動的につくように設定すると簡単に疎通できると思います resource "aws_imagebuilder_infrastructure_configuration" "this" { name = var.name # AMIを作成するためのEC2につけるIAMロール instance_profile_name = aws_iam_instance_profile.image_builder.name # AMIを作成するためのEC2のインスタンスタイプ instance_types = [var.instance_type] # AMIを作成するためのEC2につけるセキュリティグループ security_group_ids = [aws_security_group.this.id] # AMIを作成するためのEC2につけるサブネット subnet_id = aws_subnet.public.id # 異常終了時にインスタンスを削除するかどうか # パイプラインが失敗しデバッグしたい時はfalseにしてインスタンスを残すようにした方が良い terminate_instance_on_failure = false lifecycle { ignore_changes = [instance_metadata_options, logging] } } https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_infrastructure_configuration Distribution Configuration 作成したAMIをどのアカウント・どのリージョンに展開するか記述します resource "aws_imagebuilder_distribution_configuration" "sample" { name = var.name dynamic "distribution" { for_each = var.regions content { ami_distribution_configuration { name = "${var.name}{{imagebuilder:buildDate}}" ami_tags = { Name = "${var.name}" } # AMIのコピー先 target_account_ids = [ data.aws_caller_identity.current.account_id, ] # AMIの共有先(コピーせず、自アカウントのAMIを他アカウントから読めるようにする) launch_permission { user_ids = var.ami_share_ids } } # リージョン region = distribution.value } } } data "aws_caller_identity" "current" {} https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/imagebuilder_distribution_configuration 1リージョンごとに設定を入れます terraformだとdynamicという構文を使うとfor文で一気に設定を入れることができます ami_tagsでamiのtagを指定できます target_account_idにAMIをコピーして配置したいIDを指定します 他のAWSアカウントでも可能ですが、ここで指定したアカウントにクロスアカウントアクセス用のロールを作成する必要があります 逆にコピーせず共有したい時にはlaunch_permissionでIDを指定しましょう resource "aws_iam_role" "ec2_image_builder_distribution_cross_account_role" { name = "EC2ImageBuilderDistributionCrossAccountRole" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Sid = "" Principal = { AWS = "arn:aws:iam::${var.origin_aws_id}:root" } }, ] }) managed_policy_arns = [ "arn:aws:iam::aws:policy/Ec2ImageBuilderCrossAccountDistributionAccess", ] } https://docs.aws.amazon.com/imagebuilder/latest/userguide/cross-account-dist.html 最後に 今回は社内ISUCONで参加者にサーバーを配布するために使用したAmazon EC2 Image Builderをご紹介しました。 このサービスを使うと、AMIの作成を自動化することができ非常に便利です。 もしよろしければ使ってみてください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
みなさんこんにちは、ニフティ株式会社新卒 1 年目の中井です。突然ですが皆さん、業務の新しいバッチ処理を Rust で書いてみようと思ったことはありませんか?ありますよね。私も入社して半年の 9 月に達成しました!!わーい! 実は元々ニフティ社内で Rust が使われていたわけではありません。それなのになぜ入社してこんなにすぐ Rust を導入することができたのかというと、他にも Rust を導入しようと企んでいる先輩がすでに オープン社内 Rust 勉強会 を開いてくださっていたからなんです。そこで学んだ知識も活かして、今回はぜひ Rust を書きたいと主張して書かせていただきました! 以前は 退勤を失敗して対策を練ったり していましたが、今回は今風な技術を使ってみたというお話です。やらかしてばかりでもないのです。 Rust とは Rust という名前だけは聞いたことがある方もいらっしゃるのではないでしょうか。自分も数々の ストリーマーがギャンブルに興じている動画 を見たことがあります。いえ、そちらではなくて、プログラミング言語の Rust です。 公式サイトが https://www.rust-lang.org/ にあるのですが、簡単にいうと、「速い」「安全な」そして「使いやすい」言語です。言語の習得がちょ〜〜っとだけ難しいという話もありますが、エコシステムとしては本当に完成度が高いです。 Cargo というパッケージマネージャー兼ビルダーの存在 Rust Analyzer という随一のエディタ支援機能 Rust の良さは無限に語れてしまうのですが、本題ではないので、とりあえず最強の言語があるということだけ覚えてください。 お題: 画像を S3 から S3 へ移動させる Lambda をつくれ ニフティには AWS の練習用アカウントを用意して月 100 ドルまで使わせてくれる実弾演習場という制度があります。ということで、Rust でどうやって Lambda を書いていくのか、小さいアプリケーションを使って実際にデプロイしてみましょう。 …待ってください、たしかにこれだけだとただの暇を持て余した人の遊びみたいな感じですが、この Lambda 部分で画像を加工してみたり、文章を要約してみたり、いろいろ夢がひろがるじゃないですか! Cargo Lambda と Terraform を組み合わせる 作るものは決まったとして、問題はデプロイ方法です。 Lambda を zip ファイルに固めて terraform apply する、という方法なら比較的簡単です。ただ自動化が大変ですし、そもそも毎回 Terraform を実行するのは怖いです。何かのタイミングでインフラを壊しそうで…。 かといって、世の中には SAM とか Serverless Framework とかいうものもあるとは聞きますが、難しそうなので何も理解していません。 今回は Cargo Lambda を採用します。これは Cargo という Rust のパッケージマネージャーを拡張して、Lambda 用のコマンドを多数増やしてくれるツールです。 https://www.cargo-lambda.info/ これを使うと、デプロイまでの流れはこんな感じ。簡単なので私でも使えます。 cargo lambda new でプロジェクトを作成 cargo lambda build で Lambda 用のバイナリをビルド cargo lambda deploy で AWS 上にデプロイ 本当に Lambda 単体がただ動けばよいだけならこれだけで OK です。最低限の IAM ロールを含め、全てをデプロイしてくれます。 ただし今回は、インフラ側は Terraform で管理した上で、うまく Cargo Lambda と組み合わせることにしました。というのも、どうせ S3 が必要になるし、また S3 へのアクセス権など IAM ロール自体の調整もあるからです。すなわち…. Terraform で S3 や IAM ロール、ダミーの仮の Lambda まで作成してしまう Cargo Lambda でホンモノの Lambda を上書きする これで、Lambda を含めたインフラ全体を Terraform で管理しつつ、日常的な Lambda のデプロイには Terraform を利用しない形にできます。 …ちなみに私は AWS 初心者なので、他にもっといい方法がある気がしています。よければ教えてください。やっぱり SAM 勉強したほうが良いですか? 実際につくってみる 何はともあれ、実際に作ってみましょう。ちなみに完成品はこちらにおいておきます。 https://github.com/statiolake/aws-terraform-rust Terraform のメインファイルを書く まずはお決まりのやつです。AWS を使いたいので aws プロバイダを指定します。 provider "aws" { region = "ap-northeast-1" shared_credentials_files = ["~/.aws/credentials"] profile = "{your-aws-profile}" default_tags { tags = { managed_by = "terraform" } } } main.tf S3 のバケットやイベントとの連携を用意する 次に S3 関連の設定を書いてしまいます。今回は入力・出力用に 2 つのバケットを用意します。また、Put イベントで Lambda を呼び出すように設定します。 {your-prefix-} には、他の人とぶつからなさそうな、自分だけの好きな文字列を入れてください。S3 の名前は全世界で重複しない必要があるらしいので、私が作った S3 バケットと衝突してエラーになってしまいます。 # 入力側 resource "aws_s3_bucket" "input" { # 名前は適当なプレフィックスを付けるなど、必ず変更すること bucket = "{your-prefix-}example-aws-terraform-rust-input" } # 出力側 resource "aws_s3_bucket" "output" { # 名前は適当なプレフィックスを付けるなど、必ず変更すること bucket = "{your-prefix-}example-aws-terraform-rust-output" } # 入力側の S3 の Put イベントで Lambda を呼び出す resource "aws_s3_bucket_notification" "put_notification" { bucket = aws_s3_bucket.input.id lambda_function { lambda_function_arn = aws_lambda_function.lambda.arn events = ["s3:ObjectCreated:Put"] } } resource "aws_lambda_permission" "allow_s3_invoke" { statement_id = "AllowS3Invoke" action = "lambda:InvokeFunction" function_name = aws_lambda_function.lambda.function_name principal = "s3.amazonaws.com" source_arn = aws_s3_bucket.input.arn } s3.tf ダミーの Lambda を Terraform で作成する さて、ここからがトリックの 1 つ目、ダミーの Lambda の作成です。 後で本物の Lambda をデプロイすることになるので、いろいろなオプションは本物の Lambda が動く基準に合わせて作ります。 runtime : provided.al2 handler : bootstrap また、後で Cargo Lambda によりコード部分を上書きするわけですが、それを後でまたダミーに書き戻されてしまっては困ります。これを避けるため、 source_code_hash を ignore_changes に指定して、その差分を無視してもらうようにします。 resource "aws_lambda_function" "lambda" { function_name = "example-aws-terraform-rust" handler = "bootstrap" role = aws_iam_role.lambda_role.arn runtime = "provided.al2" filename = data.archive_file.lambda.output_path source_code_hash = data.archive_file.lambda.output_base64sha256 environment { variables = { AWS_OUTPUT_BUCKET_NAME = aws_s3_bucket.output.bucket } } lifecycle { ignore_changes = [source_code_hash] } } # ここではダミーを指定する data "archive_file" "lambda" { type = "zip" source_dir = "dummy_lambda" output_path = "archive/dummy_lambda.zip" } lambda.tf そして、Terraform ではダミーの Lambda をデプロイします。 環境に provided.al2 と bootstrap を指定しているので、その環境で動くようにダミーの方から合わせてあげる必要があります。要するにダミーには Python とかは使えないわけですが、まあダミーなので中身はなんでも大丈夫です。シェルスクリプトで bootstrap というファイルを作って、簡単にエラー終了するようにしておきました。 #!/bin/sh echo "WARNING: This is not an actual lambda!" echo "This is a placeholder during terraform setup." echo "Please replace this lambda to the actual function by cargo-lambda." exit 1 インフラをデプロイする terraform apply をして、AWS 環境を確認すると… S3 バケットあります。 ダミーの Lambda もあります。いい感じです! この時点でイベントのセットアップなども完了しているので、バケットにファイルを入れると CloudWatch Logs にエラーが流れるはずです。 うまく動いていそうですね! cargo lambda new で Lambda を作成 次はお待ちかね、Rust での Lambda の作成です。前述の通り、Cargo Lambda というツールを使います。 このツール、インストール方法がしっかり整備してあって、簡単に使い始めることができます。 ※ 情報が古くなっている可能性もあるので、 公式サイト も合わせてご確認ください。 macOS / Linux をお使いの方であれば、homebrew から簡単に入ります。 brew tap cargo-lambda/cargo-lambda brew install cargo-lambda Windows の方は scoop から入れられるらしいですね。 scoop bucket add cargo-lambda <https://github.com/cargo-lambda/scoop-cargo-lambda> scoop install cargo-lambda/cargo-lambda PC 環境を汚したくない方に向けては Docker イメージも提供されていますので、 公式サイト を確認してみてください。 インストールが終われば、次は早速プロジェクトを作成していきましょう。 今回は actual_lambda という名前でプロジェクトを作っていきます。おもむろに cargo lambda new actual_lambda としてみてください。すると… $ cargo lambda new actual_lambda > Is this function an HTTP function? No > AWS Event type that this function receives s3::S3Event 画面上のいろいろと質問に答えるだけでプロジェクトが完成、最低限のボイラープレートも全部書いてくれています。なんと便利な。 ここから先は、もう普通の Rust プログラミングです。 Rust プロジェクトに AWS SDK を追加する 今回は、Lambda 内から S3 にアクセスしたいんでした。プロジェクトに AWS SDK を追加します。ちなみに Rust の AWS SDK はサービスごとに分離されています。 使いたいサービスを探し、必要なライブラリを追加してください。 https://awslabs.github.io/aws-sdk-rust/ 今回は S3 なので、ターミナルにこんな感じで打ち込めば完了です。 cargo add aws-config cargo add aws-sdk-s3 何気なく aws-config も追加していますが、これは設定の読み込みのためのライブラリで、どのサービスを使うにしても必要なものっぽいです。 本体を Rust で書く こんどこそ処理を編集して、実際に S3 から S3 へ画像が移動するようにしてみましょう。Rust は src/main.rs ファイルからスタートなので、このファイルを書き換えていくことになります。 S3 から S3 へ移動させるサンプルコードを下に掲載します。 あっ、コピペしたくなりますよね。わかります。全然コピペでもいいんですけど…。 ただ、もう少しだけ時間があるなら、せっかくなので手で写経してみませんか。Rust の最強支援機能、Rust Analyzer をぜひ使ってみてください。補完から型ヒントまで、とても気持ち良く書けるんです。 VSCode をお使いの方なら、Rust Analyzer は拡張機能から簡単にインストールできます。 use std::env; use aws_config::load_from_env; use aws_lambda_events::event::s3::S3Event; use aws_sdk_s3::Client; use lambda_runtime::{run, service_fn, Error, LambdaEvent}; /// This is the main body for the function. /// Write your code inside it. /// There are some code example in the following URLs: /// - <https://github.com/awslabs/aws-lambda-rust-runtime/tree/main/examples> /// - <https://github.com/aws-samples/serverless-rust-demo/> async fn function_handler(event: LambdaEvent<S3Event>) -> Result<(), Error> { let LambdaEvent { payload, .. } = event; for record in payload.records { let bucket = record.s3.bucket.name.unwrap(); let key = record.s3.object.key.unwrap(); let config = load_from_env().await; let client = Client::new(&config); let output_bucket_name = env::var("AWS_OUTPUT_BUCKET_NAME") .expect("failed to get output bucket name from env var"); let object = client.get_object().bucket(&bucket).key(&key).send().await?; client .put_object() .bucket(&output_bucket_name) .key(&key) .body(object.body) .send() .await?; client .delete_object() .bucket(&bucket) .key(&key) .send() .await?; } Ok(()) } #[tokio::main] async fn main() -> Result<(), Error> { tracing_subscriber::fmt() .with_max_level(tracing::Level::INFO) // disable printing the name of the module in every log line. .with_target(false) // disabling time is handy because CloudWatch will add the ingestion time. .without_time() .init(); run(service_fn(function_handler)).await } actual_lambda/src/main.rs 入力側 S3 からオブジェクトを取得して、出力側 S3 に書き込んで、入力側 S3 のオブジェクトを削除する、というコードになっています。 Cargo Lambda でビルドする 出来上がったら、次はビルドをしましょう。 cargo lambda build --release --target x86_64-unknown-linux-gnu --target では、Lambda のタイプを指定します。 x86_64-unknown-linux-gnu : いわゆる普通の Lambda です。 aarch64-unknown-linux-gnu : ちょっと安い ARM (Graviton) タイプの Lambda です。 こんなスイッチ一つ切り替えるだけでいい感じにネイティブバイナリが作れる、これも Rust のいいところだと思っています。 Cargo Lambda でデプロイする ビルドがうまくいけば、デプロイです。 cargo lambda deploy --profile {your-aws-profile} --binary-name actual_lambda example-aws-terraform-rust 最後の引数 example-aws-terraform-rust は Lambda の名前です。忘れないでくださいね!これを忘れてしまうと全く新しく actual_lambda という名前の Lambda が生成されてしまいます。そうすると IAM ロールなども自動で作成されてしまってゴミが増えるのでご注意を… (n 敗)。 ちなみにサンプルリポジトリの方には Docker を使うバージョンのコマンドを Makefile に書いてあるので、参考になるかもしれません。 さて、デプロイが完了したらもう動くようになっているはずです! お楽しみの動作確認 入力用の S3 バケットに適当なファイルをアップロードすると…. 出力用の S3 バケットに出力されました!わーい。 まとめ 今回は AWS 上に Terraform でインフラを作成し、その中の Lambda を Rust で実装していきました。 Terraform ではダミーの Lambda を作成し、Cargo Lambda を使ってデプロイすることで、インフラとコードのデプロイを分離することに成功しました。また、Rust 側のほとんどの作業は Cargo や Cargo Lambda が面倒を見てくれることも紹介しました。 どうでしょう。Rust で Lambda と聞くと難しそうな印象もあったかもしれませんが、思ったより簡単そうだなと思ってもらえたら幸いです。 ぜひ一度 Rust で書いてみてください。そして Rust を広めていきましょう!! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も常時受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
ニフティ株式会社では、2023年9月29日(金)に開催される「SRE NEXT 2023 IN TOKYO」にGOLDスポンサーとして協賛いたします。 また、ブースを出展いたしますので、ご来場をお待ちしております。 SRE NEXT 2023 IN TOKYO SRE NEXT 2023 IN TOKYO イベント概要 開催日:2023年9月29日 (金) 10:00 〜 18:00 (懇親会 19:00 – 21:00) オフライン会場: 九段会館テラス オンライン会場: YouTube ※詳細は公式サイトをご覧ください https://sre-next.dev/2023/ 前回(SRE NEXT 2022)ではスポンサーセッションに参加しました 当社、浅見( @rubihiko ) の発表資料はこちらです。 ブースについて ニフティブースでは、現場のエンジニアがローテーションして常駐しております。 是非お越しください! We are hiring! ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
N1!のPorductivity Engineerとして生産性向上に関わる活動をしている石川です。 ニフティでは2023年6月からPoCとしてGitHub Copilot for Businessを限定的に導入していましたが、2023年9月に正式導入することになりました。現在では希望する方は誰でも利用することができます。 本日はGitHub Copilotの利用状況と効果について話したいと思います。 GitHub Copilotの利用状況 Acceptance Rates 言語別 利用者へのアンケート結果 工数削減効果 改善されたことと変わらなかったこと 生産性は向上したか(実感ベース) 費用対効果について 最後に 宣伝 GitHub Copilotの利用状況 Acceptance Rates 20人ほどでPoCを行っていたときのCopilotの提案採用率となります。 導入初期は好奇心からか採用率は50%を超えてましたが時間が経って30%前後に集約しました。Copilot利用者の 提案採用率は約30% なので近い値にはなっていますね。 利用者がまだ少ないのと人や言語差の影響が大きく採用率が乱高下してますが、利用者がもっと増えてきたらまた変わってくるかと思います。 言語別 大抵のプログラミング言語では30%超えてますね。Javaに関しては60%超えているので、GitHubのブログにあった通りなので本当に精度がいいのだと思います。 記述内容が短文だったり自由度の高い言語ほど採用率が低い傾向にあるように見えます。 こちらもまだ母数が少なく使う人の採用スタイルに率は大きく依存するので、もっと普及するとどう変化するか追っていきたいと思います。 利用者へのアンケート結果 PoC時に取ったアンケートの結果も一部共有いたします。 工数削減効果 アンケートで取った以下の質問を散布図にしたものがこちらになります。 1日あたりCopilotの効果でどのくらい時間が節約できたか 10分未満, 20分, 30分, 1時間, 2時間, 3時間, 4時間以上 1日の仕事の中でコーディングに費やす時間 20%未満,40%,60%,80%以上 集計すると平均して 1日38分 工数削減できていて、コーディングに費やす時間が 23.73% 減ったと実感しているという結果となりました。 GitHub Copilot を使用するとタスクを 55% 早く完了できる らしいので、それに比べるとまだまだですが十分効果は出ていると思います。 改善されたことと変わらなかったこと Copilot利用前後での変化を聞いた結果がこちらになります。 主にコーディング速度とそれに伴うタスク完了までの速度に大きく影響を与えていますね。 書くのがめんどうな型定義やテストまわりで活躍していて精神面でもよい効果が出ているようです。 都度ドキュメントを調べたりする機会が減ることで集中力が高まる効果もあるかと思ったのですが、そこについては変わらないという結果となりました。 生産性は向上したか(実感ベース) 8割以上 が生産性向上を実感している。 費用対効果について GitHub Copilot for Business は $19/user/month と決して安くはないですが、コーディングに費やす時間23%減という効果は出ているため、下振れたとしてもある程度の時間コーディングしているのであれば十分元は取れるものだと思います。 ただ今回の結果が一時的なものである可能性もあるため、効果については他の要素との相関も見つつ継続して計測していくつもりです。 最後に PoC開始時点では試すだけ試してみるかというスタンスでしたが、実際に使ってみるとプログラミング体験がガラッと変わりました。ちょうどいいところにちょうどいいものを提案してくれる体験、悩んでいると合っているかは置いておいて候補を出してくれるという体験はとても心地よいものでした。 ChatGPTで十分と考えている方も一度GitHub Copilotを触ってみることをおすすめします。 公式がCodespacesでCopilotを体験できる環境を用意してくれているので無料で触れます。 Take GitHub Copilot on a test-flight. – GitHub Resources GitHub Copilot ChatもPublic betaになりましたし、Copilotは利活用できる余地は多く残されていて、まだまだ生産性を上げてくれるのではないかと考えています。 宣伝 来週 9月26日(火) 12:00〜13:00にYouTube LiveにてGitHub CopilotをテーマにしたLTを行います。こちらでは今回書いていない利用者視点の話もあります。 興味がある方がいましたら以下のconnpassにご登録をお願いいたします。 GitHub Copilotの導入や活用 – connpass We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
こんにちは。会員システムグループの渡邊です。 皆さんはGitHubのリリースノートを使っていますか? リリースノートはGitHubリポジトリでプロダクトのリリースを管理し、ユーザーに新しいバージョンや変更点を提供するための機能です。 私が所属するチームではスクラムを採用しており、細かいリリースが1スプリントで多く行わるので、このリリースノートをスプリントで行ったリリースの実績として活用しています。 ただし、私たちは複数のリポジトリにまたがった開発を行っており、各リポジトリごとに手動でリリースノートを作成するのは非常に時間がかかる作業でした。そこで、リリースノートの自動化を検討し、以下のような条件を付け加えて実装を行いました。 2週間で行われるスプリントの最終日に今回のスプリントで行ったリリース内容がリリースノートに公開される どのスプリントかをわかりやすくするために、リリースノートのタグとタイトルにスプリント名(sprint1,sprint2)をつける 前提 今回は Release Drafter というGitHub Actionsのワークフローを使って実装していきます。 簡単にRelease Drafterの説明をします。 Release DrafterはPRを出したタイミングで変更したファイルの種類を検出して、自動的にラベルを付与します。 そのラベルをもとにmasterにpushなどの特定のトリガーを基準にリリースノートのドラフトを自動で作成するワークフローです。 加えて、GitHub公式が提供している github-script というGitHub Actionを使うことで、ワークフロー内でJavaScriptを実行し、ワークフローをカスタマイズしています。 実装 configファイル作成 .github/release-drafter.yml というファイルを作成します。 これはconfigファイルになっていて、リリースノートに記載する内容の制御やPR時に付与するラベルの条件を設定することができます。 ラベルを付与する条件は、ディレクトリや特定の拡張子を指定することが可能です。 categories: - title: ' Release' labels: - 'release' - title: ' Features' labels: - 'feature' - 'enhancement' - title: ' Bug Fixes' labels: - 'fix' - 'bugfix' - 'bug' - title: ' Maintenance' label: 'chore' - title: ' Refactoring' label: 'refactor' - title: ' Documentation' label: 'documentation' - title: ' Dependency update' label: 'dependencies' change-template: '- $TITLE @$AUTHOR (#$NUMBER)' change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. template: | $CHANGES autolabeler: - label: feature branch: - '/^feat(ure)?[/-].+/' - label: bug branch: - '/^fix[/-].+/' - label: chore branch: - '/^chore[/-].+/' - label: refactor branch: - '/(refactor|refactoring)[/-].+/' - label: documentation branch: - '/doc(umentation)[/-].+/' files: - '*.md' - label: release branch: - '/release[/-].+/' - label: enhancement branch: - '/(enhancement|improve)[/-].+/' - label: nextjs files: - 'src/**/*' - 'package.json' - label: github files: - '.github/**/*' 実行ワークフロー作成 次に.github/workflow/release-drafter.yml というワークフローを作成します。 name: Release Drafter on: schedule: - cron: '0 8 * * 2' #JST 17:00 on Tuesday pull_request: types: [opened, reopened, synchronize] jobs: update_release_draft: runs-on: ubuntu-latest timeout-minutes: 15 steps: - name: checkout uses: actions/checkout@v3 - name: Get latest release tag id: get_tag uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const repo = context.repo; const { data } = await github.rest.repos.getLatestRelease({ owner: repo.owner, repo: repo.repo, }); let tag = data.tag_name; console.log(data) const regex = /sprint(\d+)/; const match = tag.match(regex); if (match) { const sprintNumber = parseInt(match[1]); tag = sprintNumber + 1; } return tag; - name: Check release date id: check_date uses: actions/github-script@v6 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const repo = context.repo; const { data } = await github.rest.repos.getLatestRelease({ owner: repo.owner, repo: repo.repo, }); const releaseDate = new Date(data.published_at); const currentDate = new Date(); const diffTime = Math.abs(currentDate - releaseDate); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); return diffDays >= 10; # リリース日から10日以上経過している場合はリリースを作成する - name: create release if: ${{ steps.check_date.outputs.result == 'true' }} uses: release-drafter/release-drafter@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: publish: true name: 'sprint${{ steps.get_tag.outputs.result }}' tag: 'sprint${{ steps.get_tag.outputs.result }}' # リリース日から2週間以上前の場合はリリースを作成しない - name: add label if: ${{ steps.check_date.outputs.result == 'false' }} uses: release-drafter/release-drafter@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: disable-releaser: true 処理内容について簡単に説明します。 スケジュールおよびプルリクエストトリガーの設定 on セクションで、このワークフローが2つのトリガーで起動するように設定されています。 schedule トリガーは、毎週火曜日のJST 17:00(UTC 8:00)に設定されています。 pull_request トリガーは、プルリクエストが開かれた、再オープンされた、または同期された場合に発生します。 最新リリースタグの取得 get_tag ステップは、github-scriptを使用して最新のリリースノートのタグを取得します。 タグ名は sprintX の形式で、X は現在のスプリント番号です。 取得したタグを次のスプリントのタグに更新します。 リリース日のチェック check_date ステップは、最新のリリースノートの公開日と現在の日付を比較して、その間の日数を計算します。 日数が10日以上経過している場合、後続のリリースノートを作成するための if 条件が満たされます。 リリースノートを作成した日付を基準に動くため、2週間スプリントなので14日と設定すると1日でもリリースノート作成がずれると正しく動かないので、余裕を持って10日と設定しています。 リリースノートの作成 create release ステップは、 release-drafter アクションを使用して、日数が10日以上経過している場合はリリースノートを作成し、公開します。 タグとリリースノート名は、前のステップで取得した次のスプリント番号を使用します。 ラベルの追加 add label ステップは、日数が10日未満の場合に実行され、最新のリリースノートを自動で作成することを制御します。 リリースノートの作成タイミングを変更する場合 scheduleのcronを実行したい日付に変更 GitHub ActionsのタイムゾーンはUTCなので、日本時間に合わせるため9時間プラスします。 check_date ステップの diffDays >= 10 を変更 1週間のスプリントならcronだけでいいので、 check_date と add label ステップを削除します。 動作確認 今回は火曜日の17:00に実行するようにcronを設定しています。 GItHubとslackを連携しているので、17時頃に実行者が github-actions[bot] でリリースノートとタグが自動的に作成されました。 まとめ 今回はRelase Drafterをチームの開発手法に合わせてカスタマイズしました。 github-scriptを組み合わせることによって、JavaScriptでGitHub APIが叩けるようになり、求めていた動作を実現することができました。 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
始めに こんにちは、ニフティ新卒1年目の高田と村山です。 現在はジョブローテーション期間中で、いろいろな部署を回っています。 現在は、情報システムチームに配属されており、社内向けシステムの開発や運用を行っています。その業務の一環として便利ツールを2人で作成したので、それについて話していきたいと思います!SlackBotを作ってAWSにデプロイしたい人はぜひ読んでみてください! 背景 ニフティでは出勤時に勤務場所と仕事内容をSlackに投稿し、Slackのステータスも勤務地に応じたものに変えるというルールがあります。また、退勤時にもSlackへの報告が必要です。これは、リモートワークによるハイブリッドな働き方により、社員全員がオフィスにいるわけではないので、どこで働いているか、今日のタスクはどうなっているかなどを共有する必要があるためです。 従来は、すべて手動で行わなければならなかったため、他の出勤時のタスクと合わせて行わなければならず、忘れがちだったり、作業の負担になっていたりしました。 そこで、我々新人はそんな状況を打破すべく、先に挙げたSlackへの投稿・ステータス変更を自動化するシステムである、「出退勤楽楽くん」の制作に取り組みました。 出退勤楽楽くんとは? 出退勤楽楽くんとは、以下のように、Slackの出退勤報告用チャンネルに報告用スレッドが毎日自動的に投稿され、 メッセージ内にあるボタンを押すだけでSlackへの出勤報告やSlackのステータス変更が行われるというシステムです。 これにより、先に挙げた報告やステータス変更をボタン一つで完了できるため、楽に出退勤時のタスクをこなすことができます。 また、社内で使用されているスケジュール管理システムのIDとPWを事前に登録しておくことで、 報告内容に当日の業務内容を自動的に含めることができます。 システム構成 アーキテクチャ 本システムは、対象がニフティの社員(数百人程度)&1日に一人当たり2回利用されることを想定した比較的小規模なツールです。ですので構成は、呼び出しが少ない場合に低コストで運用できるサーバレスとし、AWS Lambda上にデプロイを行いました。詳細なアーキテクチャは以下の通りです↓ デプロイにはServerless Frameworkを用いました。設定ファイルは以下の通りです(一部省略)↓ service: attendance-slack frameworkVersion: '3' provider: name: aws runtime: python3.10 region: ap-northeast-1 iam: role: statements: - Effect: Allow Action: - lambda:InvokeFunction - lambda:InvokeAsync Resource: "*" - Effect: Allow # ParameterStore関連 Action: - ssm:PutParameter - ssm:GetParameter Resource: "*" - Effect: Allow Action: - kms:Decrypt Resource: "*" - Effect: Allow # DynamoDB関連 Action: - dynamodb:UpdateItem - dynamodb:GetItem - dynamodb:DeleteItem Resource: "*" environment: TZ: Asia/Tokyo SERVERLESS_STAGE: ${opt:stage, 'dev'} package: patterns: - "!**" - "function/**" functions: app: # メイン関数 handler: function.slack_bolt_function.lambda_handler name: attendance-slack-${sls:stage} url: true maximumEventAge: 21600 maximumRetryAttempts: 0 post_attendance_message: # 出勤報告用メッセージ投稿関数 handler: function.post_attendance_message.lambda_handler name: attendance-slack-post-attendance-message-${sls:stage} maximumEventAge: 21600 maximumRetryAttempts: 0 events: - schedule: cron(0 22 ? * 1-5 *) # 平日朝7時(JST)に実行 post_leaving_message: # 退勤報告用メッセージ投稿関数 handler: function.post_leaving_message.lambda_handler name: attendance-slack-post-leaving-message-${sls:stage} maximumEventAge: 21600 maximumRetryAttempts: 0 events: - schedule: cron(50 2 ? * 2-6 *) # 平日朝11時50分(JST)に実行 manage_channels: # チャンネル管理用関数 handler: function.manage_channels.lambda_handler name: manage-channels-${sls:stage} url: true maximumEventAge: 21600 maximumRetryAttempts: 0 # 外部パッケージをLambda上で動かすプラグイン plugins: - serverless-python-requirements custom: pythonRequirements: zip: true slim: true useDownloadCache: false useStaticCache: false # DynamoDBのインスタンス作成 resources: Resources: ondemanddb: Type: 'AWS::DynamoDB::Table' Properties: TableName: user AttributeDefinitions: - AttributeName: slack_id AttributeType: S KeySchema: - AttributeName: slack_id KeyType: HASH # オンデマンドキャパシティモード BillingMode: PAY_PER_REQUEST Bolt for Pythonによるアプリ制作 出退勤楽楽くんはSlackの公式ライブラリである Bolt for Python を使って作られています。これによってユーザからのアクション(スラッシュコマンドやボタンクリックなど)と処理の紐づけを非常に簡単に実装できます。 メッセージ等アプリ内コンポーネントの成形には Block Kit Builder を使用しています。たとえば↑のメッセージブロックのうち、ワンクリック版は以下のようなソースでできています。 blocks = [ { "type": "section", "text": { "type": "mrkdwn", "text": ":syukkin: *おはようございます!*:syukkin:\nボタンを押して出勤報告しましょう!", }, }, {"type": "divider"}, {"type": "section", "text": {"type": "mrkdwn", "text": "*ワンクリック版*"}}, { "type": "actions", "block_id": "place_oneclick_block", "elements": [ { "type": "button", "text": {"type": "plain_text", "emoji": true, "text": "新宿17F"}, "value": "新宿17F", "action_id": "button_17f", }, { "type": "button", "text": {"type": "plain_text", "emoji": true, "text": "新宿18F"}, "value": "新宿18F", "action_id": "button_18f", }, { "type": "button", "text": {"type": "plain_text", "emoji": true, "text": "在宅"}, "value": "在宅", "action_id": "button_home", }, { "type": "button", "text": {"type": "plain_text", "emoji": true, "text": "横浜"}, "value": "横浜", "action_id": "button_yokohama", }, { "type": "button", "text": {"type": "plain_text", "emoji": true, "text": "その他"}, "value": "その他", "action_id": "button_others", }, ], }, {"type": "divider"}, # 詳細版も同様に... ] これをSlackの chat.postMessage APIにblocksとして渡してAPIを叩くことで指定のチャンネルに送ります。ボタンのアクションは以下のようにblock_idとaction_idを指定して受取り、値はaction[“value”]で受け取ります。また、bodyにリクエスト情報が一通り入っています。 def attendance_oneclick_button_clicked( action: dict, body: dict, client: WebClient ) -> None: # ユーザid取得 user_id = body["user"]["id"] schedule = "some schedule" # ここでスケジュール管理ツールから予定をとってくる schedule = "\n--やること--\n" + schedule msg = f"{body['user']['username']}が勤務を開始しました。\n場所: " + action["value"] + schedule # 出勤報告メッセージ投稿 client.chat_postMessage( channel=body["channel"]["id"], text=msg, thread_ts=body["message"]["ts"], username="出退勤楽楽くん", ) # ステータス変更 place = action["value"] if place == "新宿17F": status_text = "オフィスワーク中 17F" status_emoji = ":17f:" elif place == "新宿18F": status_text = "オフィスワーク中 18F" status_emoji = ":18f:" elif place == "在宅": status_text = "リモートワーク中" status_emoji = ":working-from-home:" elif place == "横浜": status_text = "オフィスワーク中 横浜" status_emoji = ":yokohama:" else: status_text = None status_emoji = None # 勤務場所が「その他」のとき以外は変更する if status_text and status_emoji: user_id = body["user"]["id"] client.users_profile_set( token=ps.get_parameter("SLACK_USER_TOKEN"), user=user_id, profile={ "status_text": status_text, "status_emoji": status_emoji, "status_expiration": 0, }, ) # Lazy Listener設定 app.action({"block_id": "place_oneclick_block", "action_id": re.compile("button_.+")})( ack=just_ack, lazy=[attendance_oneclick_button_clicked] ) Boltで構築したSlackアプリをLambda上で動かす場合はLazy Listenerの設定が必要です。これについては先輩が すでに記事を書いているので見てみてください 。なお、 users.profile.set APIを用いて他人のステータス変更を行う場合、その人の メンバー種別 より上位のメンバーが発行したユーザトークンが必要です。今回はプライマリーオーナー権限で払い出してもらっています。 使ってみてくれた人の感想 ニフティではSlackに個人の分報チャンネルを作成してつぶやきを発信する文化があります。そこに投稿されていた感想の一部をご紹介します。 好評ですね! 工夫した点 AWSにデプロイするにあたり、比較的安い構成を採用 規模を考慮した完全サーバレス構成 社内ツールであり、ユーザが多くて数百人程度なので、サーバは立てずにリクエストベースのLambda+DynamoDB構成にしました。 シークレットの管理をParameter Storeで行う ローテーション機能を要さないことなどから、Secrets ManagerでなくParameter Storeを使うことでコストを抑えました。 API GatewayでなくLambda Function URLsを利用 HTTPエンドポイントとしてLambda Function URLsを直接利用するようにし、認証等はSlack SDKに任せています。 開発効率を上げるためにIaCを組んだ 本プロジェクトでは、AWSを採用しているため、コンソールを使用した手動でのデプロイには時間や工数がかかります。 そのため、上記のようにServerless Frameworkを使用して、デプロイできるようにしました。また、Serverless FrameworkはTerraform等と比べて簡単に設定を書けるので、新人エンジニアがIaCを始めるきっかけとしては、とても良いのではないでしょうか。 苦労した点 AWS, SlackAPI初心者2人での設計・開発 私たちはどちらもAWSやSlackAPIを用いた開発の経験がなかったため、仕様の検討には時間がかかりました。 AWSでいえば、DBの選択や設計、シークレットの管理方法、その他必要なサービスの取捨選択などに苦労しました。わからない点は社内分報チャンネルでぼやいていると先輩方が教えてくれたり、あとはChatGPTに相談したりして決めていきました。GPT4は最強でした。 (余談ですが、弊社では上記のようにSlackでいつでも質問可能なAIが在中しています。詳細は こちら ) またSlackAPIでは、Tokenの権限、Tier(1分当たりの呼び出し可能回数)やインタラクションの実装方法(ショートカットやスラッシュコマンドなど)の検討に悩まされました。 ジョブローテによる開発期間の制約 9月下旬には他の部署へ移るため、開発はもちろん、企画や仕様の決定、諸々の調整などを含めて3か月で開発しなくてはなりませんでした。また先述の通り私たちには技術を調べる時間も必要だったため、うまくことを進めていくのが大変でしたが、先輩に頼ったり、IaCによる効率化などにより何とか乗り切りました。 まとめ 今回は出退勤時のタスクを自動化するSlackアプリを作成しました。 今回、ふたりともAWSやBoltを使用した開発は初めてでしたが、3か月という短い期間の中でひとつ形にできたのでよかったです。先ほど紹介した感想を含め、チームの方々がみんな楽になったと言ってくれてうれしかったです。 もしみなさんにも、こういったSlackでの毎日のタスクがあるなら、私たちのように自動化を考えてみてはいかがでしょうか。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに 基幹システムグループの湊谷です。 普段は主にニフティのお客様の情報を管理するシステムの開発・運用を行っています。 「◯◯の情報を取得するにはどのAPIを利用すれば良いか?」といったシステム目線のもの、「◯◯といった属性を持つお客様にメールを送りたいため、IDリストを抽出してほしい」といった企画・営業目線のもの、日々様々な問い合わせが来ます。 今年でこのシステムに携わり始めて4年目になりますが、まだまだ把握しきれていないことも多く、問い合わせを対応する時は都度調べることが欠かせません。 その中でも、「過去の類似の問い合わせを見つけ出し、その時の調査内容・回答から今回の回答のヒントを得る」ことが多いです。 しかし、問い合わせはSlackチャンネルで受け付けているのですが、数多い問い合わせの中検索して必要な情報を探し出すのは大変・・・ しかも、調査段階で右往左往してる・・・ どこかにナレッジとしてちゃんとまとめておきたい!でも手動でやりたくない!  ということで今回は、「Slackチャンネルで問い合わせが投稿されると、Notion DBに新規ページを作成し、その作成されたページがSlackチャンネルに投稿される」ことを実現します。 ちなみに、過去に Slack ワークフロー+Boltで依頼・受付の調整をスッキリさせよう! という記事も書いているので、よろしければご覧ください。 Slack BoltとZapierを使ってNotionと連携させる やることは大きく分けて以下の五つです。 Slack Bolt for Javascriptを使ってbotを作成する 問い合わせを受け付けるSlackワークフローを作成する Notionにデータベースを用意する ZapierでNotion データベースに新規ページを作成し、Slackに通知するワークフローを作成する botの実装を行う それでは一つずつ見ていきます。 Slack Bolt for Javascriptを使ってbotを作成する 早速上記の過去の記事と同様になりますが、まず最初に、Boltを使用して、チャンネルに投稿されたメッセージを受け取り応答するbotを用意しておきます。 Slackアプリの構築の仕方については、 slack apiのドキュメント や Bolt 入門ガイド に詳細があるため省略します。 問い合わせを受け付けるSlackワークフローを作成する 私たちのシステムでは、問い合わせを受けつけるチャンネル(以下、 QAチャンネル )と、システム担当者が調査・やり取りを行うチャンネル(以下、 内部用チャンネル )の二つを用意し、QAチャンネルにSlackワークフローを作成して問い合わせを受け付けています。 ※今回は、2023年6月に提供開始された 新バージョンのSlack ワークフロー ではなく、レガシー版のワークフローを用いて作成しました。 まずはワークフローを開始したチャンネル=QAチャンネルに、問い合わせの内容をそのまま投稿します。 今回の実装とは関係ありませんが、QAチャンネルに投稿されたメッセージのスレッドに、以下の様な返信を行い、システム担当者が確実に気付けるようにしています。 次に、内部用チャンネルにも投稿を行います。 基本的には問い合わせを受け付けたチャンネルに投稿した内容と同じものを投稿しますが、大切なのは一番下の部分です。 先ほど作成したSlack botへのメンションと、「Notion DBにコピーしてください」という文言を一緒に投稿しています。 後ほどbotの実装を行う際に、「アプリにメンションが飛んだ時、更に特定の文字を含んでいる」場合をトリガーとする実装を行うため、忘れずにつけておきます。 Notionにデータベースを用意する Notionに問い合わせをまとめるページを作成します。 データベースを選択してページを新規作成します。 使いやすいようにプロパティを編集しましょう。今回は「進捗」「Slackスレッド」「担当者」の三つのプロパティを持たせています。 ZapierでNotion データベースに新規ページを作成し、Slackに通知するワークフローを作成する Zapierとは、複数のアプリやサービスを連携してワークフローを作成することができるサービスです。 今回は「NotionDBにページを作成し、そのページをSlackに通知する」ワークフローを作成します。 ※Notionにページを作成しSlackに通知させる、といった複数のステップを組み合わせたワークフローの作成や、今回トリガーに使っているものは有料プランのみ可能です。 まず、「何をきっかけにして作成したワークフローを発火させるか」となるトリガーを選択します。 「Webhooks by Zapier」を選び、Eventは「Catch Hook」を選択します。 「Trigger」は特に指定せず次に進みます。 「Test」に進むと「Your webhook URL」が表示されます。 このURLを呼び出すと叩くと、現在作成しているワークフローを発火させることができます。 パラメータに、「Notion DBに作成するページのタイトル(title)・本文(detail)」と、「投稿するSlackのスレッド(ts)」の情報を持たせます。指定する値はここでは適当で問題ありません。 https://hooks.zapier.com/hooks/catch/XXXXXXX/XXXXXX/?title=test&detail=korehatestdesu&ts=hogehoge このURLを一度ブラウザで叩いてみましょう。 “status”: “success” となればOKです。 次にNotion DBにページを作成します。Add a stepでNotionを選択し、Eventには「Create Database Item」を指定します。 Accountでは使用する自身のアカウントを連携させます。 連携させる際に、先ほど作成したページを指定しておきます。 Actionで、作成するNotion DBのページの設定をしていきます。 Database  作成したページを指定 名前  ページのタイトル。パラメータに指定したtitleを選択 slackスレッド  <内部用チャンネルのURL>+/p+パラメータに指定したtsを選択 Content  ページの本文。お好みの文章と、パラメータに指定したdetailを選択 Content Format  マークダウン式で書く場合にはMarkdownを選択 これでテストをすると、先ほど作成したNotionページに新しくページが追加されていることを確認できました。 最後に、Slackに通知をする設定をします。 Zapierで設定を行う前に、Notionのページを通知させたいチャンネルに適当に投稿します。 今回は架空の問い合わせを投稿してみました。 リンクをコピーし、URLからメッセージのをタイムスタンプを確認します。 https://hoge.slack.com/archives/XXXXXXX/p1234567890123456 URLの一番最後、pの後の16桁の数字で、右から6つ目と7つ目の間にピリオドを打ったものがタイムスタンプです。 1234567890.123456 Add a stepでSlackを選択し、Eventには「Send Channel Message」を指定します。 Accountでは使用する自身のアカウントを連携させます。 Actionで、Slackにメッセージを送る際の設定をしていきます。他の項目はお好みで設定しましょう。 Channel 内部用チャンネルを選択 Message Text お好みの文章と作成したページのURLを選択 Thread パラメータに指定したtsを選択 これでテストすると、Slackに作成されたNotionのページ付きで投稿がされました! これでZapierのワークフローは完成なので、Publishしておきます。 Slack botの実装を行う やっていることは、「slackアプリに対してメンションが飛ばされた時、特定の文章を含んでいたら、ZapierのURLを叩く」です。 アプリの起動部分などは省略しています。 // Slackに投稿された文章の中から問い合わせの本文を抽出する const getElementsBetween = ( array: Array<string>, startFlag: string, endFlag: string, ): string[] => { let outputArray: Array<string> = []; let startCollecting = false; for (let i = 0; i < array.length; i++) { // startFlgが見つかったら、startCollectingをtrueにする // startFlgの要素は配列に入れないためcontinue if (array[i] === startFlag) { startCollecting = true; continue; } // endFlgが見つかったら、startCollectingをfalseにする if (array[i] === endFlag) { startCollecting = false; } // startFlgとendFlgの間の要素を配列に入れる if (startCollecting) { outputArray.push(array[i]); } } return outputArray; }; // Zapier URLを呼び出す const createQaDb = (title: string, detail: string, ts: string) => { const uri = `https://hooks.zapier.com/hooks/catch/XXXXXX/XXXXXX/?title=${title}&detail=${detail}&ts=${ts}`; const encoded = encodeURI(uri); return fetch(encoded) .then((res) => { console.log('問い合わせDB作成'); }) .catch((error) => { console.error(`問い合わせDB作成失敗:${error}`); }); }; // botの処理 // アプリにメンションが飛んだ時に実行 app.event('app_mention', async ({ body }) => {  // もし投稿の中に「Notion DBにコピーしてください」という文言が含まれていたら if (body['event']['text'].includes('Notion DBにコピーしてください')) {   // bodyのメッセージから必要な情報を取得 const text = body['event']['text']; const textArray = text.split('\n'); const title = textArray[3]; const detailArray = getElementsBetween( textArray, '■問い合わせ詳細', '■いつまでに回答が必要ですか?', ); const detail = detailArray.join('\n');   // 本文、タイトル、タイムスタンプ情報を持たせてZapier URLを呼び出す createQaDb(title, detail, body['event']['ts']); } }); これで チャンネルに問い合わせが投稿されると 内部用チャンネルに内容が転送され その情報を基にNotion DBに新しくページが作成され そのページが内部用チャンネルのスレッドに通知される ようになりました! 最後に 以前の記事に引き続き 、Slackワークフロー+Boltを使って作成したbotアプリを組み合わせた活用例を紹介しました。 今回はZapierを活用することで、SlackだけではなくNotionとの連携も簡単に行うことができました。 SlackワークフローもZapierも、完全にノーコードで様々な作業を自動化させることが可能です。 特にSlackワークフローは 2023年6月に新バージョンの提供が開始されたそうです。 まだ新バージョンの方は触れていないため、何か業務に活用できないか模索していきたいと思います。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
基幹システムグループ N1! オートメーションスペシャリストの南川です。 今回は、 Docker イメージがビルドできるか定期的にチェックし、失敗したら Slack に通知する GitHub Actions のワークフローを紹介します。 背景 Docker のベースイメージの OS や使用しているパッケージのバージョンアップにより、何もしていないのに Docker イメージのビルドが失敗するようになることがあるかと思います。また、ビルドに失敗した場合、その原因が機能追加や修正によるものなのか、自分の環境によるものなのか分からないといった問題もあります。 こうした背景から、以下のような GitHub Actions のワークフローを作成することにしました。 定期的 (平日 8:30) に Docker イメージのビルドが成功するかチェックする。 ビルドに失敗したら Slack のチャンネルにアラートを通知する。 もし、 Slack チャンネルにアラートが通知されていたら、担当者はワークフローの実行ログを確認し、 GitHub で Issue を作成して対応します。 このワークフローにより、ベースイメージやパッケージの更新による Docker イメージのビルド失敗の検知が迅速化されるほか、ビルド失敗の原因の調査にも役立つことが期待されます。 手順 前提として、今回は Docker Compose を使っているリポジトリに対して実装していきます。 (1) Slack Incoming Webhook を作成 以下のページを参考に Slack Incoming Webhook を作成します。 https://api.slack.com/messaging/webhooks 作成したら Webhook URL ( https://hooks.slack.com/services/T.../B.../... ) をメモします。 (2) Webhook URL をリポジトリシークレットに追加 GitHub のリポジトリのページを開きます。 リポジトリのメニューから「 Settings 」を選択します。 左メニューから「 Secrets and variables > Actions 」を選択します。 「 New repository secret 」ボタンを押す。 以下のように入力し、「 Add secret 」ボタンを押す。 Name : ALERT_SLACK_WEBHOOK_URL Secret : 手順 (1) でメモした Webhook URL 参考 : https://docs.github.com/ja/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository (3) GitHub Actions ワークフローファイルを作成 ブランチを切り、 .github/workflows/ 配下に以下のファイル ( check_docker_build.yml ) を作成します。 name: check docker build on: schedule: - cron: '30 23 * * 0,1,2,3,4' workflow_dispatch: jobs: check_build: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - name: define run url run: echo "ACTION_URL=https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" >> $GITHUB_ENV - name: docker-compose build run: docker-compose build - name: slack notification if: ${{ failure() }} uses: slackapi/slack-github-action@v1.24.0 with: payload: | { "text": ":github: Dockerイメージのビルド失敗 :docker:\n失敗の原因を調査し、必要に応じてhotfixのIssueを作成し、対応してください。", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": ":github: Dockerイメージのビルド失敗 :docker:" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "失敗の原因を調査し、必要に応じてhotfixのIssueを作成し、対応してください。" } }, { "type": "section", "text": { "type": "mrkdwn", "text": "${{ env.ACTION_URL }}" } } ] } env: SLACK_WEBHOOK_URL: ${{ secrets.ALERT_SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK この時のディレクトリ構成 (関係のあるファイルのみ) は以下のようになります。 |-- .github | `-- workflows | `-- check_docker_build.yml |-- Dockerfile `-- docker-compose.yml 解説 name: check docker build リポジトリの Actions タブで表示されるワークフロー名を指定しています。 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#name ここで指定した名前は、 Actions タブの実行履歴で表示されます。 on: schedule: - cron: '30 23 * * 0,1,2,3,4' workflow_dispatch: このワークフローを実行するトリガー (条件) をここで指定しています。 schedule https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule cron 式で指定した日時に実行するようにする。 UTC で指定する必要があるので注意。 (例) 月曜日 (曜日 = 1) 8:30 を指定する場合は、 UTC に変換すると、日曜日 (曜日 = 0) 23:30 になるので、「 30 23 * * 0 」となります。 今回は平日 (月曜~金曜) の 8:30 に実行するようにしています。 workflow_dispatch https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch ワークフローを手動で実行できるようにします。 https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow 今回はワークフローの動作確認のために使います。 - name: checkout uses: actions/checkout@v3 リポジトリにチェックアウトし、ワークフローでアクセスできるようにします。 https://github.com/marketplace/actions/checkout - name: define run url run: echo "ACTION_URL=https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" >> $GITHUB_ENV 環境変数 ACTION_URL を定義し、環境ファイル $GITHUB_ENV に書き込みます。 ワークフローの実行結果のURLを環境変数 ACTION_URL の値として定義しています。 ${GITHUB_REPOSITORY} , ${GITHUB_RUN_ID} はそれぞれ GitHub が設定済みの既定の環境変数。 ${GITHUB_REPOSITORY} : 所有者およびリポジトリ名。 ${GITHUB_RUN_ID} : リポジトリ内の各ワークフローの実行に割り振られたユニークな番号。 https://docs.github.com/ja/actions/learn-github-actions/variables#default-environment-variables $GITHUB_ENV はワークフローコマンドから変数を設定するファイルへのランナー上のパス。 https://docs.github.com/ja/actions/learn-github-actions/variables#default-environment-variables これによって、後続のステップで環境変数 ACTION_URL の値を使うことができます。 https://docs.github.com/ja/actions/using-workflows/workflow-commands-for-github-actions#environment-files - name: docker-compose build run: docker-compose build Docker イメージをビルドするコマンド。 必要に応じて 「–build-arg」 でオプションを指定します。 - name: slack notification if: ${{ failure() }} 前のステップ (Docker イメージのビルド)が失敗した場合に、このステップを実行(Slackにメッセージを投稿)するようにします。 https://docs.github.com/ja/actions/learn-github-actions/expressions#failure uses: slackapi/slack-github-action@v1.24.0 with: payload: | { "text": ":github: Dockerイメージのビルド失敗 :docker:\\n失敗の原因を調査し、必要に応じてhotfixのIssueを作成し、対応してください。", "blocks": [ ... { "type": "section", "text": { "type": "mrkdwn", "text": "${{ env.ACTION_URL }}" } } ] } env: SLACK_WEBHOOK_URL: ${{ secrets.ALERT_SLACK_WEBHOOK_URL }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK Slack Incoming Webhook を用いて、メッセージを Slack チャンネルに投稿します。 https://github.com/marketplace/actions/slack-send payload には Slack チャンネルに投稿するメッセージを記載します。 text https://api.slack.com/methods/chat.postMessage#arg_text blocks が指定されていない場合、チャンネルに投稿されるメッセージ。 blocks が指定されている場合、 Slack で通知されるときのメッセージ。 block https://api.slack.com/methods/chat.postMessage#arg_blocks JSON で記述された構造化されたメッセージ。 詳しくはこちらを参照してください。 https://api.slack.com/messaging/composing/layouts 先ほど定義した環境変数 ACTION_URL の値を使っています。 「 "text": "${{ env.ACTION_URL }}" 」 https://docs.github.com/ja/actions/learn-github-actions/variables#using-contexts-to-access-variable-values https://docs.github.com/ja/actions/learn-github-actions/contexts#env-context 環境変数 SLACK_WEBHOOK_URL に、手順(2)で設定したリポジトリシークレットの値を指定しています。 https://docs.github.com/ja/actions/security-guides/encrypted-secrets#using-encrypted-secrets-in-a-workflow (4) 動作確認 ビルドを失敗するように Dockerfile を書き換えてコミットし、 push します。 リポジトリの「Settings」タブを選択します。 Default branch をこのワークフローを開発しているブランチに切り替えます。 リポジトリの 「Actions」 タブを選択します。 左メニューから 「check docker build」 を選択します。 参考 : https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow#running-a-workflow 「Run workflow」 のプルダウンを開き、現在開発しているブランチを指定して、緑色の 「Run workflow」 ボタンを押します しばらくすると、チャンネルにビルド失敗のメッセージが投稿されます。 Botのアイコンがお気に入りです。 https://www.irasutoya.com/2016/11/blog-post_684.html 平日の8:30頃にビルド失敗通知に投稿されれば OK。 ビルド失敗するようにしたコミットを revert します。 平日の8:30頃にビルド失敗通知に投稿されなければ OK。 Actionsタブから実行されている(Dockerイメージのビルド成功している)ことを確認します。 土日の8:30頃にワークフローが実行されていなければOK。 Actionsタブから実行されていないことを確認します。 おわりに 今回は、GitHub Actions で定期的に Docker イメージをビルドできるかチェックし、ビルドできない場合は Slack にメッセージを投稿するワークフローについて説明しました。 Docker イメージのビルドチェック以外にも色々応用できるので、是非活用してみてください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは。ニフティ株式会社の宮永です。4月に新卒で入社しました。現在はインフラシステムグループ ISPオペレーションサブチームに所属しています。 7月9日に電気通信主任技術者試験(伝送交換)を受験し、合格しました。受験者が少ないためかネットに体験談を載せている人も少なく、今後受ける人の役に立つかもしれませんので、自分の経験をお話しします。 電気通信主任技術者とは そもそも「電気通信主任技術者」とは何でしょうか。 電気通信主任技術者は、電気通信ネットワークの工事、維持及び運用の監督責任者です。 電気通信事業者は、その事業用電気通信設備を、総務省令で定める技術基準に適合するよう、自主的に維持するために、電気通信主任技術者を選任し、電気通信設備の工事、維持及び運用の監督にあたらなければなりません。 ( 日本データ通信協会HP より引用) 電気通信主任技術者は、(原則として)「電気通信主任技術者資格者証」を持っている人から選任します。この「電気通信主任技術者資格者証」を得るための試験が「電気通信主任技術者試験」です。 電気通信主任技術者試験には 伝送交換主任技術者試験 線路主任技術者試験 の2種類あり、「伝送交換主任技術者試験」を受験しました。 なお、一定規模以上の電気通信事業者は有資格者を配置する必要があり、当社も該当します。 試験内容 試験科目は以下の3科目です。3科目それぞれ6割以上で合格です。 電気通信システム 20問 80分 電磁気学や電気工学の問題や、電気通信の基礎問題が問われます。 高校物理や符号理論、TCP/IPなど通信の基本が絡むため比較的理解しやすかったです。 伝送交換設備及び設備管理 大問9問 150分 伝送交換設備の概要や運用に加え、セキュリティやソフトウェア管理について問われます。 実務の経験が無いと聞いたことが無い用語が多く、苦戦しました。 法規 大問5問 80分 電気通信事業法をはじめとする関連法規について問われます。 いわゆる理論的な話ではなく暗記が物を言うため、苦戦しました。 科目合格制度もあるので、2科目合格して次回の試験で1科目合格する……という方法もあります。 なお、「工事担任者」などの資格を持っていると一部科目で免除があります。私は該当する資格を持っていなかったので、3科目受験しました。 勉強方法 基本的には過去問周回です。試験では過去問と同じor非常に似た問題が多く出題されるので、「見たことがある問題を可能な限り多く作り、絶対に落とさない」という戦法で挑みました。6割合格なので、この戦法で合格できると信じました。 勉強をするにあたり色々なテキストを買いたくなりますが、あれこれ買うと高くつくので、「自分はこれを完ぺきにするんだ!」というものを決めて買いました。どんな勉強でも反復学習が大事なので、決めたものをひたすら繰り返します。 試験はすべて選択マーク式です。「以下から正しいものを選びなさい」という問題がある際は、他の選択肢がなぜ間違っているのか、どこを直せば正しくなるのかを説明できるようにすることを心掛けました。 総勉強時間は約60時間でした。うち伝送交換設備及び設備管理に約30時間かけているので苦戦したことが分かります…… 試験当日 試験は日曜日の午前から始まります。年に2回しかない試験なので、寝坊すると次のチャンスは半年後になってしまいます。(受験料も2万円弱するのでもったいない) 受験会場に向かう際は若い人や女性の方もたくさんいたのですが、ほとんどが同じ場所で行っている英検の受験会場に吸い込まれていきました。 電気通信主任技術者試験の会場には200人ほどがおり、ほとんどが40~50代の男性に見えました。休日のおじ様たちがラフな格好で来ているのが大半でした。おそらく自分が会場内で一番若かったです。 各科目の試験時間は長いですが大半の方が途中退出します。お昼ご飯の時間も十分にあるので、時間が余りがちでした。空いた時間に最後のつめこみができるように、勉強道具を持っていくのがおすすめです。 腕時計を持ち込みする際、 アナログ式時計(液晶表示のあるものは認めない) という独特なルールがあるので注意です。日付表示だけ液晶表示といった時計も禁止です。隣の席の人が監督員に注意されていました。また、腕時計は外して机に置くよう指示されます。自立しないタイプの腕時計だと厳しいかもしれません。 ティッシュはカバンにしまい、使うときに監督員を呼ぶように指示されました。毎日ティッシュが欠かせない私としてはこれが一番大変でした。試験時間中に何度監督員を呼んだことか…… 問題冊子は持ち帰るように言われます。自己採点のために自分の回答を問題冊子にメモしておくと良いです。 結果発表 試験の数日後に正答がwebで公開されます。結果発表が待ちきれず自己採点しました。3科目とも7~8割で合格点に達していそうで一安心です。とはいえ結果発表までは安心できません。 試験から3週間後に結果発表があります。web上で合否を確認します。 無事に合格しました。勉強した成果が出てよかったです。 これで現状の社内で最年少の合格者になれました。 資格者証申請 まだ安心できません。試験に合格した人は申請して「電気通信主任技術者資格者証」の交付を受けなければいけません。管轄の総合通信局へ申請書を提出します。 顔写真、収入印紙、住民票の写し等を用意します。この資格者証、運転免許証などと異なり 有効期限が無い ので残念な写真は使わない方が良いです。一生残念な写真の資格者証と共に過ごすことになります。 申請から約1か月で資格者証が届きました。これで堂々と有資格者と名乗ることができます。 資格手当 先述の通り有資格者が社内で必要であるため、資格を取ると補助が会社から出ます。初任給に+で補助が出るのは大きいです。 おわりに 入社してすぐの環境に慣れない中でしたが、受験し合格することができてよかったです。 電気通信主任技術者に興味があるかたは是非受験してみてください。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass カジュアル面談も受け付けています! ニフティ株式会社 – Meety
アバター
イベント概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントでは、ニフティグループの社員が業務を通じて学んだことを発信しています! TechTalk#14は「GitHub Copilotの導入や活用」です。 どれほどのものを開発業務にもたらしてくれるのか、その便利さとは。 使ってみたいけどなにが出来るのかよくわからないなどなど気になる方は是非ご視聴ください! 概要 日程:9月26日(火)12:00〜13:00 配信方法:YouTube Live 視聴環境:インターネット接続が可能なPC/スマートフォン 参加方法 connpass にて登録をお願いいたします。 YouTube Liveにて配信いたします。 ※YouTube LiveのURLは決定後、参加者への情報欄に記載いたします。 こんな方におすすめ GitHub Copilotに興味がある方 導入を検討している方 タイムテーブル 時間 コンテンツ 12:00 – 12:10 オープニング+会社紹介 12:10 – 12:25 LT1: GitHub Copilotの導入と開発生産性への効果 12:25 – 12:40 LT2: クリーンアーキテクチャとTDDの中でCopilotを使ってみた! 12:40 – 12:55 LT3: Copilotを使って爆速コーディングする 12:55 – 13:00 まとめ+クロージング テーマ GitHub Copilotの導入や活用 登壇者プロフィール 石川 貴之(登壇者 ) ニフティ株式会社 会員システムグループ 第1開発チーム AWS/GCPの組織管理、Notion/GitHub等のSaaS管理、自社Webサービス基盤の担当をしています。 たけろいど(登壇者) ニフティ株式会社 会員システムグループ 第2開発チーム Copilotを使って開発を行うWEBアプリケーションエンジニアです。 普段はPythonやSvelteのコーディング支援をしてもらっています。 いかりがわ(登壇者) ニフティ株式会社 会員システムグループ 第1開発チーム 新卒3年目。ニフティのポータルサイトの開発運用を担当しています。 普段はNext.jsやGoをCopilotさんと一緒に書いてます。 ニフティグループでは一緒に働く仲間を募集中です 新卒採用、キャリア採用を実施しています。ぜひ リクルートサイト をご覧ください。 ニフティエンジニアが業務で学んだことやイベント情報を エンジニアブログ にて発信しています! ニフティエンジニアのTwitterアカウントを作りました NIFTY Tech Talkのことや、ニフティのエンジニアの活動を発信していきます。 Tweets by NIFTYDevelopers アンチハラスメントポリシー 私たちは下記のような事柄に関わらずすべての参加者にとって安全で歓迎されるような場を作ることに努めます。 社会的あるいは法的な性、性自認、性表現(外見の性)、性指向 年齢、障がい、容姿、体格 人種、民族、宗教(無宗教を含む) 技術の選択 そして下記のようなハラスメント行為をいかなる形であっても決して許容しません。 不適切な画像、動画、録音の再生(性的な画像など) 発表や他のイベントに対する妨害行為 これらに限らない性的嫌がらせ 登壇者、主催スタッフもこのポリシーの対象となります。 ハラスメント行為をやめるように指示された場合、直ちに従うことが求められます。ルールを守らない参加者は、主催者の判断により、退場処分や今後のイベントに聴講者、登壇者、スタッフとして関わることを禁止します。 もしハラスメントを受けていると感じたり、他の誰かがハラスメントされていることに気がついた場合、または他に何かお困りのことがあれば、すぐにご連絡ください。 ※本文章はKotlinFest Code of Conductとして公開された文章( https://github.com/KotlinFest/KotlinFest2018/blob/master/CODE-OF-CONDUCT.md )を元に派生しています。 ※本文章はCreative Commons Zero ライセンス( https://creativecommons.org/publicdomain/zero/1.0/ ) で公開されています。
アバター
はじめに こんにちは。会員システムグループの上原です。 8月末に社内でISUCONを開催・運営したので、レポーティングしていこうと思っています。 ISUCONとは? ISUCON ( Iikanjini Speed Up Contest) は、限られたリソース・時間の中でWebサービスをどれだけ高速にできたかを競うコンテストです。 ISUCONで参加者は動作が遅いWebアプリケーションを与えられ、アプリケーションを高速化していくために設定を最適化したり、コードを改善したりする必要があります。 チーム間でスコアを競い合いながら、高速化していけるところがISUCONの醍醐味です。 ISUCONを通じて、モニタリングやデータベースのチューニングなどのスキルを向上させることができます。 ちなみに、優勝すると賞金100万円をゲットできます! (※「ISUCON」は、LINE株式会社の商標または登録商標です。 https://isucon.net ) 今回のイベント 本家ISUCONと同じく、webアプリケーションをどれくらいチューニングできるかチームで競っていくぜ…と行きたかったのですが、パフォーマンスチューニングって何?という人も多い状況でいきなり競技形式で行うのは負担が大きいと思われたので、座学とハンズオン形式を組み合わせたワークショップを行いました。 また、より多くのエンジニアに参加してもらうため、デフォルトでエンジニア全員を参加対象とし、欠席者は個別に連絡してもらうオプトアウト形式を取ることにしました。 そのおかげからか94名の社内のエンジニアの皆さんに参加いただくことができました! タイムスケジュール 以下のように前半1時間は座学、後半3時間はハンズオン形式とし、講師と一緒にパフォーマンスチューニングを学べるようにしました。 座学(1時間) 高速なWebサービスの意義 チューニングの基礎 モニタリングの基礎 ハンズオン(3時間) ワークロードの分析&ボトルネックの発見 WEBサーバのログからレイテンシを調べる スロークエリを探す データベースのチューニング SQLの実行計画の分析 N+1問題の解決 Webサーバのチューニング なお、内容は以下の書籍を参考にさせていただきました。著者の方々に感謝申し上げます。 達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践 座学 高速なwebサービスとは何か?ハンズオンをやる上であらかじめ知っておくべき解説をやっていきました。 (内容紹介は省略…) ハンズオン 題材 今回使用する題材はpixiv株式会社の社内ISUCONで使用されたprivate-isuを使用しました。 https://github.com/catatsuy/private-isu このアプリケーションはisucogramという仮想の写真共有SNSで、写真投稿機能やコメント機能など簡単な機能が実装されています。 今回は、参加者全員にアプリケーションサーバー1台とベンチマークサーバー1台を提供しました。 本家ISUCONでは序盤はチューニングをいきなり行うのではなく、必要なツールの導入・設定などを行う必要がありますが、時間が限られていることもありサーバー設定、ツール導入、サーバー立ち上げなど必要な準備は運営側で全て行いました。 ということで、参加者がサーバーにsshできればすぐにパフォーマンスチューニングを楽しめる状態にしました。 また、sshでサーバー接続がうまくできないことも見越して、AWSのセッションマネージャー経由でサーバーにログインできるよう設定を仕込んだり、言語が障壁とならないように、社内でもっとも読み書きできる人間の多い python に実装を変更したりしました。 その際以下のレポジトリを参考にしました。作者の方には感謝申し上げます。 https://github.com/methane/pixiv-isucon2016-python 負荷試験を行う 早速、ベンチマークを走らせ負荷試験を行っていきます。アプリケーションに残ったログにalpコマンドやpt-query-digestコマンドを噛ませて、ボトルネックをどのように見つけていくか体験してもらいました。 この段階ではまだ0点です。 初めてのチューニング htopでCPUコアが一つしか使われていないことがわかったので、設定を変更してCPUコアをフルで使えるようにしました。 1000点くらいまで伸びました。 データベースチューニング pt-query-digestでスロークエリを特定、EXPLAINで実行計画を分析したのち、適切なインデックスを貼っていってもらいました。これだけでもスコアは15000点くらいまで伸びます。 スコアがいきなり1万点台に到達したので驚いた人もいたようです。 ほかにもN+1問題の解消などにも取り組んでもらいました。 リバースプロキシ データベースに画像が保存されている問題があるため、アプリケーションコードとリバースプロキシの設定をいじって、ファイルから画像を参照するような修正を行いました。 また、gzip配信やブラウザキャッシュなどにも取り組み、最終的には7万点くらいになりました。 ボトルネックに集中して消化することは大事 パフォーマンスチューニングはボトルネックに集中して解消しなければならないと言われます。 インデックスを消すだけで、スコアは一気に1000点台まで下がるため、ボトルネックを解消することの大切さを認識できたのではないかなと思います。 感想 イベント中、slackチャンネルも盛り上がりわいわいとした雰囲気でできたので良かったです。 参加者からのアンケートの結果、ほとんどの方から好意的な感想をいただくことができました。 理由としては、パフォーマンスチューニングの結果がスコアとして数字に出てくるのが良かったようです。 具体的な数値としてスコア改善が見られるのは面白かった。 クエリチューニングでどれくらい性能差が出るのか実感できて面白かった。 一方で4時間という短い時間に内容を詰め込んでしまったため、内容についていけないという方もいたようです。 業務に影響がないように短い時間内に収めるのはなかなか難しいですが、1日目は座学、2日目はハンズオンなど日程を分けて行うのもいいのかなと思いました。 ただ運営としては、半年間準備を行いオプトアウト形式で実施したため絶対に失敗できない…!というプレッシャーがあったのですが、参加者から学びが多かったという声が多く、苦労が報われて良かったです。 最後に 今回はワークショップ形式で行いましたが、次回は本家ISUCONと同じくチーム競技でやっていきたいと思っています。 本家ISUCONの方には今回の運営メンバーでチームを組み挑んでいきたいと思いますので、ISUCONに参加される方はよろしくお願いいたします! We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
前回の記事で、ニフティでSREとして働く社員に、ニフティでのSREの取り組みと、仕事を進めるにあたっての工夫点などをインタビューを行いました。 今回はインタビューの後編をお届けします。前編はこちらの記事をご覧ください。 【インタビュー】ニフティのSREに聞く!インターネット黎明期から安心・安全を体現してきたニフティが2023年に取り組んでいるSREとは?【SRE前編】 入社5年目のネットワークエンジニアがSREに。 Kさんは自ら希望してSREチームに入ったそうですが、希望理由はなんですか。 Kさん SRE、DevOpsに魅力を感じて希望しました。 具体的にどんなことをやっているんですか。 Kさん 最近は開発チームの生産性を可視化しようとしています。GitHubのログを抽出して、それをLooker Studioを使ってグラフにしてビジュアライズすることで、週次の生産性を計ろうとしています。生産性が低い場合にできるアクションを今検討しています。 SREチーム内でのコミュニケーションについて。 チームで動く上で大事にしていることは何ですか。 Kさん ニフティはハイブリッドワークなので、日によってオフィスにいるメンバーが違います。出社しているメンバーは出来るだけ顔を合わせて会話できるようにしています。 Sさん やっぱりコミュニケーションは大事ですよね。 Aさん そうですね。チームの体制はスクラムなので、スクラムチームのアクティビティ(デイリースクラムやスクラムイベント、レビューなど)を通してメンバーと密にコミュニケーションを取り合っています。それと、施策に対してしっかりとリリースを行うことを意識して進めています。 リモートワークだと直接顔を合わせない日もありますが、コミュニケーションが取りづらかったりすることがありますか。 Aさん 自分はこの会社に勤めて長いのであまり感じないですね。Sさんは入社して1年経ってないですがどうでしょう。社員の顔がわからないとかはありますか。 Sさん 私は入社したばかりなので、顔がわからない人は多いですね(笑)。ただ、前職はフルリモートだったのでコミュニケーションが取りづらいとは感じませんでした。ただ、出社の機会があることで顔を合わせて雑談や会話できるのはとてもいいなと思います。 SREチームのワークライフバランスとは。 休みはとれていますか。 Aさん 有給休暇は自由にとれていて、旅行など長めの休暇もとることもできます。 Aさん アフタヌーンティーに出かけたり、ディズニーにいったり近場の温泉に旅行に出かけたりしています。今年は行動制限もなくなったので、旅行に行きたいですね。 Kさん ライブに行ったり、観劇したりしています。宝塚、劇団四季など歌って踊る系が好きです。あとは映画を観たりして過ごしています。 Sさん 子供がいるので、休みの日は子供と遊ぶことが趣味になっています。最近外を歩けるようになったのでお散歩したり、子供と一緒にあそべる施設などに出かけたりしています。 Aさん お子さんはそろそろディズニーデビューできそうですか。 Sさん まだ早いです(笑)。 ニフティのSREが求めるエンジニアとは。 これからどんなエンジニアの方と一緒に仕事がしたいですか。 Aさん いろんな人とコミュニケーションをとって、自発的に提案ができるエンジニアを望んでいます。色々なチームに対して提案や技術支援を行うのでそういったコミュニケーションが得意な方と一緒に働けると嬉しいです。 Kさん 文化を浸透させる立ち位置なので、Aさんと同じく、コミュニケーションをとって相手の同意を得て進められるような方がいいですね。 Aさん Sさんと私は社会人歴としては同じくらいですよね。チームの中でKさんは年次が若いので、年が近い人に来てほしいなどありますか。 Kさん そんなことはないです。そういうことを気にする会社ではないので。 Sさん SREはいろんなサービスに横断して関わっていくので、コミュニケーションスキルはもちろん、インフラだったりクラウド知識やプログラミングのスキルなど、幅広いスキルを持っている/持ちたいと思っている方に来てほしいです。特にこのスキル!というものはないのですが、様々なスキルの中でも自分の得意なスキル、尖ったスキルを持っていて、そのスキルも他のスキルも上げていきたいという意欲がある方があっているかなと思います。 今回はニフティのSREチームのインタビューの様子をお届けしました。ニフティでは、SREを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
ニフティで推進中の「SRE」とは。 簡単に自己紹介をお願いします Aさん ニフティでSREを推進したいと考え、2020年にSREチームを立ち上げてリーダーをやっています。SRE関連業務のほかに、Webサービスの開発と運用や、サーバーをAWSへマイグレーションなども行っています。 Kさん SREチームに入ってちょうど1年経った5年目社員です。2022年9月まではネットワークエンジニアとして社内のネットワークの刷新などを担当していました。その時の知識を生かしてNIFTY Tech Day、NIFTY Tech Talkなど、YouTubeの配信を伴うイベントのお手伝いをやったりもしつつSREを推進しています。 Sさん 2023年3月に入社したばかりのキャリア社員です。ニフティへ入社する前はSRE業務ではなく、お客様に向けたWebサービスの開発を行っていたのでフィードバックや反応が見えづらい環境でしたが、今は社内メンバーがお客様のような立場で、自身が作ったものに対して喜んでくれたり、良い反応を得られるので新鮮で楽しいです。 SRE、ニフティのSREについて教えてください。 Aさん SREでは信頼性も重要な機能の一部だと捉えます。具体的な仕組みに比べると機能として捉えられないと思いますが、5回に1回買い物が失敗したり、10回に1回違うものが届いちゃうショッピングサイトを使いますか、ということですよね。必ず購入出来て、必ず正しいものが届くということ。それが信頼性です。 Sさん 前職ではSREというポジションがなく、ニフティに来て初めてSREを知ったのですが、ニフティはサービスの品質を高めようとする動きが活発だということが分かって、それはとてもいい文化だと思いました。開発に比べるとないがしろにされがちですが、システムを安定して稼働させる、障害を少なくすることは開発と同じくらい重要です。その重要性を会社全体で認識できるように活動していきたいです。 Aさん SREのアプローチを全社に広めていきたいと思っていますが、十分に浸透しているとはいえないのでアプローチの方法を色々と模索しています。勉強会やワークショップを開いてみたり、社員にまず興味を持ってもらう取り組みを行っています。また、サービス品質を向上させることを目的とした部門横断的なプロジェクトが立ち上がっているのですが、そのプロジェクトにSREチームが関与することで認知を広げていっています。 チームとチームをつなぐのは、これまでに培った技術力と柔軟なコミュニケーション力。 他のチームに入り込んで進めるとおっしゃいましたが、具体的にどのように進めているんですか。 Kさん 自分たちからSREを提案しに行きます Aさん そのチームの一員となるような感じでやっています。タスクを整理するときにSREのタスクを組み込んでやってもらうような感じです。このスプリントではこの機能を修正する、というタスクがあると思いますが、SREのためのタスクも1つは組み込んでもらう。機能開発が8割だとしたら2割くらいはSREのためのアプローチのタスクを入れてもらっています。 SREを提案されたチームの反応はどんな感じですか。 Aさん 普段の業務に追加になるので、やりたいと思ってもできないこともありますね。目指しているのは全員がやっている状態ですが、できそうなチームからお話をしています。業務の多寡などをみて優先順を決めています。 スクラムチームであれば、プロダクトオーナーは企画の社員が多いと思うのですが、企画の社員にSREを理解してもらうためにどんなアプローチを行っていますか。 Aさん 企画へのアプローチはまだ十分にできておらず、今後どんどんやっていきたいですね。企画の部門長などに必要性の説明などもしたいと思っています。 最終的に目指しているのは、企画も開発も信頼性を担保しつつ自分のサービスの成長を判断できる状態です。極端に言うと、品質が悪ければ新機能のリリースよりも品質を高めることを優先するような判断を選択肢に入れていきたいです。 Kさん 僕も同じ意見です。 Aさん 組織がアジャイル組織になっているか、DevOpsを経営層までもが理解しながら進んでいる状態をゴールに描いています。 後編に続きます! 今回はニフティのSREチームのインタビューの様子をお届けしました。続きは後編の記事をご覧ください。 【インタビュー】ニフティのSREはどんな人?【SRE後編】 ニフティでは、 さまざまなプロダクトへ挑戦する エンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトより お気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering connpassでニフティグループに 参加いただくと イベントの お知らせが届きます! connpassで ニフティグループに参加する
アバター
はじめに ニフティ株式会社の白岩です。ニフティに新卒入社して約5ヶ月が経過しました。 今秋の情報処理安全確保支援士試験を受験することにしました。本記事では、試験制度の簡単な解説と、受験するに至った経緯と合格に向けた勉強法を記載します。 情報処理安全確保支援士試験とは IPA(独立行政法人 情報処理推進機構)が実施する情報処理技術者試験の1つで、情報セキュリティスペシャリスト試験の後継です。 午前Ⅰ試験 試験時間:9:30〜10:20 50分 出題形式:四肢択一 出題数:30問 概要:午前Ⅰ試験は全てのスペシャリスト試験に共通で、応用情報技術者試験の午前問題が出題されます。 午前Ⅱ試験 試験時間:10:50〜11:30 40分 出題形式:四肢択一 出題数:25問 概要:情報セキュリティやコンピュータネットワークに関する問題が重点的に出題されます。 午後試験 試験時間:12:30〜15:00 150分 出題形式:記述式 出題数:全4題から2題を選択 概要:情報セキュリティに関する10ページ程度の文章を読み、設問に回答します。令和4年以前は午後Ⅰと午後Ⅱに分かれていましたが、令和5年以降から纏められました。 合格率:15〜20% 合格基準:全ての試験区分で60%以上 登録制度について 情報処理安全確保支援士は、弁護士や公認会計士などと同列の「士業」にあたります。試験合格後、所定の手続きに従って登録することで情報処理安全確保支援士を名乗れるようになります。 また、少々ややこしいですが「情報処理安全確保支援士試験」は 国家試験 の名称、「情報処理安全確保支援士」は 国家資格 の名称です。 情報処理技術者試験 試験区分一覧(IPAより引用) 情報処理安全確保支援士に登録した場合、資格維持のためには定期講習の受講が必須で、その費用が高額です。初回登録時の費用が約2万円、1年に1回の講習が2万円、3年に1回の講習が8万円、合計すると3年間で約14万円の費用が発生します。 この金額を何の抵抗もなしに支払える財力は今の私にはないので、すぐには登録しない予定です。今後のキャリアで必要になったときに登録を検討したいです。 実は、情報処理安全確保支援士には登録期限がありません。試験合格から20年後、30年後でも登録可能となっています。 また、未登録であっても、試験合格の実績は履歴書などに記載することができます。 ただし、支援士でない状態(未登録または期限切れ)で支援士を名乗ると法に触れるので注意が必要です。 参考: 情報処理安全確保支援士 よくあるご質問(IPA) 受験理由 情報セキュリティに関する知見を深めたい 私は情報系学部出身ですが、情報セキュリティはほとんど学習しませんでした。実務経験もまだないので、正直なところ合格できる自信は全くないです。 しかしながら、情報セキュリティはそれなりに興味のある分野であり、今後の業務に活かせる可能性もあると思い、受験を決めました。 午前Ⅰ試験の免除ができた 令和4年度春期の応用情報技術者試験を受験し、無事に合格できたので午前Ⅰ試験の免除が可能でした。 社内の支援制度が充実していた ニフティには キャリアアップ支援制度 があります。情報処理安全確保支援士試験も資格取得支援制度の対象なので、合格時に報奨金が支給されます。また、書籍購入費用補助制度を利用して参考書の購入ができます。 合格に向けた勉強法 過去問を解いていくうちに、問題の特徴や形式は、難易度は違うものの応用情報技術者試験とあまり変わらないように感じました。そのため、当時と同じ勉強法を取っています。 今回は無関係ですが、スペシャリスト試験の中には論述が出題される区分もあります。その場合は勉強法も変わってくると思います。 過去問をたくさん解く 全ての情報処理技術者試験においてマストです。最低でも過去5年分は浚っておきたいです。 午後試験では、体系的な知識のほかに、10ページ程度の長文を理解する読解力や回答を言語化する力も必要なので、過去問を解いて身につける必要があります。 応用情報技術者試験でも記述問題には苦労しましたが、過去問を繰り返し解くうちにコツを掴みました。スペシャリスト試験は問題文が非常に長いので一題一題が重いですが、過去問を通して慣れていきたいです。 参考書 先述の書籍購入費用補助制度を利用して網羅系の参考書を1冊購入しました。試験日までに一通り読んでおく予定です。 情報セキュリティに関するニュースや時事ネタを知っておく 時事問題が出題される場合があるので、概要を知っておくだけでも有利になると思います。 最近では、令和4年度の試験で、Apache Log4jのゼロデイ脆弱性であるLog4Shell(CVE-2021-45105)が題材となっています。 試験当日の準備をしておく これは試験勉強ではありませんが非常に重要です。 当日までにやるべきこととして、起床時刻と電車の時刻を集合時刻から逆算する、試験当日の持参物をまとめる、試験会場へのアクセス方法を調べる、昼食をどうするか決めるなどが挙げられます。 「乗る電車を間違えた」「試験会場に到着してから受験票がないことに気付いた」など、試験を受けられないという事態だけは絶対に避けなければいけません。 今後について 試験まであと1ヶ月程度ですが、現状では午後試験はまだまだこれからの段階です。午前試験は既に仕上がっているので、午後試験の対策をどれだけできるかによって合否が決まります。 もし今回の試験で合格できた場合、次はネットワークスペシャリスト試験に挑戦したいと考えています。セキュリティとネットワークは関わりが深く、共通する内容が多いので今回の試験勉強も活きてきます。こちらは1年に1度の開催で、合格率が13〜15%程度なのでさらに厳しい試験です。 不合格だった場合は、合格に至らなかった原因をよく考えた上で、半年後に再挑戦したいです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass カジュアル面談も受け付けています! ニフティ株式会社 – Meety
アバター
はじめに こんにちは、会員システムグループの上原です。 本記事ではサービスアカウントを使ったGoogle Apps Script(GAS)とGoogle Cloud BigQueryの連携方法を紹介していきます。 やりたいこと 今回、BigQueryを叩いてとってきたデータをスプレッドシートにまとめる処理を行う、GASスクリプトを改修していきます。 GASでBigQueryサービスを使用すると簡単にBigQueryを叩けますが、その際に実行ユーザーの権限が使用されるため、もしもそのユーザーが退職した時にスクリプトを実行できなくなって困ります。これは特にインストーラブルトリガーで定期実行設定しているようなスクリプトで問題になります (参考: https://note.com/0375/n/n3929ccfca5fc )。 この問題の解決策として、GCPからサービスアカウント(アプリケーション向けのユーザー)を払い出し、GASにその認証情報を使用させます。 これによりサービスアカウントで実行されるようになるので、属人化を排除することができます。 ということで、GCPから払い出したサービスアカウントを使ってGASからBigQueryを叩けるようにしていきます。 やり方 [GCP] サービスアカウントを追加する GCPのIAMと管理でサービスアカウントを開きます サービスアカウントの作成をクリックし、名前や説明を入力します。 作成して続行をクリックします ロールを適用します 以下のロールがあればいいです BigQueryジョブユーザー(roles/bigquery.jobUser) BigQueryデータ閲覧者(roles/bigquery.dataViewer) 完了をクリックします [GCP] サービスアカウントの認証情報を払い出す 再びGCPのIAMと管理でサービスアカウントを開き、作成されたサービスアカウントをクリックします キータブに切り替え、鍵を追加をクリックし新しい鍵を作成をクリックします キーのタイプとしてjsonを選び作成をクリックします このタイミングでjsonが勝手にダウンロードされるはずです。中身を確認すると秘密鍵の内容を見ることができます。 { "type": "service_account", "project_id": "gcp_example_id", "private_key_id": "12345678", "private_key": "-----BEGIN PRIVATE KEY-----\n秘密鍵の中身\n-----END PRIVATE KEY-----\n", "client_email": "daily-gas-bigquery@gcp_example_id.iam.gserviceaccount.com", "client_id": "12345678", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/daily-gas-bigquery%40gcp_example_id.iam.gserviceaccount.com", "universe_domain": "googleapis.com" } この認証情報は再発行できない(作り直す必要がある)かつGASの設定で使うので大切に保管しておきましょう。 [GAS] OAuth用のライブラリを追加する GASでEditorの画面からLibrariesをクリックします。OAuth用のライブラリを追加します。 Librariesをクリックし、Script IDを入力します。 ScriptIDは以下のGitHubレポジトリに書いてあります。2023/09/08現在は1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDFです。 https://github.com/googleworkspace/apps-script-oauth2 Lookupをクリック後Addをクリックします。 VersionやIdentifierはそのままでokです。 [GAS] jsonに書いてある権限情報をScript Propertiesに設定する Project Settingsに移動しScript Propertiesに変数を追加します。 BIGQUERY_CLIENT_EMAILADDRESS サービスアカウントのメールアドレスダウンロードしたjsonのclient_emailに書いてあります BIGQUERY_CLIENT_PRIVATEKEY サービスアカウントの秘密鍵ダウンロードしたjsonのprivate_keyに書いてあります [GAS] BigQueryを叩くための関数を追加する editorに戻りbigquery.gsを作成します。 bigquery.gsに以下を貼り付け、gcp_example_idの箇所を自分のプロジェクトIDに直してください。 function get_bigquery_service() { // https://github.com/googleworkspace/apps-script-oauth2/issues/122#issuecomment-507436277 // BIGQUERY_CLIENT_PRIVATEKEYの\nが\\nとなって改行がうまく反映されないため、\\nを\nにreplaceします const PRIVATE_KEY = PropertiesService.getScriptProperties().getProperty("BIGQUERY_CLIENT_PRIVATEKEY").replace(/\\n/g, '\n'); return OAuth2.createService("bigquery") .setTokenUrl("https://accounts.google.com/o/oauth2/token") .setPrivateKey(PRIVATE_KEY) .setIssuer(PropertiesService.getScriptProperties().getProperty("BIGQUERY_CLIENT_EMAILADDRESS")) .setPropertyStore(PropertiesService.getScriptProperties()) .setScope("https://www.googleapis.com/auth/bigquery"); } function create_request_option(method, payload) { const service = get_bigquery_service(); if (service.hasAccess()) { return { "method": method, "muteHttpExceptions": true, "contentType": "application/json", "payload": JSON.stringify(payload), "headers": { Authorization: "Bearer " + service.getAccessToken() } }; } else { Logger.log(service.getLastError()); } } function create_query(query) { // https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query // TODO: gcp_example_idを書き直してください const url = "https://bigquery.googleapis.com/bigquery/v2/projects/{gcp_example_id}/queries" const payload = { query: query, useLegacySql: false }; const fetch_options = create_request_option("POST", payload) const response = UrlFetchApp.fetch(url, fetch_options) const response_json = JSON.parse(response) Logger.log(response_json) return response_json } function get_query_results(jobId, pageToken) { // https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/getQueryResults // TODO: gcp_example_idを書き直してください。 let url = `https://bigquery.googleapis.com/bigquery/v2/projects/{gcp_example_id}/queries/${jobId}` if (pageToken != null) { url = `${url}?pageToken=${pageToken}` } const payload = {} const fetch_options = create_request_option("POST") const response = UrlFetchApp(url, fetch_options) const response_json = JSON.parse(response) Logger.log(response_json) return response_json } [GAS] コードの修正 BigQueryサービスにアクセスする箇所で新規に作成した関数を呼び出すよう置き換えます。 BigQueryサービスから帰ってくる値とレスポンスは同じはずなので、他に修正は必要ないはずです // BigQueryサービスを使った場合の書き方 // var queryResults = BigQuery.Jobs.query(request, "example-id"); var queryResults = create_query(queryToBigQuery); // BigQueryサービスを使った場合の書き方 //queryResults = BigQuery.Jobs.getQueryResults('example-id', jobId, { // pageToken: queryResults.pageToken //}); queryResults = get_query_results(jobId, queryResults.pageToken); 典型的には以下のようなコードになるはずです // BigQueryへのクエリを書く const querytobigquery = "select * from ~~~~"; // BigQueryにリクエストを送る var queryresults = create_query(querytobigquery); var jobid = queryresults.jobreference.jobid; // クエリが完了するまで待たないとエラーになる可能性があるので完了を待つ var sleeptimems = 500; while (!queryresults.jobcomplete) { utilities.sleep(sleeptimems); sleeptimems *= 2; queryresults = get_query_results(jobid, null); } // クエリの結果からすべてのレコードを取得する var rows = queryresults.rows; while (queryresults.pagetoken) { queryresults = get_query_results(jobid, queryresults.pagetoken); rows = rows.concat(queryresults.rows); } // rowsを処理してスプシに入れる (もしあれば)ServicesからBigQueryを削除します [GAS] 実行してみよう 実行してみる これで自分のアカウントではなくサービスアカウントの権限でBigQueryが叩かれるようになります どういった権限で叩かれているかはGCPのログを確認してみてください これでうまく動くはずですが、うまく動かない箇所があれば、以下を確認してみてください サービスアカウントが作成されているかどうか、足りないロールがないか GASに設定した認証情報が正しいかどうか 最後に 以上、BigQueryをGASからサービスアカウントで叩く方法をまとめてみました。 ネット上にある情報を参考にしても動かなくて困っていたのですが、この記事通りにすれば動くはず…!というのをまとめてみたので、もしお役に立てれば幸いです。 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
イベント概要 NIFTY Tech Talkは、ニフティ株式会社の社員が主催するトークイベントです。 本イベントでは、ニフティグループの社員が業務を通じて学んだことを発信しています! 第12回目は「スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギ」です。 ニフティの認定スクラムマスターの中から3名が語る回となります。 【6/27(火) 12:00~】スクラム開発の真髄を探る!認定スクラムマスター研修参加者が語る成功のカギを開催します! 【イントロダクション】認定スクラムマスターってなんですか? 発表に入る前に、まずは認定スクラムマスターについて説明いただきました。 資料 【LT1】認定スクラムマスター研修の概要と認定試験について 認定スクラムマスターになってまだ間もないところで、研修や試験を受けて思ったこと、感想など。 これから認定スクラムマスターを目指す方にとって参考になる内容かと思います。 資料 【LT2】スクラムに向かない情シスチームの スクラムマスターが CSMを取得して2年の間に思ったこと 講師からも困難と認定されたものに果敢に挑み、成果を出した猛者のお話し。 スクラム運営の参考になること間違いなし。 資料 【LT3】認定スクラムマスターになった後、A-CSMって取るべき? 認定スクラムマスターの次のステップ、アドバンスド認定スクラムマスターに興味のある方、取得を迷っている方にとくにみて欲しいと思います。 さらに先を目指す方必見の内容となっております。 資料 まとめ 認定スクラムマスターになってまだ間もない方や、スクラムにあまり向いていない業務に当てはめてやっている方、アドバンスドを持ってる熟練者まで幅広いお話しが聞けました。 また、発表後に長めの雑談タイムがありました。各発表での質問と違い、発表者全員から回答したりなどなど本編に劣らずためになる時間になったのではないかと思っております。 アーカイブ(YouTube) 発表資料(Speaker Deck) We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
ニフティ株式会社新卒3年目のRyommです。 ニフティ株式会社とニフティライフスタイル株式会社の合同で、毎週火曜日に CheesySwift / CheesyKotlin という名前でアプリの勉強会を主催しています。 今回は、CheesyKotlinで2回にわたった Compose Animation の勉強会の総仕上げとして行なった  Compose Animation 100本勝負  を特別に公開します! ぜひ、Compose Animationの腕試しにチャレンジしてみてください。 ↓Compose Animation 100本勝負 ↓ https://notion.engineering.nifty.co.jp/posts/cheesykotlin-compose-animation/ We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター
はじめに こんにちは、IWSです。 少し前になりますが、5月に社内で行われたLT大会に登壇させていただきました。 実はこのLTにはVRで参加させていただいたのですが、せっかくなので、今回はこのVRでLTをしたときのことについて書いていこうかなと思います。 VR で LTって? こんなのです う〜ん、これはあまりにもかわいいですね…… バーチャルな空間でスライドぱらぱらめくってLTに登壇できたら絶対かわいくてたのしいよな〜と思ったので作りました。(せっかく買ったのにほこり被り気味なVR機材を使ってあげたかったというのもありますが……) 環境 Unityを使って作っていきます。VRChatやClusterにも発表ができるワールドはあるのでそれを使えば簡単なのですが、せっかくなので自分で作って遊んでみたいと思います。 ちなみに環境は以下のとおりです。 Windows10 Home Unity : 2019.4.40f1 SteamVR Plugin Final IK HMD:Vive Cosmos 機能 VRの部分の基本的な機能はSteamVR Pluginを使って作っています。 VRでの移動システムなどが入っているのでぶっちゃけこれを使えば簡単なVRのなにかはすぐ作れたりします。すごい。 なので、これをベースにしつつLTに必要そうな機能を追加して行けばよさそうですね。 やってみましょう。 移動 せっかくのVRなのに棒立ちというのは寂しいので移動は必須でしょう。 SteamVR Pluginを使えばテレポートによる移動なんかは簡単に実装ができます。ただ、そのままでは1人称視点向けの両手だけのモデルになっておりこれだとかわいくありませんし、別視点から見ても何をしているのか分かりづらいです。ですので、こちらで用意したかわいいモデルとテレポートを組み合わせてみましょう。 テレポート用のオブジェクトやスクリプトを読み込んでモデルと組み合わせて…… できました!テレポート移動です! ……あられもない姿になってますね? 現在地からテレポート先までモデルが一歩で移動しようとしてるみたいです。 本当はVRChatのテレポートのような、移動先に向かってモデルが移動→自分の視点をモデルの位置までテレポートさせる。みたいなことをしたかったのですがうまくいってません……。 Unityド初心者には少し難しかったみたいです…… 今は代わりにコントローラーのスティックでとことこ歩くようにしておきましょう。 スライド LTなので当然スライドなりの資料をどう表示して送るかを考える必要がありますね。 まず思いつくのはボタンを押すとスライドが切り替わるタイプでしょうか、これでもいいですがVRなのに普通のプレゼンとあまり変わらないものになってしまうのはつまらないですね……。なにか面白い要素を入れたいところです。 ……と、考えてできたのがこちらです。 豪快にめくります。 ここは紙芝居形式にしてみました。インパクト抜群で動きを取り入れることもできる個人的にお気に入りの部分です。めくったスライドがゴミとして右後ろに溜まっていますがこれはこれで味があるのでいいなと思っています。 かわいいとすべて許される。 カメラ Unityの映像をどうやって共有配信するかも考える必要がありますね。 UnityCaputureというのを使えばUnity内のカメラの映像を仮想カメラとして取れそうなのでこれを使っていきましょう。Unity内で配信用カメラを配置してスクリプトを設定します。 映像を取ることができるようになったらあとはOBSなどで受け取れば配信や画面共有なども簡単にできますね。 ついでに、実際の映像が見れると自分の動きも取りやすくなるのでUnity内で自分の位置から見えるように映像を表示しておきましょう。 正面にディスプレイを置いて先程の映像を出すようにしてみました。これで動きの確認や今どのスライドが見えているかも(ミラーになってるけど)わかりやすくなったと思います。 タイマー 移動やスライドの機能ができて最低限LTはできるようになりました。ここからはオマケ便利機能を作っていきます。 社内LTでは5~7分の登壇時間がありますが、HMDを被った状態だと今何分経ったのかというのが分かりません。なので、バーチャル空間の中にタイマーを出してみましょう。 確認モニターの上にタイマーを、手元にスタート/ストップのボタンを置いてみました。 青がタイマースタート/ストップ、赤がタイマーリセットになっています。 しっかり動きはするのですが、ちょっと触れただけで止まったりリセットされたりしてしまう繊細肌になってしまったのは内緒です……。 コメント LT中はSLackが実況チャンネルとして動いているのですが、HMDを被っているとSlackが見れず反応が全くわからないのが少し寂しく感じました。 なんとか反応を見れるようにしたいな〜と思ったのでコメント欄を作ってみました。   ……はい、にせコメント欄です。 Slackの実況チャンネルからコメントを持ってくるのは色々あって難しかったため、流れているのは自分で用意したテンション爆アゲコメントです。LT中に視界に入ると「ふふっ……w」となるので作ってよかったですね。 いつか本物のコメント欄に進化するときがくるかも……? 全体 色々作ってみましたが全体はこのような感じになっています。 スライドの左側を基本立ち位置としています。正面にはタイマーのボタンが、向かい側にはカメラやタイマー、コメント欄などが置いてあるといった感じですね。 そして床には……おもちゃが散らかってます。ときおり投げて遊んだり……。 使ってみてどうだったか VRを使ったLTをいままで2回やったのですが、どちらもとても楽しかったです。見ている人からも好評でした。 オンラインだと難しい身振り手振りもVRであればできますし、そもそもこんなにかわいい姿でLTができるのに楽しくないわけがないですね!! 今はまだスライドをめくるぐらいしかVR特有の動きがありませんが、他にもサービスアイコンをならべて動かしてリアルタイムで構成図を変えて説明するみたいな事もできたら面白そうですし、いろいろな可能性がありそうです。 最後に というわけでVRでLTをしたときのお話をさせていただきました。コード実装なんかの話はできませんでしたが、この記事でVR LTに興味を持っていただけたら幸いです。 ちなみにこのVRLTの今後ですが、実は「HaritoraX ワイヤレス」というフルトラッキング機材を購入しました。なので、次回またLTをするときはフルトラッキングで動けるようにした状態でやりたいですね!フルトラッキングで動くのも楽しみです! クレジット LT、およびブログの執筆においてこちらのモデルを使わせていただきました。 オリジナル3Dモデル「ミーシェ」 – ポンデロニウム研究所 オリジナル3Dモデル「桔梗」 – ポンデロニウム研究所 We are hiring! ニフティでは、さまざまなプロダクトへ挑戦するエンジニアを絶賛募集中です! ご興味のある方は以下の採用サイトよりお気軽にご連絡ください! ニフティ株式会社採用情報 カジュアル面談も受け付けています! カジュアル面談 Tech TalkやMeetUpも開催しております! こちらもお気軽にご応募ください! Event – NIFTY engineering ニフティ株式会社 – connpass
アバター