6 ** 5

軽率なアウトプットを心がけます

CA Tech Missionに参加した話

こんにちは、ふねらるです。

1月から3月の3ヶ月間でCyberAgentのCA Tech Missionというインターンに参加してきました。

CA Tech Missionとは

www.cyberagent.co.jp

公式サイトの説明によると、以下のように説明されています。

CA Tech Missionでは、サイバーエージェントの各事業部が有する課題に挑戦していただきます。 経験豊富なエンジニアがメンターとなり、 約3ヶ月かけて難易度の高いMissionに挑戦することで、 今まで経験したことのない技術的成長を実感していただけます。

応募フローとしては、会社側がいくつかのミッションを提示していて、取り組みたいミッションに応募するといった感じでした。ミッションは ①DP室: 継続的デリバリーシステム「PipeCD」での業務でのフルタイムOSS開発、②DP室: フィーチャーフラグ・ABテストシステム「Bucketeer」におけるフルタイムOSS開発、③アドテクプロダクトの課題解決、④Unity製の大規模ゲームの開発効率を向上させるためのツールをOSSとして開発・公開の4つがありました。

自分は ①DP室: 継続的デリバリーシステム「PipeCD」での業務でのフルタイムOSS開発に応募しました。 理由としては、セキュリティミニキャンプでCloud Native Securityについての講義を受けたり、大学のPBLでArgo CDを使って運用してみたりとCloud Nativeな技術に魅力を感じていたからです。また、OSS開発にも興味があり、PipeCDがOSSだったのも理由の一つです。

給与についてですが、CA Tech Missionでは時給が3500円とかなり高い給与をいただけました。

PipeCDとは

pipecd.dev

A GitOps style continuous delivery platform that provides consistent deployment and operations experience for any applications

PipeCDとは「あらゆるアプリケーションに一貫したデプロイと運用体験を提供するGitOps型の継続的デリバリープラットフォーム」です。

類似サービスとしてArgo CDやFlux CDなどが挙げられます。

PipeCDの強みとして、PipeCDはKubernetes, Google Cloud Run, Terraform...といったいくつものプラットフォームについてサポートしている点があります。

インターン内容

基本的にはPipeCDのIssuesからやりたいIssueややってほしいと言われたIssueに取り組んでいくという感じでした。

自分が取り組んだメインのタスクはドリフト検知に関する機能で、Terraformのドリフト検知機能の追加、ドリフト検知の詳細の表示方法の変更、ドリフト検知を指定したフィールドについて無視するといったタスクに取り組みました。

ドリフト検知関連の他にも、pipectlのコマンドの機能をいくつか追加したり、Pipedでアプリケーションのリストをフィルタリングできるようにするなどのタスクにも取り組みました。

ドリフト検知とは

pipecd.dev ドリフト検知とはプラットフォーム上で実際に動いている状態とGitで定義されている状態を比較して、一致しているかどうか、もし異なる部分があればそれを表示するといった機能です。

PipeCDはGitOps型のCDツールなので、Gitを信頼でききる唯一の情報源として使用しています。そのため、実際に動いている状態とGitで定義している状態が異なることを検知することにモチベーションがありました。

ドリフト検知の表示の変更について

今回のインターンで様々なタスクに取り掛かりましたが、その中でも印象的だったタスクがドリフト検知の表示の変更でした。

PipeCDはドリフト検知にlive state(実際に動いているもの)のmanifestとGitで定義されたmanifestの両方を持っていて、2つのmanifestの差分を取ることでドリフト検知を行っています。

ドリフト検知の表示の変更で行ったことを端的にいうと、live stateのmanifestとGitのmanifestの差分を取る順番を逆にするといったものでした。

(引用: Configuration drift detection | PipeCD)

変更前は上の写真のように、Gitのmanifestの内容が-になっていて、live stateのmanifestの内容が+になっていますが、Gitの情報が正しいはずなのに、-で赤く表示されていてsyncボタンを押しにくいなど、UIがあまり良くなかったという問題がありました。

この機能の実装には差分を取る順番を入れ替えるだけなので、一見簡単に見えるのですが、実はlive stateのmanifestはPipeCDで管理するためのannotationがついており、差分を取る関数の中でannotationを無視する処理がなされていたので、単に引数の順序を入れ替えるだけでは十分ではなく、その部分も修正する必要がありました。

意識したこと

今回のインターンで意識したこととして、機能の追加を行う際にできるだけ実装の変更を少なくする、構造をできるだけシンプルにする、プログラムの構成要素の依存性が少なくなるようにするといったことを心がけました。

ただ、構造上それをすることが難しい部分などもありました。それを解決するために既存の実装を置き換えたり、リファクタリングをしたりしたくなりましたが、プロダクトの規模が大きいので簡単に実装の置き換えをすることは難しいという学びがありました。

こういった問題の解決策はインターン中に見つけることができなかったので、こういった問題の解決策を探っていくことが今後の課題の一つだなと思いました。

反省点

早くタスクをこなして進捗をたくさん生みたい、いろんなタスクに取り組みたいという気持ちが先行してしまって、一つ一つのタスクの品質を下げてしまいました。

例えば、masterブランチにマージされてから実装が十分でないことに気づくことがそこそこありましたし、新しいバージョンがリリースされてから自分の実装した機能のバグに気づいたこともありました。

感想

3ヶ月フルタイムとかで働いていると、最後の1,2週は結構マンネリ化してきてモチベーションも最初に比べ下がっていました。実際に働いたら3ヶ月どころか何年も続いていくだろうので、モチベーションの管理などを工夫していく必要がありそうだなと思いました。

PipeCDチームでは英語を使う機会が結構ありました。例えば、テキストのコミュニケーションでは3ヶ月働いて、半分くらいは英語で行っていました。また、Weeklyミーティングについても最初の数週間は英語で行われていました。(英語でのミーティングはあまりにもついていけなくて、日本語でやるようにしてもらいました)
この経験から英語をもっとできるようになりたいというモチベーションができてとても良かったです。

軽率なアウトプットがしたい

モチベーション

  • 需要を考えない
  • 書きたいことを書く
  • 未来の自分のために書く(忘れていたりするので)
  • フォーマットを考えない
  • 価値がなくてもアウトプットして良いと考える
  • すでに似た内容のアウトプットがあってもアウトプットして良い

内容

  • 興味分野についてまとめる
  • 詰まったこととどうやって解決したか

気をつけること

  • 読み手のことを考えて書く。自分の考えてることがちゃんと伝わってるか吟味しよう とにかく最初はハードルをとことん下げよう
    良いアウトプットの仕方はやっていく内にちょっとずつわかってくるはず

VimでVisual Studio Codeのような括弧補完がしたい

1.

{ + Enterで括弧を補完して改行する

inoremap {<Enter> {}<ESC>i<Enter><ESC>x<S-o>

f:id:fun7776:20210621170238g:plain

2.

次の文字に依存して括弧を補完するかどうか決める

function! BracketComplement(num) abort
    let LList = ["(", "[", "{"]
    let RList = [")", "]", "}"]
    let pos = col(".") - 1
    let str = getline(".")
    let tmpl = pos == 0 ? "" : str[:pos - 1]
    let tmpr = str[pos:]

    let out = ""
    let flg = 0
   "次の文字がOKリストの要素であれば括弧を補完する
    let OK = [' ', '', ')', ']', '}']
    for c in OK
        if tmpr[0] == c
            let flg = 1
        endif
    endfor
    if flg
        let tmpl = tmpl . LList[a:num] . RList[a:num]
    else
        let tmpl = tmpl . LList[a:num]
    endif
    let str = tmpl . tmpr
    call setline('.', str)
    call cursor(line("."), pos+2)
    return out
endfunction

f:id:fun7776:20210621170353g:plain

3.

インサートモード中に閉じ括弧上で閉じ括弧を入力すると括弧から出る。

function! BracketOut(num) abort
    let List = [')', ']', '}']
    let pos = col(".") - 1
    let str = getline(".")
    let tmpl = pos == 0 ? "" : str[:pos - 1]
    let tmpr = str[pos:]
    if str[pos] == List[a:num]
        call cursor(line("."), pos+2)
    else 
        let str = tmpl . List[a:num] . tmpr
        call setline('.', str)
        call cursor(line("."), pos+2)
    endif
    return ''
endfunctio

f:id:fun7776:20210621170514g:plain

4.

2と3の内容をシングルクオーテーション、ダブルクオーテーションにも対応させる。

function! QuotationFunc(num) abort
    let List = ['"', "'"]
    let pos = col(".") - 1
    let str = getline(".")
    let tmpl = pos == 0 ? "" : str[:pos - 1]
    let tmpr = str[pos:]
    if str[pos] == List[a:num]
        call cursor(line("."), pos+2)
    else 
        let flg = 0
       "次の文字がOKリストの要素であれば括弧を補完する
        let OK = [' ', '', ')', ']', '}']
        for c in OK
            if tmpr[0] == c
                let flg = 1
            endif
        endfor
        if flg
            let tmpl = tmpl . List[a:num] . List[a:num]
        else
            let tmpl = tmpl . List[a:num]
        endif
        let str = tmpl . tmpr
        call setline('.', str)
        call cursor(line("."), pos+2)
    endif
    return ""
endfunction

f:id:fun7776:20210621170701g:plain

5.

隣接した括弧の開き記号を消すと同時に閉じ記号も削除する

function! DeleteParenthesesAdjoin() abort
    let pos = col(".") - 1
    let str = getline(".")
    let parentLList = ["(", "[", "{", "\'", "\""]
    let parentRList = [")", "]", "}", "\'", "\""]
    let cnt = 0

    let output = ""

   "カーソルが行末の場合
    if pos == strlen(str)
        return "\b"
    endif
    for c in parentLList
       "カーソルの左右が同種の括弧
        if str[pos-1] == c && str[pos] == parentRList[cnt]
            call cursor(line("."), pos + 2)
            let output = "\b"
            break
        endif
        let cnt += 1
    endfor
    return output."\b"
endfunction

引用:Vimで隣接した括弧の開き記号を消すと同時に閉じ記号も削除するスクリプト - Qiita f:id:fun7776:20210621170619g:plain

これらの関数を文字に割り当てる(これがないと動きません)

inoremap <silent> ( <C-r>=BracketComplement(0)<CR>
inoremap <silent> [ <C-r>=BracketComplement(1)<CR>
inoremap <silent> { <C-r>=BracketComplement(2)<CR>
inoremap <silent> ) <C-r>=BracketOut(0)<CR>
inoremap <silent> ] <C-r>=BracketOut(1)<CR>
inoremap <silent> } <C-r>=BracketOut(2)<CR>
inoremap <silent> " <C-r>=QuotationFunc(0)<CR>
inoremap <silent> ' <C-r>=QuotationFunc(1)<CR>
inoremap <silent> <BS> <C-r>=DeleteParenthesesAdjoin()<CR>

参考

Vimで隣接した括弧の開き記号を消すと同時に閉じ記号も削除するスクリプト - Qiita