hamburger

主に日記

GitHub Actionsでissueの自動登録

todoやらtimesやらをプライベートリポジトリのissueで管理するようになって、そうなると毎日使うissueは自動で作成するようにしたくなった

調べてみたらワークフローが公開されていたので、ちょっと工夫しながら使ってみた

Actionsの登録

create-an-issue というワークフローを使い、日時でissueを登録するようにした

github.com

以下のようなテイストのファイルをcommitする

name: Create a routine issue on every day

on:
  schedule:
  - cron: '0 21 * * *' #JSTで6時に実行

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2 # テンプレートを使用する場合は、リポジトリをチェックアウトする
    - uses: JasonEtco/create-an-issue@v2
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # このsecretsはデフォルトのもの
      with:
        filename: .github/ISSUE_TEMPLATE/templete.md # 自身のテンプレートファイル

ちなみに先にテンプレートファイルを登録しておいたほうが手順的には正しいが、のちの説明の都合上こちらを先に説明した。

テンプレートの登録

基本的には通常のテンプレートと同じフォーマット

---
name: templete name
about: for times
title: "[times] {{ date | date('add', 1, 'days') | date('YYYY/MM/DD') }}"
labels: "times"
assignees: assignees name
---

一つ注意点があって、このワークフローではテンプレート内でdate変数を利用できるが、それがUCTのtimezoneなので日本で使おうとするとずれてしまう。

僕の場合、朝の6時に実行したかったのでそうすると現地時間では日付が1日前になる。

それを回避するためにプレースホルダ内で値を書き換えて利用している


上の設定をすれば、毎日指定の時間に指定のフォーマットでissueを登録されるので、あとは適宜編集して活用する。タスク自体軽いので、コレ単体では無料ユーザでも問題ないはず

今のところは順調に稼働してる。

デスク環境を整えた

リモートワーク開始を機に少しずつデスク環境を改善してきたが、ようやく終りが見えてきた。

この半年くらい色んなデスク環境に関するブログを見て参考になったので、自分も晒してみる。

f:id:burgerham:20200927235619j:plain

仕事用PC

MacBook Pro 13inch(2019)。会社支給。

クラムシェルモードで使いたかったので100均で購入したであろうまな板立てを押し入れから出して、それに立てている。pc用のスタンドとかよりも、通気性が良さそう

ディスプレイ

会社支給。下にプライベート用PCを隠したかったので、机上台の上に置いてる。PS4と共有しているので、スイッチを噛ませてHDMIを切り替えられるようにしている

トラックパッド

Apple Magic Trackpad 2 - スペースグレイ

Apple Magic Trackpad 2 - スペースグレイ

  • 発売日: 2018/05/16
  • メディア: Personal Computers

シルバーに比べて少し値がはるが、PCに合わせてグレーを購入した

キーボード

もともと会社の経費で購入してもらったRealforceを使用していたが、矢印キーをまたいで右手でトラックパッドを操作すると怪我した手首が痛くなるので、分離式デビューした。

打鍵感が若干Realforceより劣っていて、macモードにするとF1~10がメディアコントロールになるなど問題はあるものの、痛みは減ったので総合的には満足。

パームレスト

安かったのでマウス用のものを2つ購入した

スマートスピーカー

google home mini。キャンペーンで貰ったが、リビングにはamazon echoがあって使わなかったので普通のbtスピーカーとして使ってる

Google Nest のスマート スピーカーとディスプレイ - Google ストア

スマホスタンド

一応スマホアプリエンジニアなので、開発中はいろんな端末を使う。ぱっと見れるようにしておきたいので、3つスタンドは用意してる。

ライト

かなり昔にビックカメラで購入したもの。明るさを調整できるのと、割としっかりしているので気に入ってる

プライベート用PC

MacBook Pro 15inch(2012)。そろそろ限界なので今年中にはリプレースしたい

ワイヤレスイヤホン

コスパが良いので購入したが、1年前の物なので今はもっと良いものがありそう

デスク

社会人1年目のときにニトリで購入したもの。奥行き60幅120なので比較的大きいものだと思う。丈夫さとサイズ基準で選んだので質感とかはいまいちだけど、使い勝手が良くて重宝してる。もうすぐ10年選手。

実は利用頻度や角が子供に危ないという理由で廃棄予定だったが、捨てる直前でリモートが始まったため再活躍している。コレがなかったらと思うと恐ろしいので、今年の一番の功労者だと思う。

チェア

f:id:burgerham:20200927235632j:plain

www.steelcase.com

リープHD2。オフィスバスターズで4万円位で購入。もともと安い椅子を使ってたときに苦しめられていた腰痛が改善した。買ってほんとに良かった

マイク付きヘッドフォン(とPS4)

f:id:burgerham:20200928003645j:plain

もともと1000円くらいの安いヘッドセットを使っていたが、断線したので購入。週末に友人とFPSやっているので、それも踏まえてゲーム用を購入した。

長時間使うと熱がこもるが、音が拾いやすくなり相手も聞きやすいとのことなので満足。色も黒でゲームっぽさが薄れてるし(謎に光ったりするのは苦手)

フットレスト

椅子とデスクの高さを調整し始めたら足の位置が気になりだして購入した。が、正直なくても良かったかもしれない

ケーブルマネジメント

f:id:burgerham:20200927235644j:plain

見えないところだから良いかなぁと思い、かなり妥協している。100均の入れ物に延長コードを突っ込んで、たれているケーブルは束ねてフックに引っ掛けている

総括

じわじわとデスク周りが改善できたので、ワクワクしながらやれた。これでもうリモートだから生産性が低いと言い訳はできなくなったので、明日からは頑張る。

GitHubでread.meを配置してプロフィールページ作成する

こんな記事を見つけたので、自分も試してみた。

qiita.com

作成方法

自身のアカウント名のpublic repositoryを作成する。 作成すると、画像のようなコメントが表示される。

f:id:burgerham:20200927215117p:plain

訳: あなたは秘密を見つけました! ham-burger / ham-burgerは、GitHubプロファイルにREADME.mdを追加するために使用できる✨特別な✨リポジトリです。 公開されていることを確認し、READMEで初期化して開始します。

コミットすると

作成されたmarkdownファイルがプロフィールページにも表示される

f:id:burgerham:20200927215408p:plain

AndroidでMoboを使う方法

mobo-jp.com

スマホが高スペック化してきた今、ただメモを取りたいくらいのシチュエーションではラップトップを持ち運ぶ必要が無いのでは?と思ったのがきっかけで購入したもの。

もっとちゃんと探せばより良い製品が見つかるかもしれない。ただ、多くの家電量販店で用意されていて、いろんな機能がそれなりの水準で提供されているため強いこだわりがない場合はコレで良いのではと思っている。

それほど高い頻度で使っているわけではないので、いつもネットで初期設定方法を調べている。が、公開されている説明書がPDFダウンロード方式で毎回落とすのもあれなので、よく使うもののみメモしておく

f:id:burgerham:20200927161316j:plain
ケースがデバイスのスタンドになる

https://img.shields.io/badge/Android-11-blue

btペアリング

  1. Fn + q(チャンネル1) or Fn + w (チャンネル2) → 利用チャンネル選択
  2. Fn + x → ペアリングモード
  3. スマホ側をbtペアリングモードにして、MOBOが認識できたら接続対象にする

キーボード設定

入力方法は、Gboard を設定しておけば良い

ひらがな・アルファベット入力の切り替え

左の スタート/ Alt Opt で切り替える

CircleCIの基礎

CIサービスの理解がかなり弱いと感じていたので、早速新刊を読んでみた。3,5,6章に関しては今週中に読み切りたい。

blog.tomoya.dev


以下は自分用まとめ

動作フロー

  • リモートリポジトリのpushトリガーとして、webhookでCircleCIに通知を行う。通知を受けて、CircleCIはジョブを実行する
  • webhookの合間にpushされたcommitがある場合は、それに対応するジョブは実行されない
  • 失敗した場合はリモートリポジトリに通知を行う
    • PRのCIステータスなんかはそれの結果を表示してそう

用語

ビルド

リポジトリのコードを元にアプリを構築すること

プロジェクト

CircleCIから参照されるリポジトリのこと。プロジェクトを追加されて初めてCircleCI側の設定ができるようになる

ステップ

CircleCIで実行される処理の最小単位。その中でもCiecleCI側が用意しているものとユーザが設定するもので分類される。

ジョブ

1つ以上のステップがまとまったもの。ジョブ1つ1つで実行環境が作られ、終了すると環境は破棄される。

Executor

ジョブの実行環境のこと

ワークフロー

複数のジョブをまとまりや実行制御を記載するもの。実行順や並列実行について定義できる

データの永続化

ワークスペース

同じワークフロー間でデータを共有するための仕組み。チェックアウトしたコードを次のワークフローでも利用するときなどに宣言して使う

キャッシュ

異なるワークフロー間でジョブのデータを共有するための仕組み。ワークスペースが1回の処理内で共有する縦の共有だとしたら、キャッシュは異なるタイミングのジョブ間で横の共有をするイメージ。 ダウンロードしたライブラリをそのまま使い続けたいときなどに使うもの。

アーティファクト

ジョブの実行結果を保存するためのもの

FlutterのFreezedで生成するClassにメソッドを追加する

この記事の内容は古くなっています。更新した以下の記事を確認してください。

hamburger-tech.hatenablog.com


Freezedで生成するクラスに、自動生成以外のメソッドを追加する方法について

公式にもちゃんと記載がありました。

pub.dev

@freezed
abstract class Person with _$Person {
  const factory Person(String name, {int age}) = _Person;

  void method() {
    print('hello world');
  }
}

このコードでは、method()が正しく生成されずにエラーになります。

This is because by default, Freezed has no way of "extending" the class and instead "implements" it.

(訳)これは、デフォルトではFreezedにはクラスを「拡張」する方法がなく、代わりにクラスを「実装」しているからです。

なので、abstract classにmixinではなくimplementsするようにしてprivate constructorを追加してあげることで独自メソッドを追加できるようになります

@freezed
abstract class Person implements _$Person { // uses implements instead of with
  const Person._(); // Added constructor
  const factory Person(String name, {int age}) = _Person;

  void method() {
    print('hello world');
  }
}

GitHub ActionsでFlutterリポジトリのCIを設定した

簡単な個人アプリをFlutterで作ってみようと思い、せっかくだからCIの設定もしてみることにしました。

利用したのは検索して一番最初に出てきたflutter-actionで、設定もほぼデフォルトのままです。

github.com

name: CI

on:
  push:
    branches: [ 'master',  'feature/**' ]
  pull_request:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-java@v1
      with:
        java-version: '12.x'
    - uses: subosito/flutter-action@v1
      with:
        flutter-version: '1.17.5'
    - run: flutter pub get
    - run: flutter test
    - run: flutter build apk

CIステータスのバッジも出せます。これだけでREADMEがいい感じになります。

docs.github.com

他サービスとの比較記事がWEB上にたくさんありますが、僕のようにCIに詳しくない人はどれを使えばいいかわからないと思います。

GitHubActionsはワークフローもたくさん公開されていて公式ドキュメントもそれなりに充実しているので、かなり心理的なハードルが低いです。そういう意味で、初めて使ってみるCIサービスとしてはGitHubActionsは良い選択肢になりそうです。

制限などに引っかかってキツくなってきたら、そのときにあらためて別サービスへの移行を検討する予定です。

Macでkeytoolコマンド実行時に No Java runtime present, requesting install. と出力されたときの対応方法

自分の感覚だとそれほど使用しないが定期的に必要になるコマンド、keytool

アプリのフィンガープリントを確認したくて利用しようとしたら表題の通りNo Java runtime present, requesting install.と表示され、"keytool"コマンドラインツールを使用するには、JDKをインストールする必要があります とのメッセージが表示されました。

f:id:burgerham:20200824180718p:plain
`詳しい情報`をタップすると、Oracleのページに飛ぶ

Android Studioを利用している場合はtoolとしてインストールされているので、フルパスを入力することで実行できました

/Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home/bin/keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

Flutterでバックアクションをハンドリングする

FlutterのAddToApp1を業務で利用してるんですが、FlutterEngine内で画面が保持されてしまうのでこまめに初期画面に戻しておかないと別の画面表示時にちらっと前の画面が見えてしまいます(※もしかしたらもっと良い方法があるかもしれない)

こまめに初期画面に戻しておかないと

これをするための手段としてパッと思いつくのが、戻るアクションしたときはHost側の画面スタックと一緒にFlutter側のスタックも消してしまう方法です。

FlutterにはWillPopScopeというものがあって、childにWidgetを指定しておくと戻るアクションしたときにonWillPopが呼ばれるみたいです。

api.flutter.dev

@override
Widget build(BuildContext context) {
    return WillPopScope(
        child: Scaffold(
             // 通常通りWidgetを組む
        ),
        onWillPop: _onWillPop,
    );

  Future<bool> _onWillPop() async {
    // 戻るときに実行したい処理
    return false;
  }

UIに関わることは全てWidgetという感覚が、ここ数日で馴染んできた気がする


  1. 仕事が落ち着いたらちゃんと書きたいトピック

Dartで拡張関数を作成する(extensions methods)

最近Flutterで仕事をしているのですが、定期的にSDK側で提供している既存クラスの拡張をしたくなる時があります。Android(というかKotlin)の場合は拡張関数を定義していたので、その感覚でなにかできないかなと思っていたら、Dartにも拡張関数が実装されていました。

dart2.6から提供されているみたいです。

dart.dev

www.youtube.com

今回は、DateTime型のレシーバを任意のフォーマットに変換してString型で返却する関数を作ってみました。

Dartdatetimeをフォーマットする拡張関数

拡張関数は何でも作れてしまうので責務を意識する必要がありますが、プロジェクトに共通で必要なものはまず作ってみて、必要に応じて固有のクラスを作成していけばよいのではと考えています

MacのAutomatorを利用してちょっとだけ作業を自動化する

僕は仕事の成果やその過程は何かしらの方法で書き残しておいたほうが良いと思っている。それは、紙のメモ帳だったり、ToDoアプリだったり、slackの分報だったり、人によってやり方は様々なはず。

僕も今まで色々試行錯誤しては飽きて辞める、を繰り返してきた

今は一周回って、毎日テキストでtimes用のファイルを作成し、なにか思いついたら書き残すということをやっている。

最新版のテンプレートは以下のような感じ

# Todo
- [ ] 今日やるべきことをまとめる

# Find
- 気づいたことを書く

# Impression
- 一日の感想

# Next Action
- 次にやるべきことをメモしておく

テンプレートを作ったので、あとは毎日コピーしたファイルをリネームし、任意のディレクトリに作成するということを、Slackのリマインダーで設定して、それをトリガーに一日の仕事が始まっていた。

が、SWEだったらこのくらいリマインダーじゃなくて自動化だろうとふと思い立ち、調べたところMacAutomatorなる機能があることに気がついた。

本当はRubyをローカルでcronして動かすくらいしたかったが、意外と使えるソフトで今の所不満がない。他の人からしたら常識なのだろうか?

一応設定方法とスクリプトを残しておく

設定ファイル作成

  • Automatorというアプリを開き、アプリケーションを選択する

f:id:burgerham:20200731120641p:plain

  • アクションから、シェルスクリプトを実行を探して選択する(検索すれば早い)
  • 実行したいスクリプトを書く。今回僕が作ったのはこんな感じ
today=`date "+%Y/%m/%d.md"`
my_dir=`date "+%Y/%m"`
mkdir -p "./Documents/times/${my_dir}" 
cp -n "./Documents/times/template.md" "./Documents/times/${today}"

このスクリプトを実行すると、例えば2020/07/31なら./Documents/times/2020/07/31.md というファイルがコピーされて作られる。階層化されるのは自分の好みの部分が大きい。

定期実行する

  • Macのデフォルトカレンダーでは、指定時刻に任意のファイルを開くことが可能なのでそれを利用する
  • 予定を作成し、通知の設定で開始時刻にファイルを開く様に設定する

f:id:burgerham:20200731121406p:plain

これだけ。

定期実行はカレンダーとAutomatorに任せれば、あとは単発のシェルを書くだけなので調べればなんとかなると思う。自分で能動的に作成したファイルじゃないのでTimesを書き忘れるという弊害はあるものの、自動化でSWEとしての自尊心は満たせたので今の所プラマイゼロかなといったところ。

以上です

Swiftでsnake_caseのJSONをCamelCaseで定義されたStructのパラメータに変換する

使っているExtension

gist.github.com

例えばjson

{
  foo_bar: "baz" # よくあるsnake_case
}

みたいな形式の場合は以下のようにして使う

struct ModelStruct: Codable{
  let fooBar: String // CamelCaseに変換する
}

// dataはAlamofireのresponse
do {
  return try JSONDecoder.commonSettingInstance.decode(ModelStruct.self, from: data)
} catch let error{
  print("error \(error)")
  return nil
}

// 逆に、DataとかStringにしたい場合はEncoderを使う
do {
  let data = try JSONEncoder.commonSettingInstance.encode(self)
  let result = String(data: data, encoding: .utf8)!
  return result
} catch let error{
  print("error \(error)")
  return nil
}

リモートで採用面接をする側になって気づいたこと

最近になって採用面接に関わることが増えてきた。 このご時世なので基本的に面接はZoomを使ったリモート。

多くの人は、対面の面接と違ってリモート面接の経験を積む機会が殆どなかったんじゃないかと思っている。
それ故、リモート環境慣れがあるのと無いのとで差が大きく、面接の印象がかなり変わってくる。

現時点で気になったところをまとめておく

部屋が暗い

  • 別に業務上差し支えなさそうだが、どうしても人格も暗いように見えてしまう

顔がカメラの方を向いていない

  • 対面のときに、目を見て話すべきという話と似ている気がする。これができているかどうかで印象が違う
  • ちなみに、自分も面接中はかなり気をつけているつもり

通信環境が悪い

  • 後述の声が聞こえにくいにも関連するが、Zoomの左下のアイコンがずっと赤い人もいる。
  • 単純にコミュニケーションが取りづらいので、印象が悪い
  • (自分だけかもしれないが)自宅で仕事をするのであればSWEはある程度通信環境も意識すべきだと思う

声が聞こえにくい

  • 通信環境なのかマイクなのか声量なのかはわからないが、致命的
  • 原因が何であれ、音が小さかった人 というくくりになってしまう

リアクションが少ない

  • こちらが説明しているときなど、キャッチボールしている印象があるかないかで結構違う気がする
  • これも、油断すると自分も怪しくなるのでかなり気をつけている

結局上記は面接に限らずリモートで働く上で必要な要素になってくると思っていて、 そこができていないといくら能力が高くてもチームで働けるイメージが湧きづらい
逆に考えると、これができているだけでかなりコミュ力があるかのような錯覚をうけるので、知っていて対策をすればリモート面接はかなり有利になると思う