/ .gitlab-ci.yml
.gitlab-ci.yml
  1  workflow:
  2    rules:
  3      - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  4        when: never
  5      - if: $CI_COMMIT_TAG
  6        when: never
  7      - if: $CI_SERVER_HOST != "gitlab.com" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  8        when: never
  9      - when: always
 10  
 11  image: node:24.14.0-bullseye
 12  
 13  .build-steps: &build-steps
 14    - npm run lint
 15    - npm run build-typecheck
 16    - npm run clean
 17    - npm run build
 18  
 19  .dependencies-cache: &dependencies-cache
 20    key: $CI_COMMIT_REF_SLUG
 21    paths:
 22      - node_modules
 23      - .npm
 24      - cli/node_modules
 25      - game-server/node_modules
 26      - login-server/node_modules
 27      - proxy/node_modules
 28      - server-testing/node_modules
 29  
 30  .install-7zip: &install-7zip
 31    - apt update
 32    - apt-get -y install p7zip-full
 33  
 34  .install-jq: &install-jq
 35    - apt update
 36    - apt-get -y install jq
 37  
 38  .create-cli-artifacts: &cli-artifacts
 39    script:
 40      - set -euo pipefail
 41      - cd cli
 42      - *install-7zip
 43      - chmod +x ./provisionDefaultArtifacts.sh
 44      - ./provisionDefaultArtifacts.sh
 45      - cd .. # pack files are moved by shell script into root directory
 46      - 7z a datapack.7z datapack.database
 47    after_script:
 48      - echo "CLI_ARTIFACT_JOB_ID=$CI_JOB_ID" >> job.env
 49  
 50  .create-cli-geopack: &cli-geopack
 51    script:
 52      - set -euo pipefail
 53      - cd cli
 54      - *install-7zip
 55      - chmod +x ./provisionGeopackArtifacts.sh
 56      - ./provisionGeopackArtifacts.sh
 57      - cd .. # pack files are moved by shell script into root directory
 58      - 7z a geopack.7z geopack.database
 59    after_script:
 60      - echo "GEOPACK_JOB_ID=$CI_JOB_ID" >> job.env
 61  
 62  .prepare-package-dist: &prepare-package-dist
 63    - *install-7zip
 64    - rm -rf source
 65  
 66  .rule-run-on-tag: &rule-run-on-tag
 67    rules:
 68      - if: $CI_COMMIT_TAG # when a tag is created manually
 69  
 70  .rule-run-except-tag: &rule-run-except-tag
 71    rules:
 72      - if: $CI_COMMIT_TAG
 73        when: never
 74      - when: on_success
 75  
 76  .rule-run-on-gitlab-on-tag: &rule-run-on-gitlab-on-tag
 77    rules:
 78      - if: $CI_SERVER_HOST != "gitlab.com"
 79        when: never
 80      - if: $CI_COMMIT_TAG
 81  
 82  .docker-repository-config: &docker-repository-config
 83    - |
 84      mkdir -p $HOME/.docker
 85      echo "{
 86        \"auths\": {
 87          \"${CI_REGISTRY}\": {
 88            \"auth\": \"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"
 89          },
 90          ${DOCKER_AUTH}
 91        }
 92      }" > $HOME/.docker/config.json
 93  
 94  .install-regctl: &initialize-regctl
 95    - curl -L https://github.com/regclient/regclient/releases/latest/download/regctl-linux-amd64 > /usr/bin/regctl
 96    - chmod 755 /usr/bin/regctl
 97    - regctl --host "reg=${CI_REGISTRY},tls=insecure" registry login ${CI_REGISTRY} -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD}
 98  
 99  cache:
100    <<: *dependencies-cache
101    policy: pull
102  
103  stages:
104    - preparation
105    - build
106    - asset
107    - artifacts
108    - verify
109  
110  include:
111    - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
112  
113  #--------------------------------
114  # Preparation jobs
115  prepare-dependencies:
116    stage: preparation
117    script:
118      - npm ci --cache .npm
119    cache:
120      <<: *dependencies-cache
121      policy: pull-push
122  
123    <<: *rule-run-except-tag
124  
125  #--------------------------------
126  # Build jobs
127  cli-build:
128    stage: build
129    script:
130      - cd cli
131      - *build-steps
132      - chmod +x ./provisionServerDatabases.sh
133      - ./provisionServerDatabases.sh
134    <<: *rule-run-except-tag
135  
136  game-server-build:
137    stage: build
138    script:
139      - cd game-server
140      - *build-steps
141      - *prepare-package-dist
142      - 7z a game-server-dist.7z dist/
143      - mv game-server-dist.7z ../
144    artifacts:
145      paths:
146        - game-server-dist.7z
147      expire_in: 60 mins
148    <<: *rule-run-except-tag
149  
150  login-server-build:
151    stage: build
152    script:
153      - cd login-server
154      - *build-steps
155      - *prepare-package-dist
156      - 7z a login-server-dist.7z dist/
157      - mv login-server-dist.7z ../
158    artifacts:
159      paths:
160        - login-server-dist.7z
161      expire_in: 60 mins
162    <<: *rule-run-except-tag
163  
164  server-testing-build:
165    stage: build
166    script:
167      - cd server-testing
168      - *build-steps
169    <<: *rule-run-except-tag
170  
171  proxy-build:
172    stage: build
173    script:
174      - cd proxy
175      - *build-steps
176      - *prepare-package-dist
177      - 7z a proxy-dist.7z dist/
178      - mv proxy-dist.7z ../
179    artifacts:
180      paths:
181        - proxy-dist.7z
182      expire_in: 60 mins
183    <<: *rule-run-except-tag
184  
185  control-plane-build:
186    stage: build
187    script:
188      - cd control-plane
189      - *build-steps
190    <<: *rule-run-except-tag
191  
192  update-website:
193    stage: build
194    cache: [ ]
195    pages:
196      publish: website/source/.vitepress/dist
197    script:
198      - cd website
199      - npm ci
200      - npm run build
201    rules:
202      - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_SERVER_HOST == "gitlab.com"
203  
204  #--------------------------------
205  # Asset creation jobs
206  datapack-asset:
207    stage: asset
208    <<: *cli-artifacts
209    artifacts:
210      paths:
211        - datapack.7z
212        - game.database
213        - login.database
214      expire_in: 60 mins
215    <<: *rule-run-except-tag
216  
217  geopack-asset:
218    stage: asset
219    <<: *cli-geopack
220    artifacts:
221      paths:
222        - geopack.7z
223      expire_in: 60 mins
224    <<: *rule-run-except-tag
225  
226  package-servers-linux:
227    stage: asset
228    parallel:
229      matrix:
230        - OS: linux
231          ARCH: amd64
232          URL: "https://nodejs.org/dist/v24.14.0/node-v24.14.0-linux-x64.tar.xz"
233        - OS: linux
234          ARCH: arm64
235          URL: "https://nodejs.org/dist/v24.14.0/node-v24.14.0-linux-arm64.tar.xz"
236    tags:
237      - ${OS}-${ARCH}
238    needs:
239      - job: datapack-asset
240        artifacts: true
241      - job: geopack-asset
242        artifacts: true
243      - job: game-server-build
244        artifacts: true
245      - job: login-server-build
246        artifacts: true
247    script:
248      - *install-7zip
249      - npm ci --omit=dev --workspace=login-server --workspace=game-server
250      - cd package
251      - sed -i "s/%BUILD_HASH%/${CI_COMMIT_SHA}/g" launch-servers.sh
252      - sed -i "s/%BUILD_INFO%/L2TS ${OS}-${ARCH} Gitlab CI ${CI_PIPELINE_CREATED_AT}/g" launch-servers.sh
253      - chmod +x ci.defaultServers-linux.sh
254      - ./ci.defaultServers-linux.sh $URL
255      - mv l2ts-game-login-linux.7z ../l2ts-game-login-linux-${ARCH}.7z
256    artifacts:
257      paths:
258        - l2ts-game-login-linux-${ARCH}.7z
259      expire_in: 60 mins
260    <<: *rule-run-except-tag
261  
262  package-servers-windows:
263    stage: asset
264    parallel:
265      matrix:
266        - OS: windows
267          ARCH: amd64
268    tags:
269      - ${OS}-${ARCH}
270    needs:
271      - job: datapack-asset
272        artifacts: true
273      - job: geopack-asset
274        artifacts: true
275      - job: game-server-build
276        artifacts: true
277      - job: login-server-build
278        artifacts: true
279    script:
280      - npm ci --omit=dev --workspace=login-server --workspace=game-server
281      - powershell -ExecutionPolicy Bypass -File .\package\cleanNpmModules.ps1
282      - cd package
283      - |
284        $path = "launch-servers.ps1"
285        $content = Get-Content -Raw $path
286  
287        $content = $content -replace [regex]::Escape("%BUILD_HASH%"), $env:CI_COMMIT_SHA
288        $content = $content -replace [regex]::Escape("%BUILD_INFO%"), ("L2TS {0}-{1} GitLab CI {2}" -f $env:OS, $env:ARCH, $env:CI_PIPELINE_CREATED_AT)
289  
290        Set-Content -NoNewline -Encoding UTF8 $path $content
291      - powershell -ExecutionPolicy Bypass -File .\ci.defaultServers-windows.ps1
292    artifacts:
293      paths:
294        - l2ts-game-login-windows.7z
295      expire_in: 60 mins
296    <<: *rule-run-except-tag
297  
298  #-----------------------
299  # Artifacts like docker images, release files
300  server-image-latest:
301    stage: artifacts
302    cache: []
303    <<: *rule-run-except-tag
304    image:
305      name: quay.io/buildah/stable
306    parallel:
307      matrix:
308        - OS : linux
309          ARCH: amd64
310        - OS: linux
311          ARCH: arm64
312    tags:
313      - ${OS}-${ARCH}
314    needs:
315      - job: datapack-asset
316        artifacts: true
317      - job: geopack-asset
318        artifacts: true
319      - job: game-server-build
320        artifacts: true
321      - job: login-server-build
322        artifacts: true
323    variables:
324      STORAGE_DRIVER: vfs
325      BUILDAH_FORMAT: docker
326    script:
327      - *docker-repository-config
328      - echo "$CI_REGISTRY_PASSWORD" | buildah login --tls-verify=false -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
329      - buildah build 
330        --platform=linux/${ARCH}
331        --force-rm=true
332        --no-cache
333        --label version=latest
334        --label source=$CI_PROJECT_URL
335        --label revision=$CI_COMMIT_SHA
336        --label license="AGPL-3.0-or-later"
337        --build-arg BUILD_HASH=$CI_COMMIT_SHA
338        --build-arg BUILD_INFO="L2TS ${OS}-${ARCH} Gitlab CI ${CI_PIPELINE_CREATED_AT}"
339        -t ${CI_REGISTRY_IMAGE}/server:latest-${ARCH} 
340        -f ${CI_PROJECT_DIR}/docker/server.ci.Dockerfile
341        ${CI_PROJECT_DIR}
342      - buildah push --tls-verify=false ${CI_REGISTRY_IMAGE}/server:latest-${ARCH}
343  
344  server-merge-manifests:
345    stage: artifacts
346    cache: []
347    needs:
348      - job: server-image-latest
349        artifacts: false
350    image:
351      name: quay.io/buildah/stable
352    variables:
353      STORAGE_DRIVER: vfs
354      BUILDAH_FORMAT: docker
355      IMAGE_NAME: "$CI_REGISTRY_IMAGE/server:latest"
356    script:
357      - *docker-repository-config
358      - echo "$CI_REGISTRY_PASSWORD" | buildah login --tls-verify=false -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
359      - buildah manifest create $IMAGE_NAME
360      - buildah manifest add --tls-verify=false --arch=amd64 $IMAGE_NAME ${IMAGE_NAME}-amd64
361      - buildah manifest add --tls-verify=false --arch=arm64 $IMAGE_NAME ${IMAGE_NAME}-arm64
362      - buildah manifest push --tls-verify=false --all --format=v2s2 $IMAGE_NAME
363  
364  server-cleanup-tags:
365    stage: artifacts
366    cache: [ ]
367    needs:
368      - job: server-merge-manifests
369        artifacts: false
370    script:
371      - *initialize-regctl
372      - regctl --host "reg=${CI_REGISTRY},tls=insecure" tag delete ${CI_REGISTRY_IMAGE}/server:latest-amd64
373      - regctl --host "reg=${CI_REGISTRY},tls=insecure" tag delete ${CI_REGISTRY_IMAGE}/server:latest-arm64
374  
375  proxy-image-latest:
376    stage: artifacts
377    cache: []
378    <<: *rule-run-except-tag
379    image:
380      name: quay.io/buildah/stable
381    parallel:
382      matrix:
383        - OS: linux
384          ARCH: amd64
385        - OS: linux
386          ARCH: arm64
387    tags:
388      - ${OS}-${ARCH}
389    variables:
390      STORAGE_DRIVER: vfs
391      BUILDAH_FORMAT: docker
392      IMAGE_NAME: ${CI_REGISTRY_IMAGE}/proxy:latest-${ARCH}
393    script:
394      - *docker-repository-config
395      - echo "$CI_REGISTRY_PASSWORD" | buildah login --tls-verify=false -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
396      - buildah build 
397        --platform=linux/${ARCH}
398        --force-rm=true
399        --no-cache
400        --label version=latest
401        --label source=$CI_PROJECT_URL
402        --label revision=$CI_COMMIT_SHA
403        --label license="AGPL-3.0-or-later"
404        --build-arg BUILD_HASH=$CI_COMMIT_SHA
405        --build-arg BUILD_INFO="L2TS ${OS}-${ARCH} Gitlab CI ${CI_PIPELINE_CREATED_AT}"
406        -t ${IMAGE_NAME}
407        -f ${CI_PROJECT_DIR}/docker/proxy.ci.Dockerfile
408        ${CI_PROJECT_DIR}
409      - buildah push --tls-verify=false ${IMAGE_NAME}
410  
411  proxy-merge-manifests:
412    stage: artifacts
413    cache: []
414    needs:
415      - job: proxy-image-latest
416        artifacts: false
417    image:
418      name: quay.io/buildah/stable
419    variables:
420      STORAGE_DRIVER: vfs
421      BUILDAH_FORMAT: docker
422      IMAGE_NAME: "$CI_REGISTRY_IMAGE/proxy:latest"
423    script:
424      - *docker-repository-config
425      - echo "$CI_REGISTRY_PASSWORD" | buildah login --tls-verify=false -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
426      - buildah manifest create $IMAGE_NAME
427      - buildah manifest add --tls-verify=false --arch=amd64 $IMAGE_NAME ${IMAGE_NAME}-amd64
428      - buildah manifest add --tls-verify=false --arch=arm64 $IMAGE_NAME ${IMAGE_NAME}-arm64
429      - buildah manifest push --tls-verify=false --all --format=v2s2 $IMAGE_NAME
430  
431  proxy-cleanup-tags:
432    stage: artifacts
433    cache: [ ]
434    needs:
435      - job: proxy-merge-manifests
436        artifacts: false
437    script:
438      - *initialize-regctl
439      - regctl --host "reg=${CI_REGISTRY},tls=insecure" tag delete ${CI_REGISTRY_IMAGE}/proxy:latest-amd64
440      - regctl --host "reg=${CI_REGISTRY},tls=insecure" tag delete ${CI_REGISTRY_IMAGE}/proxy:latest-arm64
441  
442  update-latest-release:
443    stage: artifacts
444    cache: [ ]
445    needs:
446      - job: package-servers-linux
447        artifacts: true
448      - job: package-servers-windows
449        artifacts: true
450    # Personal access token must have api and Maintainer level access permissions
451    script:
452      - *install-jq
453      - chmod +x ./package/recreateRelease.sh
454      - chmod +x ./package/uploadPackageToGitlab.sh
455      - |
456        ./package/recreateRelease.sh \
457        --gitlab-host "$CI_SERVER_URL" \
458        --project-id "$CI_PROJECT_ID" \
459        --token "$L2TS_RELEASE_TOKEN" \
460        --tag-ref "$CI_COMMIT_SHA" \
461        --release-tag "latest" \
462        --release-name "latest" \
463        --release-description "Auto-updated latest release from pipeline ${CI_PIPELINE_ID} (${CI_COMMIT_SHORT_SHA})."
464      - |
465        ./package/uploadPackageToGitlab.sh \
466          --gitlab-host "$CI_SERVER_URL" \
467          --project-id "$CI_PROJECT_ID" \
468          --token "$L2TS_RELEASE_TOKEN" \
469          --release-tag "latest" \
470          --asset-name "l2ts-game-login-linux-amd64.7z" \
471          --file "$CI_PROJECT_DIR/l2ts-game-login-linux-amd64.7z" \
472          --package-name "game" \
473          --package-version "latest" \
474          --project-path "$CI_PROJECT_PATH"
475      - |
476        ./package/uploadPackageToGitlab.sh \
477          --gitlab-host "$CI_SERVER_URL" \
478          --project-id "$CI_PROJECT_ID" \
479          --token "$L2TS_RELEASE_TOKEN" \
480          --release-tag "latest" \
481          --asset-name "l2ts-game-login-linux-arm64.7z" \
482          --file "$CI_PROJECT_DIR/l2ts-game-login-linux-arm64.7z" \
483          --package-name "game" \
484          --package-version "latest" \
485          --project-path "$CI_PROJECT_PATH"
486      - |
487        ./package/uploadPackageToGitlab.sh \
488          --gitlab-host "$CI_SERVER_URL" \
489          --project-id "$CI_PROJECT_ID" \
490          --token "$L2TS_RELEASE_TOKEN" \
491          --release-tag "latest" \
492          --asset-name "l2ts-game-login-windows.7z" \
493          --file "$CI_PROJECT_DIR/l2ts-game-login-windows.7z" \
494          --package-name "game" \
495          --package-version "latest" \
496          --project-path "$CI_PROJECT_PATH"
497    <<: *rule-run-except-tag
498  
499  #-----------------------
500  # E2E testing of server functionality
501  server-image-test:
502    stage: verify
503    variables:
504      DISABLE_V8_COMPILE_CACHE: 1
505    retry: 1
506    script:
507      - cd cli
508      - npm run --silent portainer-deploy -- --host-ip="${PORTAINER_HOST}" --token="${PORTAINER_TOKEN}" --image="${CI_REGISTRY_IMAGE}/server:latest" --env="${PORTAINER_ENV}" --label="Lineage2TS Game"
509      - echo "Waiting for container to start"
510      - sleep 10
511      - cd ../server-testing
512      - sed -i "s/127.0.0.1/${PORTAINER_HOST}/g" cucumber.json
513      - npm run scenarios
514    <<: *rule-run-except-tag