z/OSにおけるGitの活用(2) - Rocket Git構成

# はじめに
ここではRocket Git for z/OSを利用する上での基本的な構成について見ていきます。

## 関連記事

[z/OSにおけるGitの活用(1) - 概要](https://qiita.com/tomotagwork/items/ea5b1ec89dd8d32c655d)
[z/OSにおけるGitの活用(2) - Rocket Git構成](https://qiita.com/tomotagwork/items/a13c0969f88fe804ebc6)
[z/OSにおけるGitの活用(3) - Git活用例](https://qiita.com/tomotagwork/items/4770b8ba9052463e8a68)

# Rocket Git構成例

## インストール
参考: [Program Directory for Rocket Git for z/OS 1.1.1 (GI13-4387-05)](https://publibfp.dhe.ibm.com/epubs/pdf/i1343875.pdf)

ここではインストール手順の詳細は割愛しますが、他のプロダクトと同様SMP/Eでのインストールが可能です。実体としてはUSS上のファイルシステム上に各種ライブラリーが展開されることになります。

## 環境変数設定
参考: 
[Rocket Software Forum - Using git for z/OS with GitHub](https://community.rocketsoftware.com/forums/forum-home/digestviewer/viewthread?GroupId=79&MID=2509&CommunityKey=1e694975-142d-4f2d-9b52-0e37e225db41&tab=digestviewer)
[DBB - Setting up Git on USS](https://www.ibm.com/docs/en/dbb/2.0.0?topic=SS6T76_2.0.0/setup_git_on_uss.htm)

Gitを使用するシェルで以下の環境変数を有効化します。

```
GIT_ROOT=/usr/lpp/Rocket/rsusr/ported

export GIT_SHELL=$GIT_ROOT/bin/bash
export GIT_EXEC_PATH=$GIT_ROOT/libexec/git-core
export GIT_TEMPLATE_DIR=$GIT_ROOT/share/git-core/templates

export PATH=$GIT_ROOT/bin:$PATH
export MANPATH=$MANPATH:$GIT_ROOT/man
export PERL5LIB=$PERL5LIB:$GIT_ROOT/lib/perl5

# These enable enhanced ASCII support
export _BPXK_AUTOCVT=ALL
export _CEE_RUNOPTS="FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)"
export _TAG_REDIR_ERR=txt
export _TAG_REDIR_IN=txt
export _TAG_REDIR_OUT=txt
```

補足: 

- **GIT_ROOT**: Rocket Gitがインストールされたディレクトリを指定します。
- **_BPXK_AUTOCVT**: ガイドだと`ON`を指定している例がありますが、`ALL`を指定することをおすすめします(`ALL`だとUnicodeもサポートされるため)。

参考: 
[_BPXK environment variables](https://www.ibm.com/docs/en/zos/2.5.0?topic=variables-bpxk-environment)


## Configファイル作成
Gitを使用するユーザーのホームディレクトリ下にGit利用に関する設定を行っておきます。
※.gitconfigファイルはUTF-8で作成し、タグ付けしておくことをおすすめします(Jenkins連携の際に必要)。

.gitconfig設定例:

```[home_dir]/.gitconfig
[user]
        name = USER01
        email = USER01@example.com
[http]
        sslverify = false
[credential]
        helper = cache --timeout=3600
```

補足:

- **http.sslverify=false**: SSL通信時の証明書検査を行わないよう設定
- **credential.helper = chace --timeout=3600**: パスワードを一定時間(3600sec)キャッシュする


参考: [git reference - git-config](https://git-scm.com/docs/git-config#FILES)


## .gitattributes

GitHubなどのリモート・リポジトリでは基本的には各テキスト・データはUTF-8で保持することが一般的だと思われます。一方でz/OS上のローカル・リポジトリ(USS上)では、EBCDICコードページ(ibm-1047など)で保持したい場合が多いと思います。
テキスト・ファイルのエンコーディングは`.gitattributes`ファイルで制御することができます。一般的にはプロジェクトのルートにこのファイルを配置し、そのプロジェクト配下にあるファイルの文字コード属性などを指定します。
取り扱う拡張子ごとに、ローカル・リポジトリ(z/OS USS上)とリモート・リポジトリ(Git Server上)の間でcodepageのマッピングを行う例を以下に示します。

```.gitattributes
# line endings
* text eol=lf

# file encodings
.gitattributes zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
*.cpy zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
*.cbl zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
*.txt zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
*.sh zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
*.jcl zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
*.log zos-working-tree-encoding=ibm-1047 git-encoding=utf-8
```

参考: [git reference - gitattributes](https://git-scm.com/docs/gitattributes)

<font color="red">※注意!</font>
.gitattributesに指定があるファイルの場合、変更/追加したファイルを`git add`(ステージング)する際は、そのファイルのタグ付け、文字コード指定は.gitattributesの指定に合わせる必要があります(不一致の場合git add でエラーになります)。

例えば、上のような.gitattributesの設定の場合、拡張子が`txt`のファイルはIBM-1047の指定をしておく必要があります。

NG例1: テキストとしてタグ付けされていないファイルを`git add`しようとした場合

```
TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > ls -laT build/ | grep prop.txt
- untagged    T=off -rw-r--r--   1 TAGUCHI  SYS1         115 Apr 22 07:49 prop.txt

TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > git add build/prop.txt
fatal: can't add "build/prop.txt": file is untagged, set correct file tag
```

NG例2: .gitattributesとファイルの文字コードが違っているファイルを`git add`しようとした場合
```
TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > ls -laT build/ | grep prop.txt
t IBM-1399    T=on  -rw-r--r--   1 TAGUCHI  SYS1         115 Apr 22 07:49 prop.txt

TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > git add build/prop.txt
fatal: can't add "build/prop.txt": file tag (IBM-1399) does not match its attributes (IBM-1047)
```

OK例: .gitattributesとファイルの文字コードを合わせて`git add`を実行
```
TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > chtag -tc IBM-1047 build/prop.txt
TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > ls -laT build/ | grep prop.txt
t IBM-1047    T=on  -rw-r--r--   1 TAGUCHI  SYS1         115 Apr 22 07:49 prop.txt

TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > git add build/prop.txt
TAGUCHI : /u/TAGUCHI/ISEConf2023_MySample01 : > git status
On branch wazi_test01
Your branch is up to date with 'origin/wazi_test01'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   build/prop.txt
```

## CA証明書の設定

GitHubのリポジトリをクローンしようとすると、以下のようなエラーが出る場合があります。

```
$ git clone https://github.com/xxx/xxx.git
Cloning into 'Lightweight_Command_Utility_on_USS'...
fatal: unable to access 'https://github.com/xxx/xxx.git/': error setting certificate verify locations:  CAfile: /opt/anaconda1anaconda2anaconda3/bin/ca-bundle.crt CApath: none
```

これは、HTTPS通信を行う際のGitHub側のサーバー証明書のチェックで信頼できるCA証明書が設定されていないことに起因するものです。先の設定例のように `.gitconfig` にて `http.sslverify`をfalseにするとチェックがされないのでエラーは回避できます。ただし、証明書の信頼性を真っ当にチェックしたいのであれば、ルート証明書を信頼できるものとして登録しておく必要があります。
例えば以下のような設定を行うことで証明書のチェックを正しく行わせることができます。

### (1) 証明書チェーンの入手
手っ取り早いのはブラウザなどから入手する方法です。以下FireFoxでの例です。

Gitサーバー(以下の例ではGitHub)にブラウザからアクセスし、鍵マークをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/b699f552-3b06-57d4-a3dc-3110cfe8154d.png)

プルダウンメニューから"安全な接続"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/0ca997b1-3dcd-00fa-1b89-d8ecf98c5bf9.png)

"詳細を表示"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/e90eef49-115b-aa93-8f1b-1e3aae99210b.png)

"証明書を表示"ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/fb24d762-1b10-1742-28e9-1516c5673b47.png)

PEM(チェーン)をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/d6fb1320-8a72-ab39-38ed-3804118972fc.png)

適当なディレクトリを指定してファイルを保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/003cdfec-669d-a47f-b7b9-89de1870df80.png)

保存したファイルをテキスト・モードでUSS上の適当なディレクトリに配置します。

### (2) CA証明書ファイルの指定

.gitconfigにて、`http.sslverify = false`の代わりに以下のように`http.sslCAInfo`パラメーターで上で取得したpemファイルを指定します。

```.gitconfig
...
[http]
        proxy = socks5h://127.0.0.1:9901
        sslCAInfo = /u/cics004/Git/github-com-chain.pem
...
```

これで証明書のチェックが正しく行われてエラーが回避されるはずです。


## Proxy構成例

z/OSは開発環境であってもセキュアなネットワーク上に配置されていることもあり、ネットワーク構成上外部との接続が難しい場合もあります。例えば特定のポートのみ外部からの接続は受付けるが、z/OSから外部へのコネクションは制限されている、というようなケースはあるかと思います。

GitServerに接続可能なLinuxマシンをSSHトンネリングと合わせ技でProxyとして設定する例を紹介します。

Gitクライアントを使用したいz/OSと、インターネット上のGitHubの両方に接続可能なLinuxマシンがある想定です。また、z/OS上にはSSHDが構成されておりLinuxマシンからSSH接続かつポートフォワードが可能な状態を想定します。このような環境でLinuxマシンをProxyとしてz/OS上のGitクライアントから外部のGitHubにアクセスする構成をしてみます。
イメージとしては以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/3f5c931f-f70e-12c8-d264-cbc5b1727389.png)
Proxyとして使用するLinux上ではSSHクライアントが使えればOKです。他に追加で必要なコンポーネントは特にありません。
Linuxからz/OSに対して以下のsshコマンドを発行してポートフォワードの設定を行います。

```sh:ssh_proxy.sh
#!/bin/bash

export proxyPort=9901
export sshUser=user01
export sshAddress=zos01

ssh -f -N -R ${proxyPort} -o "StrictHostKeyChecking no" -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3" ${sshUser}@${sshAddress}
```

補足:

- **proxyPort**: z/OS側でListenするポート番号(任意)
- **sshUser**: SSH接続する際に使用するユーザー
- **sshAddress**: SSH接続する際の宛先(z/OS側)アドレス

このスクリプトを実行することで、Linuxからz/OSにSSH接続が行われ、9901番ポートがz/OS側でListenされます(9901番ポートへのリクエストがProxy経由で外部アクセスできるようになります)。

z/OS上のGitの構成として、.gitconfigで以下のようにProxyを設定します。ポート番号は上で指定したポート番号(proxyPort)に合わせる必要があります。

```.gitconfig
...
[http]
        proxy = socks5h://127.0.0.1:9901
...
```

これでgitの操作を行うとProxy経由でGit Serverにアクセスできるようになります。

<br/>
<font color="red">
※技術的にはこのような構成もできます、ということですが、セキュリティー・ポリシーとして許されるかどうかは環境によりますのでご注意ください。
</font>


# Gitコマンドメモ

Local Repository初期化

```
git init
```

Local Repositoryステータス確認

```
git status
```

Remote Repositoryの情報追加

```
git remote add origin https://github.com/xxxx/xxx.git
```

Remote Repositoryの情報確認

```
git remote -v
```

ブランチ名をmainに変更

```
git branch -M main
```

ブランチ作成&切り替え

```
git checkout -b new_branch
```

ブランチ情報確認

```
git branch
```

クローン作製 (Remote Repository => Local Repository)

```
git clone https://github.com/xxxx/xxx.git
```

リモート・リポジトリの変更情報取り込み

```
git pull origin main
```

全変更をステージング

```
git add .
```

ステージングされた変更をコミット

```
git commit -m "comment"
```

変更内容をRemote Repositoryに反映

```
git push origin main
```