- 投稿日:2020-04-14T21:29:18+09:00
Git で、トラッキングしていないファイルをまとめて一括で .gitignore に追加する
目的
簡単なプロジェクトで、バージョン管理が必要なファイルが少なく、IDE が吐き出した管理不要なほとんどのファイルを無視したい、といった場合に。
手順
先ずはじめに、バージョン管理が必要なファイルだけ、ファイル名を指定した上で git commit しておきます。
残りは、管理する必要がないファイルなので無視しても良いのですが、git status するたびに出てきてしまうので、.gitignore に入れてしまいたい。でも、手作業でそれをするのは敗北を意味する。
そこで、以下のコマンドを実行します。
git status --porcelain | grep '^??' | cut -c4- >> .gitignore参考
何度かお世話になっているワンライナーですが、どうも毎回 Web 検索に苦労しているような気がするので、検索が容易になりそうなタイトルで投稿しておきます。
元ネタは以下です。
- 投稿日:2020-04-14T16:06:13+09:00
複数のコミットを一括でcherry-pickする
複数の連続したコミットをcherry-pickしたい
コマンド
git cherry-pick {始点となるコミットの1つ前のコミットハッシュ}..{終点となるコミットハッシュ}コミットハッシュを
..
でつなぐことで、間のコミットがcherry-pickされるcherry-pickしたい1つ前のコミットを指定することに注意
始点のコミットハッシュは、cherry-pickの対象に含まれないことに注意。
- commitA
- commitB
- commitC
- commitD
のうちcommitBからcommitDをcherry-pickしたい場合
git cherry-pick {commitA}..{commitD}となることに注意。
git cherry-pick {commitB}..{commitD}としてしまうと、commitCとcommitDのみがcherry-pickされてしまう。
- 投稿日:2020-04-14T15:00:13+09:00
Nuxt.jsで初めて作成したポートフォリオをGitHub Pagesで公開しました
この記事は、「Nuxt.js ってなんですか?」な状態の人間が、やりたいことを盛り込んで作成したポートフォリオについて書いたものです。
作成したポートフォリオ
https://tayuta.github.io/portfolio/
GitHub Pages に公開しています。https://github.com/tayuta/portfolio
ソースコードです。作成に至った動機
ポートフォリオを作成することになったのは、社内でポートフォリオ部(正式名称:そうだポトフを作ろう! 略称:ポトフ)が発足されたことがきっかけです。
もともと業務では、JavaScriptやHTML、CSSなど、フロント系はほとんど触れあったことがなかったので、勉強になるかと思い、入部しました。プロジェクトの作成
ポートフォリオの研究
ポートフォリオが一体どういったものか知らなかったので、ほかの人が作成しているものを片っ端から見あさりました。
また、ポートフォリオの作成だけでなく、自分でレイアウトを考えたりすることも初めてだったので、デザイン手法などについても学習しました。【学習に利用した記事】
全部知ってる?主要なWebデザイン手法のまとめポートフォリオ概要決め
つぎに、どのようなポートフォリオを作るか、なんとなく決めました。
- SPA
- Nuxt.jsで作成する
- テーマは、海の中(最終的には全く違うものができました。←)
- 以下のコンテンツを縦に並べる
- プロフィール
- スキル
- これまで作ったもの(ほぼありませんが...)
- 愛犬について(あまりにコンテンツが少なかったので後から追加)
Nuxt.js プロジェクトの作成
以下の記事を参考に、Nuxt.js プロジェクトを作成しました。
Nuxt.js を導入しよう設定内容が少し変わっていたので、こちらの記事も参考になります。
Nuxt.js の導入 -2.8.1ver-画面が表示できたので、あとは自分がやりたいことを好きなように盛り込みました。
盛り込んだこと
背景に泡をぷかぷかさせる
当初のテーマは海だったので、背景に泡をぷかぷかさせたいと思いました。
導入方法
bubbly-bg.js をポートフォリオに組み込みます。
GitHub : https://github.com/tipsy/bubbly-bg※Nuxt.js の場合、JavaScriptファイルをどこに置いて、どこで読み込めばいいのか分からなかったので有識者に質問したところ、ファイルの内容を mounted にぶち込むように教わったので、そうしました。
※mounted が何なのかはもちろん分からなかったので、以下の記事を読んでなんとなく理解しました。
Vueのライフサイクルを完全に理解した想定通りに動くことを確認した後、?ソースなので、整理をします。
index.vue<template> <section class="container"> <canvas id="bubbly"></canvas> <div class="body"> <!-- 省略 --> </div> </section> </template> <script> export default { mounted() { const canvas = document.getElementById('bubbly') const width = (canvas.width = window.innerWidth) const height = (canvas.height = window.innerHeight) const context = canvas.getContext('2d') context.shadowColor = '#c9ffbf' context.shadowBlur = 4 const gradient = this.setGradient(context, width, height) const bubbles = this.setBubbles(width, height) const draw = () => { requestAnimationFrame(draw) this.anim(context, gradient, bubbles, width, height) } draw() }, methods: { // メソッド内省略 } } </script> <style lang="scss"> #bubbly { position: fixed; z-index: -5; top: 0; left: 0; min-width: 100vw; min-height: 100vh; } </style>以下の記事を参考にしました。
背景のグラデーションや、泡の数・動く速度を変更したい場合も、こちらが参考になります。
【JavaScript】美しい泡が漂う[Beautiful bubbly backgrounds]の使い方背景を斜めにする
背景が斜めだとおしゃれかと思い、背景を斜めにしました。
導入方法
背景を斜めにするためには、要素全体を回転させ、その内側の要素を反対に回転させます。
ただ要素を回転させると、左右に空白ができてしまうため、横幅を大きめに指定します。sample.vue<template> <section class="container"> <div class="contents"> <div class="inner"> コンテンツ </div> </div> </section> </template> <style scoped lang="scss"> .contents { -webkit-transform: rotate(10deg) translate3d(0, 0, 0); transform: rotate(10deg) translate3d(0, 0, 0); background-color: #ffdadf; width: 200%; margin-left: -180px; .inner { -webkit-transform: rotate(-10deg) translate3d(0, 0, 0); transform: rotate(-10deg) translate3d(0, 0, 0); max-width: 50%; margin-left: 157px; } } </style>また、このままでは、背景が横にはみ出てしまい、横スクロールが発生してしまいます。
そのため、はみ出た部分を非表示にする必要があるので、親要素である container に「overflow-x: hidden;」を指定します。sample.vue<style scoped lang="scss"> .container { overflow-x: hidden; } </style>以下の記事を参考にしました。
斜めの背景を作るためのCSSは「回転させて元に戻す」で書く!スクロールにより、要素をふわっと表示させる
要素が画面に表示されてからアニメーションを発火させるために、カスタムスクロールディレクティブを作成しました。
導入方法
まずは、plugins フォルダ内に以下のファイルを作成します。
scroll.jsimport Vue from 'vue' Vue.directive('scroll', { inserted: function(el, binding) { const f = function(evt) { if (binding.value(evt, el)) { window.removeEventListener('scroll', f) } } window.addEventListener('scroll', f) } })nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/scroll'] }mixin.js に handleScroll メソッドを定義します。
mixin.jsexport default { methods: { handleScroll: (evt, el) => { const top = el.getBoundingClientRect().top if (window.scrollY > top + window.pageYOffset - 600) { el.classList.add('isView') return true } return false } } }ふわっと表示させたい要素に、v-scroll ディレクティブを追加し、アニメーションを設定します。
アニメーションを変更することで、ふわっと表示以外にも、横から表示・回転しながら表示などもできるかと思います。sample.vue<template> <div v-scroll="handleScroll" class="fade-in">ふわっと表示</div> </template> <script> import mixin from './mixin' export default { mixins: [mixin] } </script> <style scoped lang="scss"> .fade-in { opacity: 0; } .fade-in.isView { animation-name: fade-in; animation-duration: 2s; animation-timing-function: ease-out; animation-delay: 0.2s; animation-iteration-count: 1; animation-direction: normal; animation-fill-mode: both; } @keyframes fade-in { 0% { opacity: 0; transform: translate3d(0, 20px, 0); } 100% { opacity: 1; transform: translate3d(0, 0, 0); } } </style>以下の記事を参考にしました。
Nuxt.js でスクロールでふわっと要素が出現するやつを「カスタムディレクティブ」で実装するまた、handleScroll メソッドに関しては、sample.vue に記述しても問題ありませんが、私は複数コンポーネントで利用する予定だったので、mixinに記述しました。
mixin については、以下が参考になります。
ミックスインスクロールしながら画面遷移を行う
メニューのリンクをクリックした際に、スクロールしながら指定場所を表示させたいと思い、「vue-scrollto」を導入しました。
導入方法
まずは、プロジェクトディレクトリで下記のコマンドを実行します。
npm i vue-scrolltoその後、plugins フォルダ内に以下のファイルを作成します。
vue-scrollto.jsimport Vue from 'vue' import VueScrollTo from 'vue-scrollto' Vue.use(VueScrollTo, { duration: 700, // スクロール継続時間 easing: [0, 0, 0.1, 1], // 速度の緩急 offset: -70 // 遷移後の位置調整 })nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/vue-scrollto'] }あとは、以下のように、v-scroll-to に遷移先の要素の id を指定することで画面内遷移が可能です。
sample.vue<template> <nuxt-link v-scroll-to="'#bottom'" to>Scroll to bottom</nuxt-link> <div id="bottom">bottom</div> </template>以下の記事を参考にしました。
スクロール継続時間などのオプションについても、こちらが参考になります。
「vue-scrollto」を使ってイージングスクロールを実装する写真をスライダーで表示
コンテンツが少なかったので、愛犬の写真を表示することにしました。
複数の写真を見てもらうため、自動で写真が切り替わるようにしたかったので、実現することができそうな「vue-awesome-swiper」を導入しました。導入方法
まずは、プロジェクトディレクトリで下記のコマンドを実行します。
npm install vue-awesome-swiper --saveその後、plugins フォルダ内に以下のファイルを作成します。
vue-awesome-swiper.jsimport Vue from 'vue' import VueAwesomeSwiper from 'vue-awesome-swiper' import 'swiper/css/swiper.css' Vue.use(VueAwesomeSwiper)nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/vue-awesome-swiper'] }以下のように、スライダーを組み込みます。
sample.vue<template> <swiper :options="swiperOption" ref="mySwiper1"> <swiper-slide v-for="(item, index) in items" :key="index"> <img :src="item.img" alt="..." /> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> <div class="swiper-button-prev" slot="button-prev"></div> <div class="swiper-button-next" slot="button-next"></div> </swiper> </template> <script> export default { data: function() { return { items: [ { img: require('~/static/img_1.jpg') }, { img: require('~/static/img_2.jpg') } ], swiperOption: { autoplay: { delay: 2500, disableOnInteraction: false }, pagination: { el: '.swiper-pagination', clickable: true }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' } } } } } </script> <style scoped lang="scss"> .swiper-container { height: 300px; width: 100%; } .swiper-slide { text-align: center; font-size: 38px; font-weight: 700; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; border-left:1px solid #fff; } </style>以下の記事を参考にしました。
「swiperOption」のその他の設定についても、こちらが参考になります。
モバイルタッチスライダー「vue-awesome-swiper」の使い方注意点
フェードアニメーションと複数カラムスライドは同時に設定できませんでした。
以下の記述の場合、「slidesPerView: 3」の設定が無視されます。sample.vueswiperOption: { effect: 'fade', slidesPerView: 3, ... }パララックス
パララックスを利用しているサイトかっこいい!と思い導入しましたが、どこに使えばいいか分からず、ひっそりと利用しています。
私が今回導入したプラグインは、「vue-prlx」ですが、その他に、「vue-parallax-js」などがあるようです。以下が参考になるかと思います。
nuxt.jsでパララックスをするならvue-parallax-jsがお手軽。Cool!細かい挙動の設定が「vue-prlx」のほうが分かりやすかったので、今回は「vue-prlx」を選択しましたが、気が向いたら「vue-parallax-js」も使ってみようかな、と思っています。(
思っているだけです。)導入方法
まずは、プロジェクトディレクトリで下記のコマンドを実行します。
npm i vue-prlxその後、plugins フォルダ内に以下のファイルを作成します。
vue-prlx.jsimport Vue from 'vue' import VuePrlx from 'vue-prlx' Vue.use(VuePrlx)nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/vue-prlx'] }あとは、パララックス効果を追加したい要素に対して、v-prlx ディレクティブを追加するだけです。
sample.vue<template> <img src="sample.png" alt="" v-prlx> </template>以下の記事を参考にしました。
細かい挙動の設定についても、こちらを参照してください。
vue-prlxを使ってさくっとパララックス体験をしてみるファビコンの作成
私は、「X-Icon Editor」を利用して、作成しました。
簡単なデザインだったので、問題なく作成できました。GitHub Pagesに公開
ポートフォリオなので、ゆくゆくは人目に触れるようにしたいと思い、ひとまず手軽にできると聞いた GitHub Pages に公開することにしました。
公開方法
まず、nuxt.config.js の router の base と favicon のパスにリポジトリ名を記述。
※ router の base を編集することにより、localhostのパスが「localhost:3000/リポジトリ名」になりますnuxt.config.jsexport default { router: { base: '/リポジトリ名/' }, head: { title: pkg.name, meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: pkg.description } ], link: [ { rel: 'icon', type: 'image/x-icon', href: '/リポジトリ名/favicon.ico' } ] }次に、ローカルにgh-pagesブランチを作成し、gitignoreからビルド先フォルダを外します。
# Nuxt generate # distビルドコマンドを実行します。
npm run generatedist フォルダが作成されるので、ローカルのgh-pagesブランチにコミットします。(masterブランチにコミットする必要はありません。)
最後に、以下のコマンドを実行し、dist フォルダのみを gh-pages ブランチに切り離してリポジトリに push します。git subtree push --prefix dist/ origin gh-pagesうまく公開できている場合、GitHub の Setting から公開されたページを確認することができます。
以下の記事を参考にしました。
Nuxt.jsで作ったWebサイトをささっとGithub Pagesに公開する悩んだこと・大変だったこと
無名関数内で this を利用する
無名関数内で、this を利用する際に、以下のように記述していました。
sample.vue<script> export default { data: function() { return { count: 0, } }, methods() { increment: function() { const a = function() { this.count++ } a() } } } </script>この記述では、Vueインスタンスが参照できないため、「Cannot read property 'count' of undefined」というエラーが発生します。
対応方法① this を別の変数に代入しておく
sample.vue<script> export default { data: function() { return { count: 0, } }, methods() { increment: function() { const me = this const a = function() { me.count++ } a() } } } </script>余分に me という変数が出現するため、個人的にはあまり好きではないと思いました。
対応方法② アロー関数を利用する
sample.vue<script> export default { data: function() { return { count: 0, } }, methods() { increment: function() { const a = () => { this.count++ } a() } } } </script>私が実際に採用した方法です。
余分に変数が増えない分、すっきりしました。モバイルルータで画像が表示されない
流行りのコロナウイルスによりテレワークになった際に、会社から支給されたモバイルルータが少し遅めだったこともあり、画像が表示されないという事件が発生しました。
原因は、画像サイズが大きすぎたことでした。対応方法① png ファイルを jpeg ファイルに変更
なんとなく png ファイルにそろえていましたが、容量的には jpeg ファイルの方が良いということを初めて知りました。
今後は、透過画像以外は jpeg ファイル、と心に刻みました。対応方法② 画像サイズを縮小
そもそも、高画質である必要がない画像ばかりだったので、画像サイズを縮小しました。
斜めレイアウトの調整
marginの調整などの際、斜めに移動するため、思い通りにレイアウトできるまでに時間がかかりました。
数学が得意であれば、計算でもう少しスムーズにできたのかもしれないです...これからやりたいこと
- Netlifyで正式にリリース
- それっぽいドメインにできるそうなので、気が向いたら変えたい。
- Lighthouseを使ってチューニング
- 画像サイズ以外にも改善できるところを改善したい。
- 投稿日:2020-04-14T14:27:17+09:00
[備忘録]vimをgitのエディタのdefault設定に
- 投稿日:2020-04-14T13:52:33+09:00
git revertでコンフリクトした記録
エラー
以下のようなエラーが出ました。
revert.sh$ git revert HEAD~4 error: could not revert 54ea783... Adjustment plugin hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git commit'status.sh$git status On branch feature You are currently reverting commit 54ea783. (fix conflicts and run "git revert --continue") (use "git revert --abort" to cancel the revert operation) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: example.php Unmerged paths: (use "git reset HEAD <file>..." to unstage) (use "git add/rm <file>..." as appropriate to mark resolution) Unmerged paths: (use "git reset HEAD <file>..." to unstage) (use "git add/rm <file>..." as appropriate to mark resolution) deleted by them: example2.php both modified: example3.css both modified: example4.css状況
featureブランチを進めていて
ローカルでadd → commit
リモートへ向けてプッシュ
github上でマスターにマージして
ローカルでrevertしようとしたら前述のエラーが出ました。最初心当たりがなく、コンフリクトしている状況というのも?という状態でしたが
よくよく確認してみるとテスト用に作成したtestブランチが残っており
(git branch -D testしたのですがなぜか消えていなかった)
featureで編集していたファイルと被っていて
testブランチはマージされていない状態っぽいことがわかりました。コンフリクト解消
特にphpstorm上でgitの設定をした覚えはないのですが
example.php
example2.php
example3.css
example4.css
この4つのファイルがphpstorm上で赤く表記されており
以下のように変更内容のどちらを残すかという形になっておりました。
phpstormに助けられました。IDE,エディタの設定や選定も重要ですね。example.php<<<<<<< HEAD # featureブランチで行った変更内容 echo "feature"; ======= # testブランチで行った変更内容 echo "test"; >>>>>>> develop今回は以下のようにfeatureブランチの内容を残して上書き保存しました。
example.phpecho "feature";上記ページに従ってともかくコンフリクト解消したものを
add → commit → pushしてみるとエラー自体が解消されたので
revertする必要もなくなりました。原因として予想している事
今回消したはずのtestブランチが残っていて
しかもマージされていない状態があったこと。
featureは独自にコミットを進めてしまっていて
リモートプッシュ、リモートでのプルリクマージまで進んでしまったこと。
これらの状況があってrevertする際に
初めてコンフリクトが起こってしまったのではないかと予想しています。コンフリクトを再現してみました
以下の画像のように2つのブランチが走っていて
枝分かれ部分のコミットをrevertしようとしたところ
前述したコンフリクトが再現できました。againconflict.sh$git revert bfa14cd3f7a3c525b error: could not revert bfa14cd... Added test1230 hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git commit'ただコンフリクトしているファイルtest.htmlを開いてみても
<<<<<<<<<< HEADなどの表記はありませんでした。よく確認してみるとこの時点でtest1230.htmlが生成されただけの状態で
featureブランチ、testブランチ間での差異はない状態でした。add → commitでrevertコミットが生成されました。
コンフリクト再現2
ファイルの差分がある状態を再現できれば
最初のコンフリクトと同じ状態を作れると予想し以下を実行しました。conflict.sh$git revert 8c01b7f7cee4393df596758 error: could not revert 8c01b7f... added text tesst1230.html hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git commit'test1230.htmlを開くと
test1230.htmltest1230 <<<<<<< HEAD added from feature branch added from feature branch2 ======= >>>>>>> parent of 8c01b7f... added text tesst1230.htmlとなっており
test1230.htmltest1230 added from feature branch added from feature branch2として保存しadd → commit したら
無事revertコミットが作成されました。
教訓
コミットを逆にたどるような場合もコンフリクトが発生する。
いらないブランチはすぐに消しておく方が良さそう。
- 投稿日:2020-04-14T12:31:23+09:00
AWS CodePipelineが対応していないgitリポからのCI/CD構築
本記事の対象読者
- AWS CodePipelineに対応していないgitリポから、CodePipelineに乗せたい人
- AWS Lambdaでgitコマンドを使いたい人
CI/CDしたい
とあるAWSプロジェクトで、ソースコード管理にBacklog gitを利用していました。
どうせならCI/CDを組んでしまおうと考えたのですが、AWS PipelineがBacklog gitに対応しておらず。。。そこで、Backlogのwebhookを使ってS3にまでソースコードを連携する以下のようなアーキテクチャ構成としました。
アプリ自体はnuxt.jsで作成しており、buildしてS3にアップロード、静的WEBとして公開することがゴールです。
実装環境
AWS Cloud9
- Serverless Frameworkを利用したので、node.js環境が必要
- Docker環境
API Gateway, Lambdaの構築
Serverless Framworkを利用して作成しました。
Cloud9使うならLambdaデプロイできる機能あるじゃん!!
と言われそうですが、ymlファイル等で管理できる&ソースのgit管理が容易、という点で自分はServerless Frameworkいいな!って思いました。severless.ymlの作成 → Lambdaで使うライブラリの用意 → Lambda関数コード
の順で説明していきます。serverless.ymlの作成
以下がAPI GatewayとLambdaをデプロイするためのserverless.ymlです。
下記サイトを参考にプロジェクトを作成しました。
[2] Serverless Frameworkの使い方まとめserverless.ymlservice: backlog-to-s3 # frameworkVersion: "=1.67.0" plugins: - serverless-kms-secrets provider: name: aws runtime: python3.8 stage: dev region: ap-northeast-1 iamRoleStatements: - Effect: "Allow" Action: - "s3:PutObject" Resource: "arn:aws:s3:::{your_bucket_name}/*" - Effect: "Allow" Action: - KMS:Decrypt Resource: ${self:custom.kmsSecrets.keyArn} custom: kmsSecrets: file: ${file(kms-secrets.${opt:stage, self:provider.stage}.${opt:region, self:provider.region}.yml)} keyArn: 'arn:aws:kms:ap-northeast-1:***************:key/{your_key_id}' functions: git_clone: handler: handler.git_clone memorySize: 128 timeout: 300 events: - http: path: git/push method: post async: true integration: lambda request: parameters: querystrings: payload: true cors: origin: "*" headers: - Content-Type - X-Amz-Date - Authorization - X-Api-Key - X-Amz-Security-Token - X-Amz-User-Agent environment: USER_NAME: git_user_name BUCKET_NAME: your_bucket_name S3_KEY_SUFFIX: your_s3_key/ PASS: ${self:custom.kmsSecrets.file.secrets.GIT_PASSWORD}
plugins
serverless-kms-secretsを利用して、後述するgitのパスワードを暗号化しました。
AWS KMSを利用して暗号化・復号化を行っています。provider
ServerlessFrameworkで使うサービス等を指定します。
今回はAWS Lambdaに持たせるサービスロールも含めて指定します。
ここでは、git cloneしたソースコードをS3に配置する権限、KMSを使ってパスワードを復号する権限を付与しています。custom
KMSでパスワードを暗号化すると、暗号化後の値が記載されたymlファイルが作成されます。
ここでは、そのymlファイルを指定してserverless.ymlの中で利用できるように設定しています。
暗号化、復号化は下記サイト参考。
[3] Serverless FrameworkでAWS KMSfunctions
Lambda関数の設定をしていきます。
ServerlessFrameworkで扱う際の関数名を指定します。(実際に作成されるLambda関数名はやや異なります)
eventsの項ではLambdaのキックイベントを指定でき、ここではAPI Gatewayの設定を行っています。
environmentの項では、Lambdaに持たせる環境変数を設定しています。
ポイントとしては、
- events: async
API Gatewayは最大で29秒までしかリスポンスを待ってくれないので、念のため非同期でLambdaをキックするようにしています。- events: cors
Backlog gitのwebhookからAPIが叩かれるため、CORSの設定をしておきます。
- environment: PASS
GIT_PASSWORDというキーで暗号化したパスワードを呼び出しています。Lambdaで使うライブラリの用意
次に、ライブラリを準備します。
gitコマンドを使うために必要なライブラリをそろえるため、下記サイトを参考にDockerイメージからコピーしてきます。
[4] Lambdaでgitコマンドを使う方法詳しくは上記を参考にしていただきたいですが、自分の場合/usr/share/git-coreが不足していてLambda実行時にエラーが発生したため、build.shに追記をしています。
build.sh#!/bin/sh OUTPUT_PATH=${OUTPUT_PATH:-output} yum install -y git cp -a /usr/bin/git ${OUTPUT_PATH} cp -a /usr/libexec/git-core/git-remote-https ${OUTPUT_PATH} cp -a /usr/libexec/git-core/git-remote-http ${OUTPUT_PATH} cp -a /usr/share/git-core ${OUTPUT_PATH}少し怖かったので、一旦別のディレクトリにgitライブラリをコピーしてきたのち、別途ServerlessFrameworkのプロジェクトディレクトリに配置しました。
Lambda関数コード
Lambda関数のコードは以下です。
serverless.ymlのhandlerで指定したメソッドから実行がスタートします。(git_clone)handler.pyimport json import os import subprocess import urllib import boto3 import base64 import shutil import datetime now = datetime.datetime.now() now = now.strftime("%Y%m%d%H%M%S") kms = boto3.client('kms') password = kms.decrypt( CiphertextBlob=base64.b64decode(os.getenv('PASS')) )['Plaintext'].decode('utf-8') # Lambda関数は前回実行時のインスタンスを再度使用する場合があり、ディレクトリ名などがかぶることがあるので対策する tmpdir = "/tmp/" + now os.makedirs(tmpdir) target = tmpdir + "/{your_git_repo_name}" # ユーザー名がメアドだったりすると「@」でバグがでるのでURIエンコードする username = os.environ['USER_NAME'].replace("@","%40") source_bucket = os.environ['BUCKET_NAME'] def zip_files(): print('ソースコードを zip で圧縮します.') try: shutil.make_archive(target, 'zip', target) except Exception as e: print(e) def upload_to_s3(env): print('圧縮したソースコードを s3 にアップロードします.') zip_file_name = target.split('/')[-1] s3_key = env + "-" + os.getenv("S3_KEY_SUFFIX") s3 = boto3.client('s3') try: s3.upload_file(target + '.zip', source_bucket, s3_key + zip_file_name + '.zip') except Exception as e: print(e) def git_clone(event, context): # Backlogのwebhookからブランチ名を取り出す print(event) body = event["body"] branch = body["content"]["ref"].split("/")[-1] # master, developブランチへの変更のみdeployしたかった if branch in ["master","develop"]: print("deploy start") root = os.path.abspath(os.path.join(__file__, "..")) print("root : {}".format(root)) os.environ["HOME"] = "/tmp" os.environ["GIT_TEMPLATE_DIR"] = os.path.join( root, "git-core/templates" ) repo_url = '{your_clone_url_https}' print(repo_url + ' からソースコードを取得します.') parsed_url = urllib.parse.urlparse(repo_url) src = parsed_url.scheme + '://' + username + ':' + password + '@' + parsed_url.netloc + parsed_url.path os.chdir(tmpdir) print("git clone start") subprocess.call([os.path.join(root, "git"),f"--exec-path={root}","clone","--depth","1","--branch", branch, src]) print("git clone end") os.chdir(target) print("branch check") subprocess.call([os.path.join(root, "git"),f"--exec-path={root}","branch","-a"]) zip_files() env = "prd" if branch == "master" else "dev" upload_to_s3(env) # 後処理 os.chdir(root) shutil.rmtree(tmpdir) else: print("not deploy target brach") response = { "statusCode": 200, 'headers':{ "Access-Control-Allow-Origin":"*" } } return responsedevelopとmasterブランチでそれぞれ別々のS3パスにソースコードをアップロードして、発火させるCodePipelineが別になるようにしています。
CodePipelineを2本作成し、それぞれを検証環境、本番環境へのデプロイに対応させています。また、前回実行時と同じインスタンスが使用された時の挙動に注意です。
tmpディレクトリ内のファイル名は気を付けていましたが、カレントディレクトリも同じ状態で引き継がれるようです。。。上記ファイルが準備できたら、Lambda関数をデプロイします。
serverless deploy -v
ここまでで一苦労、、、
でもここからは割と楽だったCodePipeline, CodeBuildの構築
まずは、CodeBuildで利用するbuildspec.ymlを作成します。
このymlファイルでは、build時のコマンドなどを設定します。
buildに必要なパッケージ等がある場合などにも、ここに記載してインストールします。
すこし雑ですが、今回は必要最低限の以下の内容としました。buildspec.ymlversion: 0.2 phases: build: commands: - cd ./{your_nuxt_project_name} - npm install - npm run build finally: - | if [ ${ENVIRONMENT} -eq 'prd' ]; then aws s3 sync --exact-timestamps --delete ./dist/ s3://{your_bucket_for_prd}/ else aws s3 sync --exact-timestamps --delete ./dist/ s3://{your_bucket_for_dev}/ fi - |上記のbuildspec.ymlをリポジトリのルートディレクトリに配置しておきます。
次に、CodePipelineをコンソールから作成します。
↑ ソースコードを配置するS3パスを指定します。
↑ ここで、「プロジェクトを作成する」から新しいCodeBuildプロジェクトを作成します。
↑ サービスロールにはS3へのPUT権限が必要です。
CodePipelineに戻ります。
↑ 環境変数を設定することで、buildspec.yml内で利用できます。
↑ 今回、build, S3へのデプロイをCodeBuildで行うため、デプロイステージはスキップします。以上で構築は完了です!
Backlog gitのmaster, developに変更が加わると本番・検証環境用のS3バケットに自動デプロイされます!まとめ
CodePipelineに対応していないgitリポジトリからもAWSへCI/CDできました!
Circle CI等、外部ツールを使う方法も今後試してみようと思います!参考
[1] Backlog gitからAWS CodePipeline
[2] Serverless Frameworkの使い方まとめ
[3] Serverless FrameworkでAWS KMS
[4] Lambdaでgitコマンドを使う方法
- 投稿日:2020-04-14T10:49:44+09:00
gti cloneでリポジトリの中身だけ取ってくる
普通にgit cloneするとリポジトリ名フォルダが作られる。
中身だけほしいときは[orogin-url]のあとにドットを記述する。$git clone [origin-url] .
- 投稿日:2020-04-14T09:50:39+09:00
git 過去の複数コミットのコメントを修正する
これはなに
過去の複数のコミットのコメントを一斉に修正した際のメモ。
考え方
git rebase を使用して、既存のコミットを新規コミットで置き換える際に、コメントを書き換える。
手順
まず、修正するコミットのハッシュを調査する。
$ git log --first-parent <branch-name>修正したいコミットの、ひとつ前のコミットのハッシュを調べる。
つぎに、git rebase を開始する。
$ git rebase -i <target-hash>指定した hash の次以後が rebase の対象となる。
標準 editor で以下のような編集画面が開く。pick d66d1fc3a feat: define placeholder at patients pick fa93d61e7 feat: define placeholder at groups pick 4a015ad56 wip: rem placeholder pick 73c8ae6a4 feat: add place holder # Rebase d860920d9..73c8ae6a4 onto d860920d9 (4 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented outここで、修正したいコミットの
pick
をedit
に変更し save する。
もし行を消去すると、該当行はコミットから除外されるので注意。
edit
とreword
の違いについて(たしかこんな感じだった)
-edit
は、コミット毎に amend が実行され、コメントを編集する。
-reword
は、対象コミットのすべてのコメントを(同一の内容で)置き換えるそして、
edit
に修正したコミットの編集を開始する。
git commit --amend
を実行する。$ git commit --amendコミットを編集し、save する。
つぎのコミットを編集するため、git rebase --continue
する$ git rebase --continue前述と同様に、
git commit --amend
を実施する。
これをedit
に変更した全コミット分繰り返す。
全コミットに分完了すると、git rebase
の完了となる。$ git rebase --continue Successfully rebased and updated refs/heads/fix/10541_hoge_fuga.つぎに、この変更した branch をリモート(origin)に反映する。
$ git push -f origin <branch-name>-f オプションを付与し、強制的に更新する。