オンプレGitLabでgit+CI+npmサーバー2024 の変更点

更新


#author("2024-09-08T05:25:56+00:00","default:administrator","administrator")
#author("2024-09-08T05:33:23+00:00","default:administrator","administrator")
[[プログラミング/svelte]]

* 自前サーバーで GitLab を動かしてプライベートな npm プロジェクトなどを置きたい [#p3da9108]

GitLab は、

- GitHub のように使える git 利用開発支援機能
- テストやビルドやデプロイを自動化する CI サーバー機能
- npm パッケージサーバー機能

など、さまざまな機能を兼ね備えるフリーソフト。

自前のサーバーにインストールして動かせる。

GitLab を動かすには 4GB 以上のメモリが必要で、しばらく前だと二の足を踏んでいたのだけれど今なら軽いはず。

Docker を使ってサクッと動かす。(動かせるといいな)

今のところ、

- docker で GitLab を動かす
- ホストの apache2 をプロキシサーバーとして外からの接続を docker との間で中継する
- docker で GitLab Runner を動かす
- GitLab に Runner を登録する(shell モード)
- CI/CD で成果物を .zip としてダウンロード可能にする

ところまで基本を押さえることができました。

- GitLab に Runner を登録する(docker モード)
- GitLab の npm パッケージサーバーへパッケージを Deploy する

はこれからです。

** 目次 [#xea030b5]

#contents
* GitLab サーバーを docker compose で動かす [#bf994d2a]

https://gitlab-docs.creationline.com/ee/install/docker.html#install-gitlab-using-docker-compose

を見ながら docker イメージで動作するよう設定する。

- ホストサーバーには docker 環境があって、自分が管理者である
-- gitlab は docker 内で動かす
- ホストサーバーには apache2 が https://myserver.com/ への通信を受け付ける状況になっている
- https://myserver.com/gitlab/ というアドレスへの通信を docker 内の gitlab サーバーへ繋ぐ

という形で GitLab を動かします。

 LANG:console
 $ cd ~
 $ mkdir gitlab
 $ cd gitlab
 $ echo GITLAB_HOME=`pwd` > .env
 $ cat <<"EOS" > docker-compose.yml
 services:
   web:
     image: 'gitlab/gitlab-ce:latest'
     restart: always
     environment:
       GITLAB_OMNIBUS_CONFIG: |
         external_url 'https://myserver.com/gitlab'
         nginx['listen_port'] = 80
         nginx['listen_https'] = false
         gitlab_rails['gitlab_shell_ssh_port'] = 2224
     ports:
       - '8980:80'
     volumes:
       - '$GITLAB_HOME/etc:/etc/gitlab'
       - '$GITLAB_HOME/log:/var/log/gitlab'
       - '$GITLAB_HOME/data:/var/opt/gitlab'
     shm_size: '256m'
 EOS
 $ docker compose up -d
 [+] Running 10/10
  ✔ web Pulled                               58.2s 
    ✔ 857cc8cb19c0 Pull complete              2.1s 
    ✔ 28812802a434 Pull complete              2.1s 
    ✔ 54e2e989e54c Pull complete              3.0s 
    ✔ abb7892b26dc Pull complete              3.0s 
    ✔ e9d667f5a8c1 Pull complete              3.0s 
    ✔ a8891519352d Pull complete              3.1s 
    ✔ 8b624a00a604 Pull complete              3.1s 
    ✔ 0cf3370d74b6 Pull complete              3.1s 
    ✔ 3253094bd895 Pull complete             55.9s 
 [+] Running 2/2
  ✔ Network gitlab_default  Created           0.0s 
  ✔ Container gitlab-web-1  Started           0.7s 

これで docker 内で GitLab サーバーが立ち上がる。

** 全体としての注意 [#o2bf1916]

上記のようにして動かすと、etc/ フォルダに etc/gitlab.rb というのができて、
これを書き換えれば設定を変えられる。

設定項目についてはこちらに説明がある。~
https://gitlab-docs.creationline.com/omnibus/settings/configuration.html

また、ファイルの冒頭には以下の注意書きがある。

 ## GitLab configuration settings
 ##! This file is generated during initial installation and **is not** modified
 ##! during upgrades.
 ##! Check out the latest version of this file to know about the different
 ##! settings that can be configured, when they were introduced and why:
 ##! https://gitlab.com/gitlab-org/omnibus-gitlab/blame/master/files/gitlab-config-template/gitlab.rb.template
  
 ##! Locally, the complete template corresponding to the installed version can be found at:
 ##! /opt/gitlab/etc/gitlab.rb.template
  
 ##! You can run `gitlab-ctl diff-config` to compare the contents of the current gitlab.rb with
 ##! the gitlab.rb.template from the currently running version.
  
 ##! You can run `gitlab-ctl show-config` to display the configuration that will be generated by
 ##! running `gitlab-ctl reconfigure`
  
 ##! In general, the values specified here should reflect what the default value of the attribute will be.
 ##! There are instances where this behavior is not possible or desired. For example, when providing passwords,
 ##! or connecting to third party services.
 ##! In those instances, we endeavour to provide an example configuration.
  
 ## GitLab URL
 ##! URL on which GitLab will be reachable.
 ##! For more details on configuring external_url see:
 ##! https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab
 ##!
 ##! Note: During installation/upgrades, the value of the environment variable
 ##! EXTERNAL_URL will be used to populate/replace this value.
 ##! On AWS EC2 instances, we also attempt to fetch the public hostname/IP
 ##! address from AWS. For more details, see:
 ##! https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
 # external_url 'GENERATED_EXTERNAL_URL'
  
 ## Roles for multi-instance GitLab
 ##! The default is to have no roles enabled, which results in GitLab running as an all-in-one instance.
 ##! Options:
 ##!   redis_sentinel_role redis_master_role redis_replica_role geo_primary_role geo_secondary_role
 ##!   postgres_role consul_role application_role monitoring_role
 ##! For more details on each role, see:
 ##! https://docs.gitlab.com/omnibus/roles/index.html#roles
 ##!
 # roles ['redis_sentinel_role', 'redis_master_role']
  
 ## Legend
 ##! The following notations at the beginning of each line may be used to
 ##! differentiate between components of this file and to easily select them using
 ##! a regex.
 ##! ## Titles, subtitles etc
 ##! ##! More information - Description, Docs, Links, Issues etc.
 ##! Configuration settings have a single # followed by a single space at the
 ##! beginning; Remove them to enable the setting.
  
 ##! **Configuration settings below are optional.**

一方、例えば data/nginx/conf/gitlab-http.conf に nginx 関連の設定ファイルが見つかるのだけれど、
こちらの設定ファイルはサーバーを立ち上げ直すと gitlab.rb の内容を元に自動的に生成されるものなので、
手で書きかえてはいけない。

ちゃんと冒頭に

 # This file is managed by gitlab-ctl. Manual changes will be
 # erased! To change the contents below, edit /etc/gitlab/gitlab.rb
 # and run `sudo gitlab-ctl reconfigure`.

などと書かれている。

etc/gitlab.rb を書き換えてしまうと設定情報が docker-compose.yml と gitlab.rb とに分かれてしまうので、どちらか一方にまとめた方がいいのかもしれない。

単純な見やすさからすると docker-compose.yml に書く方が良さそうなのだけれど、
gitlab-ctl diff-config を使うなら gitlab.rb でもいいのかもしれない。

docker コンテナの外から確認するなら:

 LANG:console
 $ docker compose exec web gitlab-ctl diff-config


** ポートの指定 [#i42dc48e]

外からの接続を受ける apache2 と同じマシンに置くのであれば docker-compose.yml の

      ports:
        - '8980:80'

のところは

      ports:
        - '127.0.0.1:8980:80'

として、外からの接続が直接 docker へ行かないようにする。

docker でポートを開けると
ufw などのファイアウォールで許可してなくても
外向きにポートが開いてしまうので十分注意する。

** https を名乗りつつ http で待ち受ける [#z2f50ccd]

gitlab の設定で

       GITLAB_OMNIBUS_CONFIG: |
         external_url 'https://myserver.com/gitlab'
         nginx['listen_port'] = 80
         nginx['listen_https'] = false

としている理由は以下の通り。

この docker イメージは external_url の設定を見て、内部の nginx で 80 番で http を待つか、443 番で https を待つかを決めている。

「どちらか片方しか有効にならない」というのが重要な点。

今実現したい構成では、外部から見た gitlab サーバーのアドレスは https://myserver.com/gitlab 
で https 接続になるのだけれど、その暗号化通信は間に入る apache2 が受け持つので
docker 内の nginx への接続は http になる。

external_url を https としてしまうと gitlab docker は nginx を 443 番で https を待つように設定してしまい 80 番の http では繋がらなくなってしまう。

そこで 80 番で http を待つように設定しているのがこの部分だ。

サーバーに繋ぎに行って「接続をリセットされました」みたいになるときは、

 LANG:console
 $ sudo less data/nginx/conf/gitlab-http.conf

として gitlab 関連の nginx の設定を確かめるといい。

(これに気付くのにかなり時間がかかりました・・・)

** GITLAB_OMNIBUS_CONFIG で指定可能なその他の設定 [#d7e481ac]

GITLAB_OMNIBUS_CONFIG では

 LANG:console
 $ sudo less etc/gitlab.rb 

として表示される設定項目に値を指定できるので、
「こんなことできないのかな」と思ったときにはじっくり読むといい。

* apache2 をプロキシサーバーとして接続を中継させる [#g1e47924]

ホストマシンの /etc/apache2/sites-enabled/default-ssl.conf に

 <IfModule mod_proxy.c>
     ProxyRequests Off
     <Proxy *>
         Require all granted
     </Proxy>
 
     AllowEncodedSlashes NoDecode
     <Location /gitlab>
         Order deny,allow
         Allow from all
     </Location>
     RequestHeader set X_FORWARDED_PROTO 'https'
     ProxyPass /gitlab http://localhost:8980/gitlab
     ProxyPassReverse /gitlab http://localhost:8980/gitlab
 </IfModule>

と設定して、

 LANG:console
 $ sudo a2enmod proxy
 $ sudo service apache2 reload

とすることで apache2 がプロキシサーバーとして振る舞い、
https://myserver.com/gitlab 以下へのアクセスを http://localhost:8929/gitlab へ転送してくれる。

ここで重要なのが AllowEncodedSlashes NoDecode だ。

これをしておかないと、後々 GitLab を npm パッケージサーバーとして使おうとした際に、パッケージリポジトリへの PUT が 404 で失敗する。

https://stackoverflow.com/questions/20496963/avoid-nginx-decoding-query-parameters-on-proxy-pass-equivalent-to-allowencodeds

 LANG: console
 $ npm publish    # 他の設定が終わってからの話
 ...
 npm error code E404
 npm error 404 Not Found - PUT https://myserver.com/gitlab/api/v4/projects/1/packages/npm/@myscope%2fmypackage
 npm error 404
 npm error 404  '@myscope/mypackage@0.0.1' is not in this registry.
 npm error 404
 npm error 404 Note that you can also install from a
 npm error 404 tarball, folder, http url, or git url.

のように、npm publish で認証は通過しているのに、そして、アップロードしようとしているのに 404 で落ちるていたらこの設定を見直すといい。



* メールを送れるように設定する [#aa2a5159]

GITLAB_OMNIBUS_CONFIG に

 gitlab_rails['gitlab_email_from'] = 'gitlab@myserver.com'
 gitlab_rails['gitlab_email_display_name'] = 'GitLab'
 gitlab_rails['smtp_enable'] = true
 gitlab_rails['smtp_address'] = "smtp.server"
 gitlab_rails['smtp_port'] = 465
 gitlab_rails['smtp_user_name'] = "smtp user"
 gitlab_rails['smtp_password'] = "smtp password"
 gitlab_rails['smtp_domain'] = "example.com"
 gitlab_rails['smtp_authentication'] = "login"
 gitlab_rails['smtp_enable_starttls_auto'] = true
 gitlab_rails['smtp_tls'] = false
 gitlab_rails['smtp_pool'] = false

あたりを追加する。

設定の仕方はこちらを参照:~
https://gitlab-docs.creationline.com/omnibus/settings/smtp.html

* root でログインする [#u468af48]

初期設定で root という管理者ユーザーが登録されているので、
ウェブサーバーから https://myserver.com/gitlab へアクセスして root でログインする。

管理者 root の初期パスワードは gitlab の docker-compose.yml を作ったフォルダの下の etc フォルダを調べるとわかる。

 LANG:console
 $ sudo cat etc/initial_root_password 

** 普段使いのユーザーを作っておく [#i200c3a4]

この root ユーザーを使って普段使いのユーザー(以下では "myname" とする)を作っておく。


** 自分で変更した root のパスワードを忘れてしまった場合 [#p77da698]

root のパスワードを自分で変更して、その後忘れてしまうと困ったことになる。

そんな時は、

https://blog.k-bushi.com/post/tech/environment/construct-gitlab-runner-docker/#gitlab%E3%81%B8%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3

にあるように、

 LANG:console
 $ docker compose exec web gitlab-rake "gitlab:password:reset"
 Enter username: root
 Enter password: 
 Confirm password: 
 Password successfully updated for user with username root.

とすればパスワードを設定しなおせるらしい。

* GitLab Runner も docker で動かす [#a35f227c]

CI で実際にジョブを実行するサーバーは GitLab Runner と呼ばれる。

同時に使用する人数と比較すると今使っている物理サーバーには余裕があるので、
CI サーバーも同じ物理サーバーで動かしてしまうことにした。

先の docker-compose.yml に以下を追加する。

   runner:
     image: 'gitlab/gitlab-runner:latest'
     restart: unless-stopped
     volumes:
       - '$GITLAB_HOME/runner:/etc/gitlab-runner'
       - /var/run/docker.sock:/var/run/docker.sock
     ports:
       - '8093:8093'

そして、

 LANG:console
 $ sudo docker compose up -d

* Runner を GitLab に追加する [#k5e1dceb]

** GitLab 画面で新しい Runner インスタンスを作成 [#k2bc716a]

https://myserver.com/gitlab/admin/runners

から右上の [New Instance Runner] を押す。

ここでは特別な設定をしないごく一般的な shell の動くサーバーを建てるので、

x Run untagged jobs のチェックを付けて [Create runner] とする。



** docker で動かした Runner と対応付ける [#ka34cbec]

次の画面の Step 1 となっているところで

 $ gitlab-runner register
    --url https://myserver.com/gitlab
    --token glrt-iqghvxb-GLHJG9WsFPT6

のようなところをコピーする。

ちょっと手直しをして次の形にして Runnner を起動した docker-compose.yml のあるフォルダで実行。

 $ docker compose exec runner \
    gitlab-runner register \
        --url https://myserver.com/gitlab \
        --token glrt-iqghvxb-GLHJG9WsFPT6

コマンドを起動するといくつか質問に答えることになる。

- GitLab instance URL には指定した https://myserver.com/gitlab が入っているのでそのまま ENTER
- Enter a name for the runner にはこの Runner を識別する名前を付ける
- Enter an executor には shell を指定

これで Runner 一覧に正しく追加される。

** ERROR: Verifying runner... failed → extra_hosts の設定が必要? [#kde9fa35]

何らかの事情で Runner の docker 内部から myserver.com で apache2 の動くサーバーへ到達できない場合には(LAN 内で ローカル IP を持っている場合など)、

 $ docker compose exec runner \
    gitlab-runner register \
        --url https://myserver.com/gitlab \
        --token glrt-iqghvxb-GLHJG9WsFPT6
                                                    
 Enter the GitLab instance URL (for example, https://gitlab.com/):
 [https://myserver.com/gitlab]: <ENTER>
 
 ERROR: Verifying runner... failed                   runner=yFiGd5DTA status=couldn't execute POST against https://myserver.com/gitlab/api/v4/runners/verify: Post "https://myserver.com/gitlab/api/v4/runners/verify": dial tcp xx.xx.xx.xx:443: connect: connection refused
 PANIC: Failed to verify the runner.            

のように connection refused というエラーが出て失敗する。

このときは docker-compose.yml 内で runner に 

     extra_hosts:
       - myserver.com:192.168.0.2
 
のようなのを追加して https://myserver.com/gitlab でサーバーへ到達できるようにしておく必要がある。

* CI 動作を試してみる [#jb5189f3]

 LANG: console
 $ mkdir ~/gitlab-ci-hello
 $ cd ~/gitlab-ci-hello
 $ cat <<"EOS" > .gitlab-ci.yml 
 build:
   script:
     - echo hello `pwd`
     - ls -la
 EOS
 $ git init
 $ git add .
 $ git commit -m "Initial commit"

として .gitlab-ci.yml だけをコミットした git リポジトリを作成する。

GitLab 上でブランクプロジェクトを作ってそこへコミットしてみる。

https://myserver.com/gitlab/projects/new#blank_project

- Project name: gitlab-ci-hello 
- Project url: https://myserver.com/gitlab/myname/gitlab-ci-hello
- Visibility Level: private
- Project Configuration: README のチェックを外す

そして Create Project

次のページの Push an existing Git repository の手順で push する。

 LANG:console
 $ git remote add origin https://myserver.com/gitlab/myname/gitlab-ci-hello.git
 $ git push --set-upstream origin --all
 Username for 'https://myserver.com': myname
 Password for 'https://myname@myserver.com': xxxxxx
 Enumerating objects: 3, done.
 Counting objects: 100% (3/3), done.
 Delta compression using up to 4 threads
 Compressing objects: 100% (2/2), done.
 Writing objects: 100% (3/3), 266 bytes | 266.00 KiB/s, done.
 Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
 To https://myserver.com/gitlab/myname/gitlab-ci-hello.git
  * [new branch]      master -> master
 branch 'master' set up to track 'origin/master'.
 $ git push --set-upstream origin --tags
 Username for 'https://myserver.com': myname
 Password for 'https://myname@myserver.com': xxxxxx
 Everything up-to-date

push 時には gitlab サーバーのユーザー名とパスワードを聞かれるので入力する。

GitLab の画面で確認すると、

&ref(jobs-success.png,,50%);

こちらのようにコミット番号の隣に緑のチェックマークがついて、
ジョブが成功したことを確認できる。

このチェックをクリックして中を見ると、

 LANG:console
 Running with gitlab-runner 17.3.1 (66269445)
   on myrunnner1 t2X9wkLjw, system ID: r_FoHQflE05Zou
 Preparing the "shell" executor 00:00
 Using Shell (bash) executor...
 Preparing environment 00:00
 Running on 8163caea6de5...
 Getting source from Git repository 00:00
 Fetching changes with git depth set to 20...
 Initialized empty Git repository in /home/gitlab-runner/builds/t2X9wkLjw/0/gitlab/myname/gitlab-ci-hello/.git/
 Created fresh repository.
 Checking out cc71a4d9 as detached HEAD (ref is master)...
 Skipping Git submodules setup
 Executing "step_script" stage of the job script 00:00
 $ echo hello `pwd`
 hello /home/gitlab-runner/builds/t2X9wkLjw/0/gitlab/myname/gitlab-ci-hello
 $ ls -la
 total 16
 drwxrwxr-x 3 gitlab-runner gitlab-runner 4096 Sep  7 13:03 .
 drwxrwxr-x 4 gitlab-runner gitlab-runner 4096 Sep  7 13:03 ..
 drwxrwxr-x 6 gitlab-runner gitlab-runner 4096 Sep  7 13:03 .git
 -rw-rw-r-- 1 gitlab-runner gitlab-runner   53 Sep  7 13:03 .gitlab-ci.yml
 Cleaning up project directory and file based variables 00:00
 Job succeeded

のようにして、

 LANG:console
 $ echo hello `pwd`

と

 LANG:console
 $ ls -la

が正しく実行されていることを確認できる。

ワーキングフォルダが /home/gitlab-runner の下にあることからもわかるとおり、
このシェルは gitlab-runner というユーザー権限で実行される。

そのままでは sudo は使えないので、システムに変更を加えるようなコマンドは実行できない。

Runner の Dockerfile はこちらにある:~
https://hub.docker.com/r/gitlab/gitlab-runner/dockerfile

中身はものすごく古い ubuntu を元にしている?

なんでこんなに古いんだろう???

** CI スクリプトの書き方 [#q6b58aca]

概要:~
https://gitlab-docs.creationline.com/ee/ci/yaml/gitlab_ci_yaml.html

リファレンス:~
https://gitlab-docs.creationline.com/ee/ci/yaml/index.html

用語の整理:
- パイプラインは複数のステージから構成される
- 個々のステージは並列実行可能な複数のジョブから構成される
- 個々のステージは前のステージのジョブがすべて成功してから次へ進む

** node 環境を準備&ビルド&テスト [#d1c57aa0]

例えば、以下の .gitlab_ci.yml と package.json をコミットしてみる。

.gitlab_ci.yml
 variables:
  NODE_VERSION: 22
  NVM_VERSION: v0.40.0
 
 stages:
   - build
   - test
   - package
 
 cache:
   paths:
     - dist/*
 
 # common setting for each job
 default:
   before_script:
     - ls -d "$HOME/.nvm" || (curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash)
     - export NVM_DIR="$HOME/.nvm"
     - \[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
     - nvm --version
     - nvm use ${NODE_VERSION} || nvm install ${NODE_VERSION}
 
 # each job is associated to a stage
 build:
   stage: build
   script:
     - echo $CI_PIPELINE_SOURCE
     - echo $CI_COMMIT_REF_NAME
     - echo $CI_COMMIT_TAG
     - echo $CI_COMMIT_BRANCH
     - npm run lint
     - npm run build
   environment: production
 
 test:
   stage: test
   script:
     - npm run test:unit --run
  
 package:
   stage: package
   only:
     - tags
   except:
     - branches
   script:
     - ls dist
   artifacts:
     name: mypackage-${CI_COMMIT_TAG}.tar.gz
     paths:
       - dist/*

package.json
 LANG:console
 {
         "name": "mypackage",
         "version": "0.0.1",
         "scripts": {
                 "lint": "echo 'lint - success!'",
                 "build": "mkdir -p dist && (echo 'Hello!' > dist/hello.txt) && echo 'build - success!'",
                 "test:unit": "echo 'test:unit - success!'"
         }
 }

すると build と test に成功して、

build の結果:
 LANG:console
 Running with gitlab-runner 17.3.1 (66269445)
   on bee01 t2X9wkLjw, system ID: r_FoHQflE05Zou
 Preparing the "shell" executor 00:00
 Using Shell (bash) executor...
 Preparing environment 00:00
 Running on 8163caea6de5...
 Getting source from Git repository 00:00
 Fetching changes with git depth set to 20...
 Reinitialized existing Git repository in /home/gitlab-runner/builds/t2X9wkLjw/0/gitlab/osamu/gitlab-ci-hello/.git/
 Checking out 504e92af as detached HEAD (ref is master)...
 Skipping Git submodules setup
 Executing "step_script" stage of the job script 00:07
 $ ls -d "$HOME/.nvm" || (curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash)
 ls: cannot access '/home/gitlab-runner/.nvm': No such file or directory
   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                  Dload  Upload   Total   Spent    Left  Speed
 100 16555  100 16555    0     0  59336      0 --:--:-- --:--:-- --:--:-- 59336
 => Downloading nvm from git to '/home/gitlab-runner/.nvm'
 => Cloning into '/home/gitlab-runner/.nvm'...
 * (HEAD detached at FETCH_HEAD)
   master
 => Compressing and cleaning up git repository
 => Profile not found. Tried ~/.bashrc, ~/.bash_profile, ~/.zprofile, ~/.zshrc, and ~/.profile.
 => Create one of them and run this script again
    OR
 => Append the following lines to the correct file yourself:
 export NVM_DIR="$HOME/.nvm"
 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
 => Installing Node.js version 22
 Downloading and installing node v22.8.0...
 Downloading https://nodejs.org/dist/v22.8.0/node-v22.8.0-linux-x64.tar.gz...
 ######################################################################## 100.0%
 Computing checksum with sha256sum
 Checksums matched!
 Now using node v22.8.0 (npm v10.8.2)
 Creating default alias: default -> 22 (-> v22.8.0 *)
 => Node.js version 22 has been successfully installed
 => Close and reopen your terminal to start using nvm or run the following to use it now:
 export NVM_DIR="$HOME/.nvm"
 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
 $ export NVM_DIR="$HOME/.nvm"
 $ \[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
 $ nvm --version
 0.40.0
 $ nvm use ${NODE_VERSION} || nvm install ${NODE_VERSION}
 Now using node v22.8.0 (npm v10.8.2)
 $ npm run lint
 > mypackage@0.0.1 lint
 > echo 'lint - success!'
 lint - success!
 $ npm run build
 > mypackage@0.0.1 build
 > mkdir -p dist && (echo 'Hello!' > dist/hello.txt) && echo 'build - success!'
 build - success!
 Cleaning up project directory and file based variables 00:00
 Job succeeded

test の結果:
 LANG:console
 Running with gitlab-runner 17.3.1 (66269445)
   on bee01 t2X9wkLjw, system ID: r_FoHQflE05Zou
 Preparing the "shell" executor 00:00
 Using Shell (bash) executor...
 Preparing environment 00:00
 Running on 8163caea6de5...
 Getting source from Git repository 00:01
 Fetching changes with git depth set to 20...
 Reinitialized existing Git repository in /home/gitlab-runner/builds/t2X9wkLjw/0/gitlab/osamu/gitlab-ci-hello/.git/
 Checking out ae25c69e as detached HEAD (ref is master)...
 Removing dist/
 Skipping Git submodules setup
 Executing "step_script" stage of the job script 00:00
 $ ls -d "$HOME/.nvm" || (curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash)
 /home/gitlab-runner/.nvm
 $ export NVM_DIR="$HOME/.nvm"
 $ \[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
 $ nvm --version
 0.40.0
 $ nvm use ${NODE_VERSION} || nvm install ${NODE_VERSION}
 Now using node v22.8.0 (npm v10.8.2)
 $ npm run test:unit --run
 > mypackage@0.0.1 test:unit
 > echo 'test:unit - success!'
 test:unit - success!
 Cleaning up project directory and file based variables 00:00
 Job succeeded

となる。

ちゃんと初回に node がインストールされて、2回目はそれが再利用されている。

ちゃんと test をするときは report を作成するといいらしい~
https://docs.gitlab.com/17.3/ee/ci/testing/unit_test_reports.html

** パッケージング [#u55ac843]

まず、上で

 cache:
   paths:
     - dist/*

をしておかないと build で作成したファイルが package に引き継がれないので注意が必要だ。

そして package ステージには

   only:
     - tags
   except:
     - branches

がついているので、tag を付けたときで、なおかつそのタグがデフォルトブランチ(ここでは master)についてないとスクリプトは実行されない。

- https://stackoverflow.com/questions/42796018/how-to-run-a-gitlab-ci-yml-job-only-on-a-tagged-branch
- https://stackoverflow.com/questions/69199614/ci-commit-tag-in-if-statemets-of-regular-job

あたりを参照。

試してみよう

GitLab 画面のプロジェクトページの左上 "+" のドロップダウンから New Tag を選んで、

https://myserver.com/gitlab/myname/mypackage/-/tags/new

から 0.0.1 というタグを作成する。

・・・ん? 新しいパイプラインが生成されないような???

> 
> https://forum.gitlab.com/t/pipeline-not-executed-after-commit/87173/6
> 
> によると GitLab と Runner のバージョンを合わせた方がいいと書かれてる?
> 
> GitLab のバージョンは、
> 
>  $ docker compose exec web gitlab-rake gitlab:env:info
> 
> とするか、GitLab 画面左下の Help ボタンを押すことで確認できる。
> 
> ここでは 17.3.1 だった。
> 
> Runner のバージョンは GitLab の admin メニューから CI/CD - Runners で
> 
> https://myserver.com/gitlab/admin/runners
> 
> ここから個々の Runner をクリックして show detail すると、、、17.3.1 なので問題なし。
> 

ああ、違った。

ちゃんと動いているけれど、トップ画面の緑色のチェックマークはあくまでコミットに対する CI/CD の結果で、タグに対する CI/CD の結果は Tags のページでタグの横に現れるのか。

個別のタグのページに CI/CD の結果を表示してくれないので混乱した。

https://myserver.com/gitlab/myname/gitlab-ci-hello/-/tags/0.0.1

パイプラインがすべて正しく実行されると、

https://myserver.com/gitlab/myname/gitlab-ci-hello/-/tags

のタグの横に緑のチェックが出て、その右のダウンロードメニューに artifact - package が現れる。

選択すると mypackage-0.0.1.tar.gz を落とせた。

メニュー自体の表示を mypackage-0.0.1.tar.gz にすることはできないのかな???

TODO: リリース時にこのアーティファクトを参照する方法も調べる

* GitLab に Runner を登録する(docker モード) [#k3e6874a]

node は sudo の必要なくインストールできるので shell モードで簡単に動かせたけれど、
例えば playwright を動かそうとすると apt などでネイティブなパッケージをいろいろ入れなければならず、
困ってしまう。

そういう時は

https://qiita.com/yusayoshi/items/6b48bca5b5c0a17cd40e#gitlab-cicd

のように runner を docker モードで動かしてやればいいいいみたい。

これは、docker の中で走っている Runner が、さらに docker を起動して ci スクリプトをその docker の中で実行させるというもの。いわゆる dind (docker-in-docker) という技術らしい。Runner の docker コンテナを作る際に /var/run/docker.sock を受け渡しているおかげでそういうことができるのだとか。

Runner を docker モードで動かすには
上記手順で Runner を GitLab へ追加する際に
Executor を shell ではなく docker とする。

すると、デフォルトで使う docker image を聞かれる。

ここでは主に node 上での開発を考えているので playwright が使えるようリンク先にあった

 mcr.microsoft.com/playwright:focal

を指定した。

ci スクリプトから image を指定されないときにはこれが使われることになる。
スクリプトで image 指定すれば別の image を使うこともできる。

** extra_hosts を設定する [#dc5bb821]

上で runner に extra_hosts を追加している場合には、

runner/config.toml に、

 [[runners]]
   [runners.docker]
     extra_hosts = ["myserver.com:192.168.0.2"]

の設定をしないと、runner docker 内部で作成される docker コンテナに hosts の設定が引き継がれないことに注意が必要。

** 試してみる [#p08621ae]

これで始めから npm や playwright の使える環境で ci スクリプトを走らせることができるようになったはず。

上のスクリプトの before_script をバージョン確認だけにしてみた。

 default:
   before_script:
     - node --version
     - npm --version

すると、

 LANG:console
 $ node --version
 v20.16.0
 $ npm --version
 10.8.1

と表示され、残りのスクリプトも正しく実行された。

* GitLab の npm パッケージサーバーへパッケージを Deploy する [#fbffbb3a]

GitLab には npm パッケージサーバーの機能があるので、
そこへパッケージを Deploy してみよう。

** GitHub のプロジェクトをクローンして GitLab へ登録する [#vc66bcf0]

まず、こちらで作った typescript-vitest-skeleton という GitHub プロジェクトをクローンして、
GitLab へ登録しなおす

https://dora.bk.tsukuba.ac.jp/~takeuchi/?typescript+%2B+vitest+%E3%81%A7+npm+%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E9%96%8B%E7%99%BA+2024

GitLab 上で typescript-vitest-skeleton という空のプロジェクトを作成しておいて、

 LANG:console
 $ git clone https://github.com/osamutake/typescript-vitest-skeleton.git
 Cloning into 'typescript-vitest-skeleton'...
 $ cd typescript-vitest-skeleton/
 $ npm i
 $ git remote add origin2 https://myserver.com/gitlab/myname/typescript-vitest-skeleton.git
 $ git push origin2 --all

左のメニューの Deploy - Package Registray からこの GitLab プロジェクトのパッケージレジストリを確認できる。

https://myserver.com/gitlab/myname/typescript-vitest-skeleton/-/packages

当然今は空だ。

ここに上記 npm パッケージを登録したい。

** パッケージ名のスコープ [#eca37037]

GitLab プロジェクトのパッケージレジストリへパッケージを登録するには、

https://myserver.com/gitlab/api/v4/projects/(project id)/packages/npm/@(scope_name)/(package_name)

のようなアドレスへパッケージを PUT することになる。

ここで、

- project id : この GitLab サーバーのプロジェクトにつけられた通し番号
-- プロジェクトのトップページ https://myserver.com/gitlab/myname/typescript-vitest-skeleton の右上の縦に3つ並んだ点のアイコン(More actions)をクリックして "Copy Project ID: 9" をクリックするとコピーできる

- scope_name : npm ではパッケージ名の前に @ユーザー名 を付けることでスコープ付きにして、他のパッケージと名前が被らないようにしますが、それと似たような識別子
-- GitLab で使うときは GitLab サーバーを識別するために使うことになるみたい?

- package_name : 例えば上の typescript-vitest-skeleton

まだよくわかっていないのだけれど、どうやら GitLab の提供する npm パッケージサーバーからパッケージをダウンロードさせたい場合「"@osamu_takeuchi/*" のように @osamu_takeuchi というスコープがついているパッケージは npm ではなく特定の GitLab サーバーを探しに行け」という設定をすることになるみたいなので、パッケージ名を例えば @myserver/typescript-vitest-skeleton というような、分かりやすいスコープ付きにしておくのが良さそう?

 LANG:console
 $ git remote remove origin
 $ git remote remove origin2
 $ git remote add origin https://myserver.com/gitlab/myname/typescript-vitest-skeleton.git
 $ sed -i.bak s/@osamu_takeuchi/@myserver/ package.json 
 $ git add package.json
 $ git commit -m "Scope of package is changed"
 $ git push origin

** デプロイ用のトークンを発行して .npmrc を設定する [#k4264fcf]

パッケージのアップロードには個々のプロジェクトからのアクセス許可が必要なので、

プロジェクトの Settings - Repository - Deploy Tokens - Add token からトークンを発行する。

https://myserver.com/gitlab/myname/typescript-vitest-skeleton/-/settings/repository

&ref(add-deploy-token.png,,50%);

GitLab はいろんなところでいろんな用途のトークンを発行できるので、
違うところで違う用途のトークンを発行して設定して、動かないなあ、となることが多い(汗

- Name を npm push とする
- write_package_registry にチェックを入れる
- [Create deploy token] を押す
- 次の画面で gldt-XXXXXXXXXXXXXXXX のようなトークンをコピーする

プロジェクトのフォルダーにこのトークンを指定した .npmrc を作成する。

 LANG:console
 $ echo ".npmrc" >> .gitignore
 $ cat <<"EOS" >.npmrc
 //myserver.com/gitlab/api/v4/projects/9/packages/npm/:_authToken=gldt-XXXXXXXXXXXXXXXXX
 @myserver:registry=https://myserver.com/gitlab/api/v4/projects/9/packages/npm/
 EOS

このファイルを GitLab へアップロードしてしまうと誰でもデプロイできるようになってしまうので、
必ず .gitignore に追加しておく必要がある。

** 手動でデプロイする [#xbeab9f0]

後は普通に npm publish すればいい。

 LANG:console
 $ npm publish
 npm notice Publishing to https://myserver.com/gitlab/api/v4/projects/9/packages/npm/ with tag latest and default access
 + @myserver/mypackage@0.0.1

これでパッケージがデプロイされ、Package Registry に 

 @myserver/mypackage (latest)
 0.0.1 npm

のような項目が現れる。

TODO: プロジェクトじゃなくグループ単位のレジストリを使った方が良いのかも?

TODO: ci スクリプトから自動的にデプロイする方法は?

特に Deploy Token をどのように CI スクリプトに渡せばいいのかが想像つかない???

** Package Registry のパッケージを npm install する [#fcdddf1c]

こちらでは読み取りのみの権限があればいいので、
https://myserver.com/gitlab/myname/typescript-vitest-skeleton/-/packages

の一覧から先にデプロイした 0.0.1 をクリックすると、

 LANG:console
 $ echo @myserver:registry=https://myserver.com/gitlab/api/v4/packages/npm/ >> .npmrc
 $ npm i @myserver/mypackage

のようにすればインストールできると書かれていた。

ただし認証が必要になると。

ここでは読み取りのみの権限があればいいので、

トップページのサイドバーの右上アイコンから Edit Profile、サイドバーの User settings - Access Tokens - Add new token を選択。

https://myserver.com/gitlab/-/user_settings/personal_access_tokens

- Token name を例えば npm install とかにして
- read_api だけチェックして
- Expiration date を適当に延ばして [Create personal access token]
- 次のページでトークンをコピーする (glpat-XXXXXXXX みたいなの)

そして、

https://docs.gitlab.com/ee/user/packages/npm_registry/#authenticate-to-the-package-registry

を見ながら、

 LANG:console
 $ npm config set @myserver:registry https://myserver.com/api/v4/packages/npm/
 $ npm config set -- //myserver.com/api/v4/packages/npm/:_authToken=glpat-XXXXXXXX
 $ cat ~/.npmrc
 @myserver:registry=https://myserver.com/api/v4/packages/npm/
 //myserver.com/api/v4/packages/npm/:_authToken=glpat-XXXXXXXX

これらは ~/.npmrc に書き込まれるのでその後は自由に npm i が使えるはず。
これらが ~/.npmrc に書き込まれるのでその後は自由に npm i が使えるはず。

試しに、
 LANG:console
 $ mkdir ~/test_npm_install
 $ cd ~/test_npm_install
 $ npm init
 {
   "name": "test_npm_install",
   "version": "1.0.0",
   "main": "index.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "author": "",
   "license": "ISC",
   "description": ""
 }
 $ npm install @myserver/mypackage
 npm error code E404
 npm error 404 Not Found - GET https://myserver.com/api/v4/packages/npm/@myserver%2fmypackage
 npm error 404
 npm error 404  '@myserver/mypackage@*' is not in this registry.
 npm error 404
 npm error 404 Note that you can also install from a
 npm error 404 tarball, folder, http url, or git url.

ん?そうでもないぞ。

そんなパッケージは見つからないと言われる・・・って URL を指定し間違っていた。

今は gitlab/ というサブフォルダで gitlab を動かしているので
今は gitlab/ というサブフォルダで gitlab を動かしているので GitLab が教えてくれていた通り、

 LANG:console
 $ npm config set @myserver:registry https://myserver.com/gitlab/api/v4/packages/npm/
 $ npm config set -- //myserver.com/gitlab/api/v4/packages/npm/:_authToken=glpat-XXXXXXXX
 $ npm config set -- //myserver.com/gitlab:_authToken=glpat-XXXXXXXX

が正しい。

でもそうしたら今度は

 LANG:console
 $ npm install @myserver/mypackage
 npm error code E404
 npm error 404 Not Found - GET https://registry.npmjs.org/@takenchi%2fmypackage - Not found
 npm error 404
 npm error 404  '@takenchi/mypackage@*' is not in this registry.
 npm error 404
 npm error 404 Note that you can also install from a
 npm error 404 tarball, folder, http url, or git url.

となってしまった。

URL のパスが api から始まっていないと認識してくれない???

・・・どうやらそうじゃなくて、myserver.com の API が registry.npmjs.org へのリダイレクトを返しているらしい。適当なパッケージ名を与えても同じ動作をするので、恐らく自分が持っていないパッケージに対するフォールバック動作がこれみたい。
・・・どうやらそうじゃなくて、myserver.com の API が registry.npmjs.org へのリダイレクトを返しているらしい。適当に、絶対存在しないパッケージ名を与えても同じ動作をするので、恐らく自分が持っていないパッケージに対するフォールバック動作がこれみたい。

つまり、プロジェクトへ Deploy したパッケージはここには見つからない??
つまり、プロジェクトへ Deploy したパッケージがここに見つからない??

なんでだろう???


Counter: 49 (from 2010/06/03), today: 19, yesterday: 30