- 投稿日:2020-08-08T21:49:54+09:00
.gitディレクトリを探索(objects編)
普段は覗かない.gitディレクトリ。どういう構造になっているのか、そしてどうやってバージョンを管理しているのか、確認してみました。動きを追っていくと、gitの仕組みが見えてきます。今回は、init~commitまでにobjectsディレクトリがどう変化するかを見てみます。
まずはinit
まずはinitします。
$ git init Initialized empty Git repository in D:/gittest/.git/ $ tree .git .git |-- HEAD |-- config |-- description |-- hooks | |-- applypatch-msg.sample | |-- commit-msg.sample | |-- fsmonitor-watchman.sample | |-- post-update.sample | |-- pre-applypatch.sample | |-- pre-commit.sample | |-- pre-merge-commit.sample | |-- pre-push.sample | |-- pre-rebase.sample | |-- pre-receive.sample | |-- prepare-commit-msg.sample | `-- update.sample |-- info | `-- exclude |-- objects | |-- info | `-- pack `-- refs |-- heads `-- tags 8 directories, 16 filesinitすると、8つのディレクトリと16のファイルが生成されました。objectsの下にはinfo/とpack/のみ存在しています。以降は.git/objects/のみを対象とします。
ファイル作成
2つのファイルを作成して、.gitフォルダの変化を確認します。
$ echo "hello qiita" > file1.txt $ mkdir dir $ echo "hello git" > dir/file2.txt当然、これらのファイルはgit管理下にはないので、.git/objects/に変化はありません。
$ tree .git/objects/ .git/objects/ |-- info `-- pack 2 directories, 0 filesgit add
次にgit addします。
$ git add * $ tree .git/objects/ .git/objects/ |-- 8d | `-- 0e41234f24b6da002d962a26c2495ea16a425f |-- 92 | `-- ca5c8297eb1e13c6039ae6ad11dc03f89057ed |-- info `-- pack 4 directories, 2 filesaddすると、objects/の下に2つのディレクトリ、その下に各1つのファイルが生成されました。git addしたファイルのハッシュ値を確認すると、その正体が分かります。
$ git hash-object file1.txt 92ca5c8297eb1e13c6039ae6ad11dc03f89057ed $ git hash-object dir/file2.txt 8d0e41234f24b6da002d962a26c2495ea16a425f生成されたファイルの中身のハッシュ値を確認すると、先頭2桁をディレクトリ名とし、残り38桁をファイル名としていることが分かりました。objects/直下に大量のファイルが生成され、読み取り速度が低下することを防ぐために、このような設計になっているようです。
次に、git cat-fileコマンドでオブジェクトのタイプと中身を確認します。(なぜか、git cat-file -t 92/ca5c8297eb1e13c6039ae6ad11dc03f89057edとすると、エラーになる)
$ cd .git/objects/ $ git cat-file -t 92ca5c8297eb1e13c6039ae6ad11dc03f89057ed blob $ git cat-file -p 92ca5c8297eb1e13c6039ae6ad11dc03f89057ed hello qiita $ git cat-file -t 8d0e41234f24b6da002d962a26c2495ea16a425f blob $ git cat-file -p 8d0e41234f24b6da002d962a26c2495ea16a425f hello gitどちらもgit addしたファイルのBlobオブジェクトです。つまり、git addされたファイル(の内容)は、objects/にBlobオブジェクトとして格納されます。(圧縮されているため、catでは内容を確認できない)
commit
commitします。どのように.git/objects/が変化するのでしょうか?
$ git commit -m "commit 1" [master (root-commit) 98664b3] commit 1 2 files changed, 2 insertions(+) create mode 100644 dir/file2.txt create mode 100644 file1.txt $ tree .git/objects/ .git/objects/ |-- 46 | `-- 660d479ecbb352fe6139074d4cca2ec9ac2f31 |-- 8d | `-- 0e41234f24b6da002d962a26c2495ea16a425f |-- 92 | `-- ca5c8297eb1e13c6039ae6ad11dc03f89057ed |-- 98 | `-- 664b3fad7883101dafcb8f4891c0f7cc9f4798 |-- f9 | `-- 68a777a91646758326fe23b06633280db6bc02 |-- info `-- pack 7 directories, 5 files46/、98/、f9/が追加されていることが分かります。git cat-fileでそれぞれのオブジェクトタイプと内容を確認します。
$ git cat-file -t 46660d479ecbb352fe6139074d4cca2ec9ac2f31 tree $ git cat-file -p 46660d479ecbb352fe6139074d4cca2ec9ac2f31 040000 tree f968a777a91646758326fe23b06633280db6bc02 dir 100644 blob 92ca5c8297eb1e13c6039ae6ad11dc03f89057ed file1.txt $ git cat-file -t 98664b3fad7883101dafcb8f4891c0f7cc9f4798 commit $ git cat-file -p 98664b3fad7883101dafcb8f4891c0f7cc9f4798 tree 46660d479ecbb352fe6139074d4cca2ec9ac2f31 author XXXX <XXXX@gmail.com> 1596887068 +0900 committer XXXX <XXXX@gmail.com> 1596887068 +0900 commit 1 $ git cat-file -t f968a777a91646758326fe23b06633280db6bc02 tree $ git cat-file -p f968a777a91646758326fe23b06633280db6bc02 100644 blob 8d0e41234f24b6da002d962a26c2495ea16a425f file2.txtそれぞれ、1つのcommitオブジェクトと2つのtreeオブジェクトです。
commitオブジェクトはcommitの内容、およびコミットした対象(treeオブジェクト)が書かれています。
一方、treeオブジェクトはファイルのディレクトリを表しています。再度commit
ファイルを変更して、再度commitしてみます。
ファイル更新
$ echo "hello qiita again" >> file1.txt $ tree .git/objects/ .git/objects/ |-- 46 | `-- 660d479ecbb352fe6139074d4cca2ec9ac2f31 |-- 8d | `-- 0e41234f24b6da002d962a26c2495ea16a425f |-- 92 | `-- ca5c8297eb1e13c6039ae6ad11dc03f89057ed |-- 98 | `-- 664b3fad7883101dafcb8f4891c0f7cc9f4798 |-- f9 | `-- 68a777a91646758326fe23b06633280db6bc02 |-- info `-- pack 7 directories, 5 filesこの時点では、.gitフォルダには変化はありません。オブジェクトは、addして初めて生成されるためです。
git add
$ git add file1.txt $ tree .git/objects/ .git/objects/ |-- 23 | `-- ce4645d730951533cb1b75c03cd7e8b5d9e071 |-- 46 | `-- 660d479ecbb352fe6139074d4cca2ec9ac2f31 |-- 8d | `-- 0e41234f24b6da002d962a26c2495ea16a425f |-- 92 | `-- ca5c8297eb1e13c6039ae6ad11dc03f89057ed |-- 98 | `-- 664b3fad7883101dafcb8f4891c0f7cc9f4798 |-- f9 | `-- 68a777a91646758326fe23b06633280db6bc02 |-- info `-- pack 8 directories, 6 files $ git cat-file -t 23ce4645d730951533cb1b75c03cd7e8b5d9e071 blob $ git cat-file -p 23ce4645d730951533cb1b75c03cd7e8b5d9e071 hello qiita hello qiita again新しいBlobオブジェクトが生成されました。ファイルを更新してaddするたびに、Blobオブジェクトが新規に作成されるようです。
commit
次にcommitします。
$ git commit -m "commit 2" [master e2e5b8a] commit 2 1 file changed, 1 insertion(+) $ tree .git/objects/ .git/objects/ |-- 23 | `-- ce4645d730951533cb1b75c03cd7e8b5d9e071 |-- 36 | `-- b5886d72132ff023c27b2ca783eba3f3759b19 |-- 46 | `-- 660d479ecbb352fe6139074d4cca2ec9ac2f31 |-- 8d | `-- 0e41234f24b6da002d962a26c2495ea16a425f |-- 92 | `-- ca5c8297eb1e13c6039ae6ad11dc03f89057ed |-- 98 | `-- 664b3fad7883101dafcb8f4891c0f7cc9f4798 |-- e2 | `-- e5b8a03da8735003da7e78cefbc84d45e524ce |-- f9 | `-- 68a777a91646758326fe23b06633280db6bc02 |-- info `-- pack 10 directories, 8 files36/、e2/ディレクトリが追加されました。これまでの流れから、これらはtreeオブジェクトとcommitオブジェクトのはずです。確認してみましょう。
$ git cat-file -t 36b5886d72132ff023c27b2ca783eba3f3759b19 tree $ git cat-file -p 36b5886d72132ff023c27b2ca783eba3f3759b19 040000 tree f968a777a91646758326fe23b06633280db6bc02 dir 100644 blob 23ce4645d730951533cb1b75c03cd7e8b5d9e071 file1.txt「23ce46」は、今回のcommitで新しく生成されたBlobオブジェクトです。
$ git cat-file -t e2e5b8a03da8735003da7e78cefbc84d45e524ce commit $ git cat-file -p e2e5b8a03da8735003da7e78cefbc84d45e524ce tree 36b5886d72132ff023c27b2ca783eba3f3759b19 parent 98664b3fad7883101dafcb8f4891c0f7cc9f4798 author XXXX <XXXX@gmail.com> 1596887500 +0900 committer XXXX <XXXX@gmail.com> 1596887500 +0900 commit 2parentが98664bとなっており、これは1回目のcommitのオブジェクトです。
オブジェクトを図示すると、下記の様になります。
まとめ
- initすると、.gitディレクトリおよびいくつかのサブディレクトリとファイルが作成される。
- ファイルをaddすると、.git/objects/にファイルの内容のハッシュ値に基づいてディレクトリとファイル(Blobオブジェクト)が生成される。ディレクトリ名はハッシュ値の先頭2桁、ファイル名は残り38桁となる。
- commitするたびにcommitオブジェクトとtreeオブジェクトが生成される。
- commitオブジェクトはコミットの内容を表す。「parent」に親コミットのオブジェクトが記載され、コミットの親子関係を把握することができる。「tree」はコミット対象のtreeオブジェクトを表す。
- treeオブジェクトはBlobオブジェクトまたは他のtreeオブジェクトを指しており、ディレクトリを表現している。
- 投稿日:2020-08-08T18:09:27+09:00
コピペでつくるGitサーバーとCI/CD環境(Gitea+Jenkins)
はじめに
「いまあるリポジトリからブランチきって進めてくれればいいよ」
よくある会話なんですよね?これって。やりかたが分からずコマンドレベルで教えてもらいました。ずびばぜん。。。
ナウでヤングな開発をしたかったのでGitのべんきょうをしようとおもいました。ついでにテストとかデプロイとかの自動化をしたかったので、環境を構築してみました。
手段の目的化ばんざい!
べろべろーとコピペすると、VPSやらオンプレ環境でGitサーバ+CIツールが使えるようになります。このエントリを読むとできること
- orginizationという組織のrepo-Aリポジトリにpushすると、、、
- GiteaからSlackおよびJenkinsのwebhookをたたく
- Jenkinsではrepo-Aにpushがあったという通知をGiteaプラグインが受ける
- pushされたrepo-AにJenkinsfileがあるかチェックする
- Jenkinsfileがあればそれをもとにpipeline処理を行う
- pipeline処理の結果を判別し
- JenkinsからSlackのwebhookをたたく
ということができる。
「CI/CDする」までは解説できていませんので、「CI/CDができる環境を作る」です(よね?)
この環境を構築したうえで、ちゃんとテスト自動化できるようなコードを書いたりpipeline処理を書いたり、デプロイを自動化するための処理を書いたりすることで、「CI/CDする」んだと思います。本エントリの解説では、組織単位で発生する全イベントでwebhookをたたくようになっているので、
- リポジトリごとに設定したり
- ブランチ毎に設定したり
- マージされた場合だけという設定をしたり
とやっていくと、必要なことができるようになるんではないかとおもいます。
あと、pipeline処理の結果はマークダウン形式で常時確認できるので、リポジトリのREADME.mdに書いておけば、そのリポジトリ(のブランチ)の状態がわかるようになる。
対象機器および環境
検証環境
- CentOS8 (8.2.2004)
- Gitea (1.13.0+dev-389-ge17e3f71f)←記事作成時点のMasterブランチものです
- Jenkins (2.251)
構築パラメータ
私用環境で検証しています。
FQDNやらポート番号やらは、必要に応じて修正してください。
(あとで紹介するコピペコマンドを修正する必要があります)
項目 Gitリポジトリマネージャ CI/CDツール Software Gitea Jenkins Path /opt/gitea /opt/jenkins Port 3000 8080 User gitea gitea FQDN(A) vmnetserv03.prosper2.net vmnetserv03.prosper2.net FQDN(CNAME) gitea.prosper2.net jenkins.prosper2.net また、GiteaとJenkinsを動作させるために、以下のユーザを新規作成します。
適当なユーザがいれば、それを利用してもOKですが、シェルが必要なので、nobodyなどの/sbin/nologin
や/bin/false
ではダメです。
項目 値 ユーザ名 gitea グループ名 gitea Shell /bin/bash Home /opt/gitea 注意事項
すべてHTTPでつくっています。(GitはSSHですけど)
HTTPSでやるなら証明書発行したり、Nginxでsslをかぶせたりしてください。
プライベートPKIを利用するなら、JenkinsがJAVAなのでkeytoolでルートとか中間のCAをトラストストアに追加するか、チェーン済み証明書をNginxに配置するなど工夫してください。作業内容
CentOS8の準備
CentOS8をクリーンインストールしておく。(最小構成でOK)
ESXi6.7にCentOS8を最小構成で構築サーバ構築
さぁ、コピペの時間だ。
あ、コピペコマンドが長くなるのがイヤだったので、
sudo
してません。
すべてroot
で作業してください。事前準備
- タイムゾーンの修正
- SELinuxを無効
- 動作に必要なソフトウェアのインストール
- nginxのサービス登録と起動
- Giteaユーザの追加
timedatectl set-timezone Asia/Tokyo sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config shutdown -r now firewall-cmd --add-service=http --zone=public --permanent firewall-cmd --reload dnf install -y nginx systemctl enable nginx systemctl start nginx useradd --user-group --shell /bin/bash --home-dir /opt/gitea giteaGiteaの構築
- gitのインストール
- 必要なディレクトリを作成
- Giteaのバイナリを取得
- GiteaのServiceファイルを作成し、サービス登録と起動
- Nginx設定ファイルを作成し、サービス再起動
dnf install -y git mkdir -p /opt/gitea/{gitea-repositories,data,custom,log} curl -L https://dl.gitea.io/gitea/master/gitea-master-linux-amd64 -o /opt/gitea/gitea chmod 755 /opt/gitea/gitea chown -R gitea.gitea /opt/gitea cat <<EOF > /usr/lib/systemd/system/gitea.service [Unit] Description=Gitea (Git with a cup of tea) After=syslog.target After=network.target [Service] RestartSec=2s Type=simple User=gitea Group=gitea WorkingDirectory=/opt/gitea/ ExecStart=/opt/gitea/gitea web --config /opt/gitea/custom/conf/app.ini -p 3000 Restart=always Environment=USER=gitea HOME=/opt/gitea GITEA_WORK_DIR=/opt/gitea [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl start gitea systemctl enable gitea cat <<'EOF' > /etc/nginx/conf.d/gitea.conf server { listen 80; server_name gitea.prosper2.net; location / { proxy_pass http://127.0.0.1:3000; } } EOF systemctl restart nginxJenkinsの構築
- javaのインストール
- 必要なディレクトリを作成
- Jenkinsのwarファイルを取得し展開
- JenkinsのServiceファイルを作成し、サービス登録と起動
- Nginx設定ファイルを作成し、サービス再起動
dnf install -y java-11-openjdk-devel java-11-openjdk mkdir -p /opt/jenkins/{data,web} /var/log/jenkins curl -L https://updates.jenkins-ci.org/latest/jenkins.war -o /opt/jenkins/jenkins.war cd /opt/jenkins/web jar -xf /opt/jenkins/jenkins.war chown -R gitea.gitea /opt/jenkins /var/log/jenkins cat <<EOF > /usr/lib/systemd/system/jenkins.service [Unit] Description=Jenkins Automation Server After=syslog.target network.target [Service] Type=simple ExecStart=/usr/bin/java -jar /opt/jenkins/jenkins.war --webroot=/opt/jenkins/web --httpPort=8080 --logfile=/var/log/jenkins/jenkins.log User=gitea Restart=always RestartSec=300s Environment="JENKINS_HOME=/opt/jenkins/data" [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl start jenkins systemctl enable jenkins cat <<'EOF' > /etc/nginx/conf.d/jenkins.conf server { listen 80; server_name jenkins.prosper2.net; location / { proxy_set_header Host $host:$server_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Fix the "It appears that your reverse proxy set up is broken" error. proxy_pass http://127.0.0.1:8080; proxy_read_timeout 90; proxy_redirect http://127.0.0.1:8080 jenkins.prosper2.net; # Required for new HTTP-based CLI proxy_http_version 1.1; proxy_request_buffering off; # workaround for https://issues.jenkins-ci.org/browse/JENKINS-45651 add_header 'X-SSH-Endpoint' 'jenkins.prosper2.net:50022' always; } } EOF systemctl restart nginx各サーバの初期設定
Giteaのセットアップとユーザ追加
Giteaに設定したFQDNへブラウザでHTTPでアクセスする(今回の例では http://gitea.prosper2.net/ )
以下のように変更して、画面下部の「Giteaをインストール」をクリック
項目 値 データベースのタイプ SQLite3 SSHサーバーのドメイン gitea.prosper2.net GiteaのベースURL http://gitea.prosper2.net/ インストール後はこんな画面なので、
「アカウントが必要ですか? 今すぐ登録しましょう。」をクリック
組織を作成するので、画面右上の「+」のアイコンから「新しい組織」を選択して、、
Giteaの設定ファイルのチューニング
Giteaの設定ファイルは
/opt/gitea/custom/conf/app.ini
にあります。ここに以下を追加することで、リポジトリ内のファイルやIssueの検索ができるようになります。
/opt/gitea/custom/conf/app.ini----8<----(snip)----8<---- [indexer] ISSUE_INDEXER_TYPE = bleve ISSUE_INDEXER_PATH = indexers/issues.bleve REPO_INDEXER_ENABLED = true REPO_INDEXER_PATH = indexer/repos.bleve UPDATE_BUFFER_LEN = 20 MAX_FILE_SIZE = 1048576 ----8<----(snip)----8<----ここに以下を追加することで、OpenID利用の停止と、ユーザが自由に登録することができなくなります。
(つまり、ユーザを追加するには、最初に作成したユーザで追加するようになります)/opt/gitea/custom/conf/app.ini以下を変更する ----8<----(snip)----8<---- [openid] ;ENABLE_OPENID_SIGNIN = true ;ENABLE_OPENID_SIGNUP = true ENABLE_OPENID_SIGNIN = false ENABLE_OPENID_SIGNUP = false [service] ;DISABLE_REGISTRATION = false DISABLE_REGISTRATION = true ----8<----(snip)----8<----こうしてからGiteaを再起動します。
systemctl restart giteaGiteaに公開鍵を登録
もし自分の秘密鍵を生成していない場合には、
ssh-keygen -t rsa -b 4096
などで生成しておく。# cat ~/.ssh/id_rsa.pub ssh-rsa AAAA(うんちゃらかんちゃら)7iQ== root@vmnetserv01.prosper2.netこれをコピーしておく。
SSH鍵の登録は、画面右上のアイコンから「設定」を選択して、、、
上部メニュのSSH/GPGキーから「キーを追加」を選択して、、、
GiteaにSlackのwebhookを登録する(組織単位)
ここでは特定の組織に対して共通のwebhookを設定します。
Slackアプリ管理画面( https://api.slack.com/apps )の「Create New App」をクリック
アプリ名と自分のワークスペースを選択して「Create App」する
Basic Information → Building Apps for Slack → Add features and functionality → Incoming Webhooks
を選択
作成したては「Off」になっているので、これを「On」にする
スクロールして下部の「Add New Webhook to Workspace」をクリック
Slackアプリから「App」を選択して、giteaがいるか確認する
以下のように追加されたら、curlコマンドをコピペしてターミナルから発行する。
組織のwebhookを設定するので、先ほど作成して「test_org」を表示させ、組織名の横にある歯車マークをクリック
設定メニュの「webhook」から「webhookを追加」の「Slack」をクリック
ターゲットURLに先ほど作成したSlackのURL(curlじゃないほう)を、チャネルにSlackアプリを追加したチャネル(#gitea)を設定し、最下部の「有効」にチェックをいれ、「webhookを追加」します。
(テストなので、すべてのイベント、すべてのブランチとしています)
これで、この組織に関連するイベントはすべてSlackに投稿されることになります。
ためしにリポジトリを作成するので、画面右上のプラスマークから「新しいリポジトリ」を選択
オーナーを「test_org」リポジトリ名を「sample」として作成する。(それ以外は空欄でOK)
これのような気もしますが、closeしてるしなぁ。。。
https://github.com/go-gitea/gitea/issues/9183GiteaにJenkinsのwebhookを登録する
GiteaのイベントをJenkinsに通知するためのwebhookを設定します。Slackのwebhookとだいたい同じです。
組織の設定メニュからwebhookを追加します(webhookの種別は「gitea」を選択します。)
ターゲットURLは http://jenkins.prosper2.net/gitea-webhook/post のように設定し、最下部の「有効」にチェックをいれ、「webhookを追加」します。
(テストなので、すべてのイベント、すべてのブランチとしています)
Jenkinsのセットアップとユーザ追加
Jenkinsに設定したFQDNへブラウザでHTTPでアクセスする(今回の例では http://jenkins.prosper2.net/ )
初期パスワードはJenkinsをインストールしたサーバにあるので、これを入力
# cat /opt/jenkins/data/secrets/initialAdminPassword b2546555f9184c4a8a28266b4cac7628インターネット接続環境があれば、「Install Suggested plugins」を選ぶと勝手によさげなものをダウンロードしてくれる。
「Start Using Jenkins」をクリックすると完了
Jenkinsにプラグインを追加
ひとまず、以下のプラグインを導入しておく
- Gitea
- Global Slack Notifier
- Embeddable Build Status(ビルド状態のバッヂを追加する)
サイドメニュの「Jenkinsの管理」の「プラグインの管理」をクリック
「利用可能」タブを選択してプラグインを検索してインストールする。
こんな感じで Global Slack Notifier と Embeddable Build Status もインストールしておく。
Jenkinsのslackアプリを追加
Slackアプリ管理画面( https://api.slack.com/apps )の画面上部の検索窓に「jenkins」と入力して検索
「Jenkins CI」の部分がリンクになっているので、これをクリック
投稿先は先ほど作成した #gitea とし、「Jenkins CI インテグレーションの追加」をして、画面に従って設定していく。
Step3にある、「チームサブドメイン」と「インテグレーション用トークン認証情報 ID」があとで必要なので、控えておく
「Jenkinsの設定」→「システムの設定」の最下部にSlackがあるので、workspaceとチャネルを入力
(workspaceは先ほどの「チームサブドメイン」もしくは https://[workspace].slack.com/ のworkspaceの部分です)
クレデンシャル情報を追加するために、「追加」→「jenkins」を選択し、
「種類」を「Secret Text」にして、先ほどの「インテグレーション用トークン認証情報 ID」として登録する。
もとの設定画面でクレデンシャル情報を選択して、TestConnectionをクリックする。(成功するとSuccessと表示される)
TestConnectionが成功すると、Slackにはこんな通知がくる。
テストのため、ビルド結果のすべてをSlack通知するため、「Jenkinsの設定」→「システムの設定」の中央付近にGlobal Slack Messagesがのすべての欄にチェックをいれる。
Jenkinsのslackアプリが追加できない場合
なんらかの理由でSlackアプリが導入できない場合には、GiteaのSlack設定したときと同じような、
https://hooks.slack.com/services/(~~なんだかながいやつ~~)
を利用する。「種類」を「Secret Text」にして、
https://hooks.slack.com/services/(~~なんだかながいやつ~~)
の(~~なんだかながいやつ~~)
を登録する。
(スラッシュが入ったディレクトリ構造になってても、そっくりそのまま全部入れる。)
「高度な設定」をクリックして展開する。
「Override url」にhttps://hooks.slack.com/services/(~~なんだかながいやつ~~)
のhttps://hooks.slack.com/services/
を入力する。
もとの設定画面でクレデンシャル情報を選択して、TestConnectionをクリックする。(成功するとSuccessと表示される)
Gitea→Slackの通知とまざってよくわからん状態ですが、緑の部分がJenkins→Slack通知のビルド成功、赤の部分がJenkins→Slack通知のビルド失敗です。
Slackアプリでなくても動作できてますね。
動作確認してみよう
README.mdをpushする
先ほど作成した test_org 配下の sample リポジトリに対して、以下のように
README.md
を作成してcommit -> pushする
Giteaではmermaid.jsが利用できるので、この書式を試してみます。mkdir -p ~/gitea/sample cd ~/gitea/sample git init cat <<'EOF' > README.md # Markdown Rendering ## mermaid.js ```mermaid graph TD; A(stuff)-->B[one]; A-->C[two]; A-->D[three]; ``` EOF git add README.md git commit -m "first commit" git remote add origin gitea@gitea.prosper2.net:test_org/sample.git git push -u origin masterリポジトリのpushを検知してJenkinsで自動ビルドさせる
JenkinsがGiteaにアクセスできるようにGiteaでトークンを発行しておく。
右上メニュの「設定」をクリックして、、、
上部メニュの「アプリケーション」でトークン名を入力して、「トークンを生成」する。
やべぇトークンがゲシュタルト崩壊してきた。
JenkinsにGiteaサーバを登録するので、「Jenkinsの管理」から「システムの設定」を選択
システム設定の中央付近にある「Gitea Servers」にURLを入力し、設定を保存する。
(きちんと認識されれば、Giteaのバージョン名が表示される。)
「Enter an item name」に適当な名称を入力し、「Gitea Organization」を選択してOKをクリック
上部メニュの「Projects」→「Gitea Organization」→「Creadential」→「追加」から先ほど作成したプロジェクト名を選択する
トークン入力画面が表示されるので、「種類」を「Gitea Personal Access Token」にして、先ほどGiteaで生成したトークンを「追加」する
Credentialとして追加したトークンを選択し、「Owner」には対象の組織名を入力する。で、保存。
すると勝手に組織内のリポジトリを走査してくれる。
現時点ではsampleというリポジトリが見つかり、そこにJenkinsfileがない、と言われている。
なので、このリポジトリにJenkinsfileをpushしてやればよい。
cd ~/gitea/sample cat <<'EOF' > Jenkinsfile pipeline { agent any stages { stage('First Stage') { steps { echo "Build pipeline : First Stage" } } } } EOF git add Jenkinsfile git commit -m "add Jenkinsfile" git push -u origin masterすると、Slackに通知がくる
通知はGiteaにpushされたトリガーでGitea→Slackのwebhookがひとつ(のはずだが、また2通きてる。。。)
もうひとつは、GiteaにpushされたトリガーでGitea→Jenkinsのwebhookを叩いた結果、Jenkinsfileが見つかったので、自動的にビルドされ、その結果をJenkins→Slackのwebhookで通知したもの。
Jenkinsのビルド履歴にビルドされたログが表示されるので、右端にあるターミナルアイコンをクリックする。
こんな感じでビルド履歴がみれる。
今回は文字列表示のみなので、ログにその文字列が出力されている。
ビルド状態をGiteaのREADME.mdにバッヂで表示させてみる
画面上部のメニュのネスト表示があり、現在は「#1」のビルド履歴が表示されているが、「master」をクリックして、masterブランチの状態を表示させる。
このときのサイドメニュのEmbeddable Build Statusをクリックすると、、、
こんな感じでいろいろな書き方でバッヂステータスが表現できる。
ので、このなかからMarkdownを見つけて、README.mdに追記してpushしてみよう。
cd ~/gitea/sample vi README.md (以下を先頭に追記) ----8<----(snip)----8<---- [![Build Status](http://jenkins.prosper2.net/job/gitea%20build%20test/job/sample/job/master/badge/icon)](http://jenkins.prosper2.net/job/gitea%20build%20test/job/sample/job/master/) ----8<----(snip)----8<---- git add README.md git commit -m "add Badge Status" git push -u origin master以下のようにJenkinsfileを修正して、ビルドが失敗するようにして、再度pushしてみる。
(echoで文字列を表示させる代わりに、シェルを走らせようとしている。この場合、そんなコマンドは存在しない。)sed -i -e 's/echo/sh/' ./Jenkinsfile git add Jenkinsfile git commit -m "mod Jenkinsfile" git push -u origin masterGiteaのステータスもfailingになっている。このバッヂ部分はJenkinsのビルドログへのリンクになっているので、クリックすると、、、
SlackにはGiteaにpushされた通知と、ビルドが失敗した通知がきている。
さいごに
テストとかデプロイの自動化とか、いろいろやりたいことがありすぎてなんなら自前でたてちまえ。ということで全部を足元においてみました。
AnsibleやDockerでも良かったのですが、クリーンインストール直後でもすぐ使えるように、コピペでまとめました。
それに公式のDockerfileならまだしも、個人が作成したDockerfileとかdocker-composeとかって、実は何してんだかよくわかんないなぁ、と思ったりもしました。ので、危険な処理してないよ。という意味も含めてです。検証をやり直しながら進めたのでスクリーンショットの時系列が一部入れ替わってる部分があります。ごめんなさい。
さて、環境がつくれたので、つぎはテストコードを含めたホントのCIをやるぞぉー。出典
https://docs.gitea.io/en-us/reverse-proxies/
https://wiki.jenkins.io/display/JENKINS/Jenkins+behind+an+nginx+reverse+proxy
https://www.eclipse.org/jetty/documentation/9.4.31.v20200723/startup-unix-service.html
https://gcube.wiki.gcube-system.org/gcube/Gitea/Jenkins:_Setting_up_Webhooks
https://plugins.jenkins.io/slack/
- 投稿日:2020-08-08T15:29:11+09:00
GitHub奮闘記②【手順まとめ】
㊗︎ 初 push
用語に続いて、この勢いで 手順もまとめます。
GitHubのユーザー登録は済ませて下さい。手順
0.最終的に、こんな感じ。
「GitTestProject」というリポジトリ名。
initial Commit
に加えて、追加したCommitが反映されています。1. gitの初期設定?
Gitに「ユーザ名」「メールアドレス」を登録します。
GitHubと同じものを指定しておくのが良いです。以下のコードを元に、ターミナルで設定します。(1行ずつ)
git config --global user.name "ユーザー名"git config --global user.email メールアドレスターミナル ?
Xcode内にターミナルは無いですが、Macに標準インストールされてます。
Finder -> アプリケーション -> ユーティリティ -> ターミナル
2. プロジェクト開始と同時に、リポジトリを作成?
Create Git repository on (My Mac)にチェック。✅
initial Commit
されます。
Commit
= 変更履歴を、ローカルリポジトリに保存すること。✅により、プロジェクト開始と同時にローカルリポジトリが作成され、
そこにソースコードが保存されました。
initial Commit
では、デフォルトのコードしかCommitされません。viewController.swiftimport UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } }補足
Xcodeメニューバーにて、
Source Control > Create Git Repositories...
からでもinitial Commit
出来ますが、リポジトリを「✅」で作成するデメリットは特に無いので、
チェック入れるのが吉。3. リモートリポジトリを作成する。?
Remoteを右クリック > Create "GitTestProject" Remote..
で、Create画面が出ます。createを押すと、「Pushing...」 ぐるぐるLoadingされます。?
ご自身でGitHubにログインして、
リモートレポジトリが作られているか確認してみましょう。
initial Commit
のみがpushされていると思います。
無事、push完了です?4. コード変更後、Xcodeでプッシュする。?
さて、『いつ、誰が、どこに、どのような変更を行ったか』。
バージョン管理がGitの利点です。実際にコードを変更して、Commitして、pushしてみます。
コードいじる。
ViewController.swift
を修正後、Commitします。
今回は以下のコードを追記してみました。ViewController.swiftfunc Log() { print("Hello") }変更したので、Commitする。
ゲームでいう、「セーブ」
- Mのついたファイルを右クリックして、
Source Control > Commit "ViewController.swift"...
(M= Modify: 修正する)- Xcodeメニューバーからでも、出来ます。
Commit完了!
補足
Commit Message欄には、『どのような変更を行ったか』を記載します。
書かないと、Commitを実行できません。
コード変更したので、Xcodeでプッシュする。
Xcodeメニューバーにて、
Source Control > Push...
GitHubを確認。
無事、pushできています✌️変更箇所も分かりやすい。
これで共同開発チームの皆が、コード変更を見ることができます。?おしまい。
参考サイト
Xcodeでgit機能を使う(プロジェクトの作成からgithubにpushするまで)
XcodeからgitとGitHubを使う方法・基本編関連記事
追記予定
- 投稿日:2020-08-08T15:28:42+09:00
GitHub奮闘記①【用語まとめ】
㊗︎ 初 push
先日まで push が出来なかったのですが、
gitの初期設定をしていなかった事が原因でした。
以下のコードを元に、ターミナルで設定します。(1行ずつ)git config --global user.name "ユーザー名"git config --global user.email メールアドレスターミナル ?
Xcode内にターミナルは無いですが、Macに標準インストールされてます。
Finder -> アプリケーション -> ユーティリティ -> ターミナル
用語
「リポジトリ」 (repository)
- ソースコードを管理する単位。
-「保管場所」をカッコ付けて言った表現。
-「ローカル」と「リモート」 がある。
- ローカルリポジトリで作業を行い、その作業内容をリモートリポジトリへpush。
-
今さら聞けない!GitHubの使い方【超初心者向け】「ソースコード」
人間が理解しやすいプログラミング言語を使って、記述されたもの。
プログラムの"元" (source)なので、ソースプログラムとも言われる。
ソースコードをコンパイルして、プログラムが作られる。
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典「バージョン管理」
システムの変更を管理すること。
『いつ、誰が、どこに、どのような変更を行ったか』Webデザイン, Webライターとかにも使われる。
ちょっと、ややこしい用語?
Git と GitHub
-
Git
ソースコードのバージョンを管理するためのシステム。-
GitHub
GitHub社が作ったサービス。Gitに、便利な機能を付け加えた。「Git」
リーナス・トーバルズ氏が開発。
Linux?も開発した、すごい人らしい。
「GitHub」
よく見かける生物。
以下、GitHub共同創業者さんのインタビュー引用。コマンドラインで使うにはGitは最高だったんですが、
オンラインでコードをシェアするのが難しかったのです。他の開発者と、コードをシェアしたかったのです。
GitHubは、週末のサイドプロジェクトとしてスタートしました。push と commit
-
commit
変更履歴を、ローカルリポジトリに保存すること。
-push
ローカルリポジトリ内の変更履歴を、GitHubに送ること。
(=リモートリポジトリ にアップロードすること。)commit → ゲームのセーブ push → セーブデータをサーバに保存commit → メールの下書き保存 push → メールの送信おしまい。
関連記事
追記予定
- 投稿日:2020-08-08T07:40:03+09:00
GitでCommitする粒度について
Gitでバージョン管理をするのはフロントエンド、バックエンドエンジニアだけでなく、インフラエンジニアにもコードを必要がある昨今だが、大規模のプロジェクトでGitを使ったことがなかった。
自分の経験を踏まえてGitでCommitする粒度について残しておく対象読者
- Gitを使ったことない人
- Gitの操作はわかるけど使いどころがわからない人
- 駆け出しエンジニア(笑)
※ 個人の経験にもとづいているので注意。
GithubだろうとGitlabだろうと何でも考え方は同じだろう。
最適なコミットの粒度とは?
結論はずばり私の”粒度は細かれば細かいほど良い”である。
では理由をつらつらと書いていこうと思います。今回はお問い合わせForm機能の追加と言う例を用いて説明しようと思う。
私ならば以下のようなタスクになるだろう。
1.HTMLの作成
2.CSSの作成
3.JavaScriptでValidationを追加
4.サーバサイドのプログラム作成(Ruby、PHP、Pythonなど)戻し作業が楽になる
細かくコミットをすることで
- どこまで動いていたのか?
- どこからバグったのか?
が仕組みでわかるようになり、バグった時の戻しが楽になります。Gitがバージョン管理ツールである以上、これが大きな理由だろう。
上の1〜4の作業を1つのコミットに入れてしまうと、バグってしまった時の切り分けが難しくなる。
特に3、4のプログラムを組見切った後にバグが発生すると、大変なことになります。タスクをサブタスク化して整理しやすくなる。ToDoに落とし込める
コミットを細かくすることでタスクをサブタスク化することになります。
つまりToDoに落とし込めることになります。上の例のJavaScriptのValidationで考えてみましょう。
Validationだけだと、何するのかフワッとしています。
メールアドレスを入力するFormのValidationを行う場合は、
- メールアドレスの形式があっているか?
- 全角文字が入っていない?
- RFCに準拠しているか?
など1つのFormに対してもいくつも実装しなければいけない機能があります。
細かくすることで〇〇の機能を実装する、〇〇と〇〇の機能を結合させると言った具合にタスクをToDoレベルに落とし込むことができます。
これにより、タスクで何をしなければいけないのか?いう作業に時間を使うのではなく、実装にパワーを使うことができます。また上司やクライアントのレポートラインに対して何がどこまで終わっているのか?が明確になります。
誰かに引き継ぎしやすくなる。
タスクをサブタスク化して整理しやすくなる。ToDoに落とし込めると似ていますが、これもメリットです。
どこまで終わって、何をやらなければいけないか整理されていたら、引き継ぎのコストは下がります。
また引き継がれた人は実装だけにパワーを使うので余計な手戻りのリスクが下がります。
自分が忙しくて手が回らなくなっても、誰かに仕事をお願いできるのはメリットだと思います。以上、私が考えるメリットです。何かありましたコメントお願いします。