Hello there !
I’ve set up a working pipeline for my gitlab repository, but i am not sure that i’ve followed best practices rules, and i think it could need some optimization too…
The background :
- Let’s see my repo as a multi-packages repository. I have 3 first level directories and in each directory, i can have several packages sources.
[TAClient]
[package1]
[package-abc]
[this is also a package]
[TAServer]
[Yet another package]
[Assets]
[PackageX]
[PackageY]
So the top directories are fixed but not the sub dirs.
- A “package” is a mix of powershell and javascript files.
- For now i’ve only implemented code linting for both powershell and javascript files.
Now let’s review the gitlab-ci.yml file :
stages:
- narrow
- lint
.narrow_template:
stage: narrow
rules:
- if : $CI_PIPELINE_SOURCE == "push"
changes:
- $DIRNAME/**/*
- when: never
.lint_template:
stage: lint
rules:
- if : $CI_PIPELINE_SOURCE == "push"
changes:
- $DIRNAME/**/*
- when: never
ClientRemoteAction:narrow:
extends: .narrow_template
variables:
DIRNAME: "taclient"
image: node:17.3.0
script:
- CUSTOM_COMMIT_BEFORE_SHA=$(git rev-parse HEAD~1);
- CUSTOM_COMMIT_SHA=$(git rev-parse HEAD~0);
- MODIFIED_ITEMS=($(git diff --name-only $CUSTOM_COMMIT_BEFORE_SHA...$CUSTOM_COMMIT_SHA | grep ^$DIRNAME | cut -d "/" -f1-2 | uniq));
- MODIFIED_PACKAGES=()
- for i in "${MODIFIED_ITEMS[@]}"; do [[ -d $i ]] && MODIFIED_PACKAGES+=($i); done
- if [ ${#MODIFIED_PACKAGES[*]} -eq 0 ]; then echo "Nothing to do !";exit 1;fi
- COMMA_SEPARATED_PACKAGES=$(IFS=, ; echo "${MODIFIED_PACKAGES[*]}")
- echo "MODIFIED_FOLDERS=$COMMA_SEPARATED_PACKAGES" >> variable.env
artifacts:
when: always
reports:
dotenv: variable.env
ClientRemoteAction:eslint:
extends: .lint_template
variables:
DIRNAME: "taclient"
image: node:17.3.0
needs:
- job: ClientRemoteAction:narrow
artifacts: true
before_script:
- npm install eslint@7.32.0 eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise
script:
- mod=${MODIFIED_FOLDERS//,/\/**/\*.js }/**/*.js
- ./node_modules/.bin/eslint $mod --c "$DIRNAME/.eslintrc.conf" -f junit -o eslint.xml
artifacts:
reports:
junit: eslint.xml
ClientRemoteAction:posh-lint:
extends: .lint_template
variables:
DIRNAME: "taclient"
image: mcr.microsoft.com/powershell:latest
needs:
- job: ClientRemoteAction:narrow
artifacts: true
before_script:
- apt-get update -qq
- apt-get install -qq git
- pwsh -c '$global:progresspreference="silentlycontinue";Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted;Install-Module -Name "Pester", "PSScriptAnalyzer" -Scope CurrentUser'
script:
- pwsh "./$DIRNAME/lint.ps1"
artifacts:
reports:
junit: posh-analysis.xml
ServerRemoteAction:narrow:
extends: .narrow_template
variables:
DIRNAME: "taserver"
script:
- echo "ICI";
This setup allows me to use a variable called $DIRNAME
which contains the first level directory name (taclient, taserver or assets)
The first stage, called narrow allows me to get a list of modified packages directories.
In this stage, i use git rev-parse
to get the two SHAs needed by the git diff
. If you wonder why i am doing this rather than using the built-in pipelines variables, it’s because when you create a new branch, you have the pipeline default COMMIT_BEFORE_SHA
set to 000000000000000000000. Which is not the case when you get it with git rev-parse HEAD~1
When i have my list of modified package directories, i export it to a dotenv variable in a comma-separated string (since dotenv does’nt allow arrays)
Then i have two jobs, one for running eslint and the second for running PsScriptAnalyzer (for powershell).
I have not provided the lint.ps1 file, but if someone wants to see it no problem.
In the eslint job, i replace the commas of my dotenv variable by /**/*.js so if i have something like :
MODIFIED_FOLDERS=taclient/abc,taclient/def
it becomes taclient/abc/**/*.js taclient/def/**.*.js
If there is another way of eslinting differents folders, i don’t know it
Then i call eslint with its conf file. If you also wonder why i use an .eslintrc.conf
instead of a json, js or any known eslint config file ext , this is because it’s the only workaround i’ve came up to make eslint work on my dev computer (Windows + VsCode + eslint vscode extension) => If i use a regular config name, eslint doesn’t work, if i rename it to some unknown extension, it works…
Well this is it, thanks for your time !