{"id":49510608,"url":"https://github.com/williamw-dev/gitlab-ci-cd","last_synced_at":"2026-05-01T19:01:18.810Z","repository":{"id":315760525,"uuid":"745391986","full_name":"williamw-dev/gitlab-ci-cd","owner":"williamw-dev","description":"Full GitLab CI-CD with all configurations ( Own Runners / OWASP / GitLab Pages )","archived":false,"fork":false,"pushed_at":"2024-01-19T08:37:22.000Z","size":12089,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-20T15:54:10.483Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/williamw-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-01-19T08:33:42.000Z","updated_at":"2024-02-25T22:27:17.000Z","dependencies_parsed_at":"2025-09-20T16:04:30.403Z","dependency_job_id":null,"html_url":"https://github.com/williamw-dev/gitlab-ci-cd","commit_stats":null,"previous_names":["williamw-dev/gitlab-ci-cd"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/williamw-dev/gitlab-ci-cd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamw-dev%2Fgitlab-ci-cd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamw-dev%2Fgitlab-ci-cd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamw-dev%2Fgitlab-ci-cd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamw-dev%2Fgitlab-ci-cd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/williamw-dev","download_url":"https://codeload.github.com/williamw-dev/gitlab-ci-cd/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/williamw-dev%2Fgitlab-ci-cd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32508912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-01T19:01:15.554Z","updated_at":"2026-05-01T19:01:18.798Z","avatar_url":"https://github.com/williamw-dev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ⚙️ CI-CD Project - M1 Dev B\n\n## 🐳 Exercise 0 - Before the CI: Dockerized web static app\n\n##### 🚀 To start the container, you need to follow these instructions.\n\n- Clone the projet with this command : `git clone git@gitlab.com:william-wtr92/m1-ci-cd.git`\n- Go at the root of the cloned project : `cd m1-ci-cd/`\n- Build the image with : `docker build -t m1-ci-cd .`\u003cbr/\u003e\n\n##### 🌐 The different `docker run` commands depend on the environment you want to be in\n\n- To launch the **STAGING** container so that you're able to modify the content thanks to the docker volume, run this command:\n  `docker run -d --name m1-ci-cd-staging -P -v $(pwd)/data/modif-data:/app/data/modif-data -e ENV=staging m1-ci-cd`\n\n- To launch the **PRODUCTION** container with the embedded part directly in the image, run this command :\n  `docker run -d --name m1-ci-cd-prod -P -e ENV=production m1-ci-cd`\n\n- Optional: To override the embedded `emb-data` in production with a volume:\n  `docker run -d --name m1-ci-cd-prod-over -P -v $(pwd)/data/emb-data:/app/data/emb-data -e ENV=production-over m1-ci-cd` \u003cbr/\u003e\n\n## ✏️ Exercise 1: Continuous Integration and Deployment with Auto DevOps\n\n#### 🔨 Introducing and configuring Auto DevOps\n\n- To activate Auto DevOps on the project, go to `CI/CD Settings \u003e Auto DevOps` and expand the feature.\u003cbr/\u003e\u003cbr/\u003e\n\n- Once inside, tick the Default to Auto DevOps pipeline box and for **the purposes of the exercise** it was preferable to choose the **3rd option ( Automatic deployment to staging, manual deployment to production )** as we would be dealing with deployment in staging and production.\n\n![Capture d’écran 2023-12-03 à 19.39.11](https://i.imgur.com/dfKOMYG.png)\n\n- Once this was done, you were given a default configuration, which is this: [Link to config](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml), this configuration automatically creates jobs based on the content of your project, so you don't need a **.gitlab-ci.yml file to have a CI**.\u003cbr/\u003e\u003cbr/\u003e\n\n- Below is a screen of my pipeline for adding Auto DevOps **without a .gitlab-ci.yml file.**\n  **(The failed jobs are due to the gitlab-runners because I'm using my own, I put their configurations right after)**\u003cbr/\u003e\u003cbr/\u003e\n  - [Link to the target pipeline](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1093666231):\n    ![Capture d’écran 2023-12-03 à 19.55.21](https://i.imgur.com/cUWp8zv.png)\n\n#### 📝 Custom and configure Runners\n\n- When a pipeline is launched, it uses Runners, either the default **Sharred Runners** or, if we wish, our own **Project Runners**, which is preferable if we want total control over our continuous integration environment.\u003cbr/\u003e\u003cbr/\u003e\n\n- For this exercise I needed 2 custom runners, so I went to **CI/CD Settings \u003e Runners** , and clicked on **New Project Runner**. I also deactivated the Sharreds to make sure they weren't used.\u003cbr/\u003e\u003cbr/\u003e\n\n  - I have a runner that allows me to run all the Auto DevOps jobs and also some custom ones, with a basic configuration, I'm sharing the **config.toml file here**:\n\n    ```yml\n      concurrent = 3 # Sets the maximum number of jobs the runner can execute simultaneously. Here, up to 3 jobs can be run at the same time.\n      check_interval = 0\n      shutdown_timeout = 0\n\n      [session_server]\n        session_timeout = 1800\n\n      [[runners]]\n        name = \"custom-runner1\"\n        url = \"https://gitlab.com\"\n        id = 30009828\n        token = \"\u003cmytoken\u003e\"\n        token_obtained_at = 2023-12-03T07:01:44Z\n        token_expires_at = 0001-01-01T00:00:00Z\n        executor = \"docker\"\n        [runners.docker]\n          tls_verify = false\n          image = \"docker:20.10.12\"\n          privileged = true # Allows the Docker container to run in privileged mode, giving the container almost the same access as the host machine.\n          disable_entrypoint_overwrite = false\n          oom_kill_disable = false\n          disable_cache = false\n          volumes = [\"/var/run/docker.sock:/var/run/docker.sock\", \"/cache\"]  # Mounts volumes inside the Docker container. Here, the Docker socket is shared to allow the container to communicate with the Docker daemon, and a cache volume is also mounted.\n          pull_policy = [\"if-not-present\"] # Defines the Docker image pull policy. Here, the image is pulled only if it's not already present locally.\n          shm_size = 0\n          network_mtu = 0\n    ```\n\n  - I have a second runner just for the code_quality job, which requires a certain architecture and whose configuration is shared at [code_quality](https://docs.gitlab.com/ee/ci/testing/code_quality.html):\n\n    ```yml\n      concurrent = 1\n      check_interval = 0\n      shutdown_timeout = 0\n\n      [session_server]\n        session_timeout = 1800\n\n      [[runners]]\n        name = \"cq-sans-dind\"\n        url = \"\u003chttps://gitlab.com\u003e\"\n        id = 30023772\n        token = \"\u003cmytoken\u003e\"\n        token_obtained_at = 2023-12-03T16:31:54Z\n        token_expires_at = 0001-01-01T00:00:00Z\n        executor = \"docker\"\n        builds_dir = \"/tmp/builds\" # Specifies the directory inside the container where the builds will be executed.\n        [runners.cache]\n          MaxUploadedArchiveSize = 0\n          [runners.cache.s3]\n          [runners.cache.gcs]\n        [runners.docker]\n          tls_verify = false\n          image = \"docker:latest\"\n          privileged = true\n          disable_entrypoint_overwrite = false\n          oom_kill_disable = false\n          disable_cache = false\n          volumes = [\"/cache\", \"/var/run/docker.sock:/var/run/docker.sock\", \"/tmp/builds:/tmp/builds\"] # Build directory for storing build files.\n          pull_policy = \"if-not-present\"\n          shm_size = 0\n          network_mtu = 0\n    ```\n\n- Once my runners are in place, I have a pipeline running and I decide to **customize it** to integrate the **staging deployment**, knowing that the **build job** for my image is done by Auto DevOps.\n\n#### 🔬 Creation and customization of the .gitlab-ci.yml file\n\n- With Auto DevOps it is possible to create a **.gitlab-ci.yml** file in order to add, complete or overwrite certain functions.\u003cbr/\u003e\u003cbr/\u003e\n\n- Once I saw that my pipeline was running with my own runners I decided to add the deployment job to the **staging environment**:\n\n  - Here is the **.yml code**:\n\n    ```yml\n    include:\n      - template: Auto-DevOps.gitlab-ci.yml # import of the Auto DevOps model\n\n      # I do not need to declare the internships in this pipeline because they are declared in the Auto DevOps template imported at the top of it\n\n    variables:\n      TEST_DISABLED: \"1\" # deletion of the Auto DevOps 'Test' job because it is deprecated and we will make it a custom\n      STAGING_CTN_NAME: m1-ci-cd-staging # variable used to remove and run the container for the STAGING environment\n      STAGING_URL: \u003chttp://localhost:3001/\u003e # variable which contains the deployment url of the website in staging\n      PROD_URL: https://m1-ci-cd-william-wtr92-b23c1a4222838f3c3110a4cf3f809745294028d2.gitlab.io # variable which contains the deployment url of the website in production\n\n    build: # I set rules for triggering the build job because it is a job that does not need to be executed when nothing has changed, it just slows down the pipeline and generates an image identical to the previous one.\n      rules: # at least one of these directories or files must be modified for the job to trigger\n        - changes:\n            - public/**/*\n            - src/**/*\n            - data/**/*\n            - Dockerfile\n            - .dockerignore\n            - package.json\n      allow_failure: false # does not accept that the job fails and fails the pipeline\n\n    semgrep-sast:\n      allow_failure: false\n\n    secret_detection:\n      allow_failure: false\n\n    nodejs-scan-sast:\n      allow_failure: false\n\n    container_scanning: # same operation as the build job\n      rules:\n        - changes:\n            - public/**/*\n            - src/**/*\n            - data/**/*\n            - Dockerfile\n            - .dockerignore\n            - package.json\n      allow_failure: false\n\n    code_quality: # Auto DevOps job, link to the doc: https://docs.gitlab.com/ee/ci/testing/code_quality.html\n      stage: test\n      services: # configuration specific to the doc\n      allow_failure: false # fail of this job is not allowed\n      tags: # code_quality needs its custom runner unlike other jobs as explained above\n        - cq-sans-dind1\n\n    deploy-staging: # custom job for staging deployment\n      rules:\n        - if: $CI_COMMIT_BRANCH == \"develop\" # the rule is there to activate the job only when the action is on the develop branch because it is the branch on which the staging version is built\n      image: docker # use of the docker image so that the commands are recognized in the job instance\n      stage: staging # belongs to the process staging stage of the pipeline\n      before_script:\n        - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin # I log in to the gitlab registry so that my job instance knows where to pull the image that was previously generated by the Auto DevOps build step\n      script:\n        - echo \"Deploying docker image 🚀\"\n        - docker pull $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:latest # pull the image from my registry using the different environment variable, most of them are self-generated variables\n        - docker rm -f $STAGING_CTN_NAME || true # deletion of the old docker container which runs the staging version if it exists otherwise the `|| true` is present when it does not find a container and it goes to the next step\n        - docker run --name $STAGING_CTN_NAME -d -p 3001:3000 -e ENV=staging $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:latest # launch of the container its name retrieved with the variable STAGING_CTN_NAME, -d to launch it detached, -p for mapping the port to the target environment, -e to setup an environment variable in the container which will be STAGING and after we tell it the target image with which to launch the container\n        - echo $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:latest\n      environment: # When we go to the Operate \u003e Environment section of the GitLab project, we have the possibility of setting up an environment, so that's what I do from my CI\n        name: $CI_COMMIT_REF_NAME # environment name\n        url: $STAGING_URL # url where we can visit our site in staging\n      needs: # the needs instruction is used to make the job understand that it needs/depends on the other jobs mentioned in the table\n        [\n          \"code_quality\",\n          \"nodejs-scan-sast\",\n          \"secret_detection\",\n          \"semgrep-sast\",\n          \"analyze_zap_report\",\n        ]\n    ```\n\n- Here is the rendering of my pipeline graphically once executed, during the example I deactivated the execution rules only on the develop branch in order to carry out my tests:\u003cbr/\u003e\u003cbr/\u003e\n\n  - [Link to the pipeline succeed with Build \u0026 Container Scanning](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1093697087) :\n    ![Capture d’écran 2023-12-03 à 21.18.19](https://i.imgur.com/qEh9d29.png)\n\n- The screen below shows the steps when the files targeted by the **build and container_scanning** job rules are not filled:\u003cbr/\u003e\u003cbr/\u003e\n  - [Link to the pipeline succeed without Build \u0026 Container Scanning](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1093789188)\n    ![Capture d’écran 2023-12-03 à 23.49.58](https://i.imgur.com/lV06EVL.png)\n\n#### 📜 Auto DevOps jobs explained\n\n- In the screenshot above we have **6 jobs self-implemented** thanks to Auto DevOps:\u003cbr/\u003e\u003cbr/\u003e\n  - **build**: Allows from my **Dockerfile** to the root of the build project to optimize its image\n  - **code_quality**: To analyze the quality and complexity of my source code. This helps keep the project code simple, readable, and easier to maintain.\n  - **container_scanning**: In-depth analysis of the structure of the image generated by the Dockerfile in order to identify vulnerabilities or not.\n  - **semgrep-sast**: Static Application Security Testing (SAST), **Job parend of nodejs-scan-sast**\n  - **nodejs-scan-sast**: Child of the semgrep-sast job to check your source code specifically for javascript and compare it to known vulnerabilities, the result is downloaded in the **project artifacts in .json format**\n  - **secret_detection**: Checks the secret leak in the current repository and avoids certain potential flaws, the result is uploaded to the project artifacts in .json format\n\n## 🔌 Exercise 2: Staging and production deployment\n\n#### 📖 Configuration of GitLab Pages for Production ENV\n\n- For the deployment of the staging and production versions we used **GitLab Pages**, mainly referring to the documentation.\n\n- We had to add a new job to manage the different deployments:\u003cbr/\u003e\u003cbr/\u003e\n\n  - [Link of GitLab Pages documentation](https://docs.gitlab.com/ee/user/project/pages/):\n\n  ```yml\n  variable:\n    PROD_URL: https://m1-ci-cd-william-wtr92-b23c1a4222838f3c3110a4cf3f809745294028d2.gitlab.io # variable used in pages job in environment step to add url in\n\n  pages: # default name of the job that allows deployment to GitLab pages\n    stage: deploy # belongs to the deployment stage\n    image: node:21.1.0-alpine # use node image to run the command in script step below\n    script:\n      - npm ci # installation of dependencies in package.json of the project\n      - npm run test:e2e # run all tests (currently, this only checks if the components are correctly rendered)\n      - npm run build # build of application\n      - rm -rf public/* # deletion of the basic public content because it must be able to welcome with the following command the content generated from the \"out/*\" folder which is generated during the command above npm run build and which generates a static version of our site\n      - mv out/* public # moving the content of \"out/*\" so what was generated in public/ folder\n      - echo \"Deploy to GitLab Pages in Production 🚀\"\n    artifacts: # creation of an artifact published on GitLab in the Build \u003e Artifacts section which is based on the contents of the public folder/, from where the scripts above\n      paths:\n        - public\n    cache: # caching of node_modules and .next/cache elements specific to the framework we use (see the GitLab Pages documentation relating to NextJS)\n      key: ${CI_COMMIT_REF_SLUG}\n      paths:\n        - node_modules/\n        - .next/cache/\n    environment: # creating a production environment with the link pointing to the URL of the GitLab Production Pages\n      name: production\n      url: $PROD_URL\n    rules: # definition of rules to start this jobs only on main branch\n      - if: $CI_COMMIT_BRANCH == \"main\"\n      - if: '$CI_PIPELINE_SOURCE == \"merge_request_event\"'\n      when: never\n    needs: # jobs that must be validated before executing the job pages\n    [\n      \"code_quality\",\n      \"nodejs-scan-sast\",\n      \"secret_detection\",\n      \"semgrep-sast\",\n      \"analyze_zap_report\",\n    ]\n    tags: # custom runner used\n      - node\n    retry: # sometimes the npm ci command marks a proxy error and on restart it works so it is a minor problem which just requires retrying the job\n      max: 2\n      when:\n        - runner_system_failure\n        - stuck_or_timeout_failure\n\n  ```\n\n- Once our CI is deployed we have in the Pages part of GitLab the link which allows us to go to the deployed website:\u003cbr/\u003e\u003cbr/\u003e\n\n  - [Pipeline Succeed with GitLab Pages deploy](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1098057313):\n    ![Capture d’écran 2023-12-07 à 19.16.30](https://i.imgur.com/UJq04km.png)\u003cbr/\u003e\u003cbr/\u003e\n\n  - [Link to Production GitLab Pages](https://m1-ci-cd-william-wtr92-b23c1a4222838f3c3110a4cf3f809745294028d2.gitlab.io)\n    ![Capture d’écran 2023-12-07 à 19.17.20](https://i.imgur.com/ByK8LF9.png)\n    ![Capture d’écran 2023-12-07 à 19.18.51](https://i.imgur.com/4WOqU0n.jpg)\n\n#### 🔎 Configuration specific to NextJS for deployment on GitLab Pages\n\n- Referring to this documentation [Custom settings for NextJS](https://docs.gitlab.com/ee/user/project/pages/public_folder.html) , we could see that it was necessary to change settings in the **NextJs configuration folder** so that it generates a compiled and possible static exported version of the site.\u003cbr/\u003e\u003cbr/\u003e\n\n- Configutation of our **next.config.js** file:\n\n  ```yml\n    /** @type {import('next').NextConfig} */\n\n    const nextConfig = {\n      output: \"export\", # this parameter allows the execution of npm run build to generate an out/ folder containing the static version of the site\n      reactStrictMode: true, # default params\n      images: {\n        unoptimized: true, # default params\n      },\n      assetPrefix: \"./\", # the assetPrefix setup allows you to give a path to the assets of the static version of the website\n    }\n\n    module.exports = nextConfig\n  ```\n\n#### 🖇️ Choice of NextJS \u0026 Own Runners: Why ?\n\n- We made the technical choice to use **NextJS** for the simplicity that the framework provides and its **compatibility with GitLab in the sense that there is written documentation on its setup for GitLab Pages for example**, its possibility of building its static content and the 'export which helped us in the creation of our CI. \u003cbr/\u003e\u003cbr/\u003e\n\n- Secondly, we chose to have our own runner because **it is important to be able to control our entire environment**, excluding the fact that we only have 400 minutes offered with the Sharred Runner, **this provides a real control over it**.\n\n## 💣 Exercise 3: Vulnerabilities?\n\n- To perform vulnerability scans on the project, we had to use **OWASP ZAP**, so that the CI would fail if the scan returned any anomalies or security issues.\u003cbr/\u003e\u003cbr/\u003e\n\n#### 📝 Explanation of jobs created for vulnerability scanning\n\n- To do this, we have created **2 separate jobs** in the CI:\n\n  - One that will perform the **scan and publish** the result in HTML format in the project's atifacts:\n\n    ```yml\n    zap_scan:\n      stage: test # stage to which the job belongs\n      image: owasp/zap2docker-stable # image owasp scan qui permet de lancer le scan et les commandes plus bas\n      script:\n        - cd /zap/wrk # move to the correct working directory /zap/wrk\n        - zap-baseline.py -t $PROD_URL -c gen.conf -r zap_report.html # we execute the command line to launch a python script that will run the scan, we must provide it with the following parameters: the URL on which it will run the scan, the configuration of the test steps in gen.conf (a file that has been sotcked locally and mapped to a volume on the runner can be read and shared when the job is run), and finally the name of the html file that will be generated and will contain the scan report.\n      after_script:\n        - echo \"Copy report file to the artifact path...\"\n        - cp /zap/wrk/zap_report.html . # we copy the content of the report generated in html so that the artifact does not generate an error: \"WARN : no *.html file in this directory\".\n      artifacts:\n        when: always\n        paths:\n          - zap_report.html # creation of artifact in the gitlab project containing the html report\n        expire_in: 1 week # rule allowing the file to be kept for 1 week in the project artifacts\n      rules: # rule requesting activation of this job than main and develop because it is only on these 2 branches that deployment jobs are executed and that we need to scan.\n        - if: $CI_COMMIT_BRANCH == \"develop\"\n        - if: $CI_COMMIT_BRANCH == \"main\"\n      allow_failure: false # not allowed to fail\n      tags:\n        - owasp # runner used to run this job\n    ```\n\n  - Secondly, we have a job that analyses the generated artifacts and, using a js script, **causes the CI to fail if there are any anomalies in the analysis of the html report:**\n\n    ```yml\n    zap_scan:\n      stage: test # stage to which the job belongs\n      image: owasp/zap2docker-stable # image owasp scan qui permet de lancer le scan et les commandes plus bas\n      script:\n        - cd /zap/wrk # move to the correct working directory /zap/wrk\n        - zap-baseline.py -t $PROD_URL -c gen.conf -r zap_report.html # we execute the command line to launch a python script that will run the scan, we must provide it with the following parameters: the URL on which it will run the scan, the configuration of the test steps in gen.conf (a file that has been sotcked locally and mapped to a volume on the runner can be read and shared when the job is run), and finally the name of the html file that will be generated and will contain the scan report.\n      after_script:\n        - echo \"Copy report file to the artifact path...\"\n        - cp /zap/wrk/zap_report.html . # we copy the content of the report generated in html so that the artifact does not generate an error: \"WARN : no *.html file in this directory\".\n      artifacts:\n        when: always\n        paths:\n          - zap_report.html # creation of an artifact in the gitlab project containing the HTML report\n        expire_in: 1 week # rule allowing the file to be kept for 1 week in the project artifacts\n      rules: # rule requesting activation of this job than main and develop because it is only on these 2 branches that deployment jobs are executed and that we need to scan.\n        - if: $CI_COMMIT_BRANCH == \"develop\"\n        - if: $CI_COMMIT_BRANCH == \"main\"\n      allow_failure: false # not allowed to fail\n      tags:\n        - owasp # runner used to run this job\n    ```\n\n  - And another job that analyzes the generated artifacts and, by using a JS script, can cause the CI to fail if there are any anomalies in the analysis of the HTML report:\n\n    ```yml\n    analyze_zap_report:\n      stage: review # stage to which the job belongs\n      image: node:latest # node image is used to run npm command below\n      script:\n        - npm install jsdom # installation of jsdom dependencies to launch the script below\n        - node analyzeReport.mjs # run the script used to retrieve and check the value of an element in the html report\n      artifacts:\n        when: on_failure # when the job analyze fails, I republish an artifact containing the HTML report on which it failed\n        paths:\n          - zap_report.html\n      rules:\n        - if: $CI_COMMIT_BRANCH == \"develop\"\n        - if: $CI_COMMIT_BRANCH == \"main\"\n      needs:\n        - job: zap_scan # dependence of the zap scan job\n          artifacts: true # requires the publication of artefacts by the latter\n      allow_failure: false # not allowed to fail\n    ```\n\n    - Here's the detailed and explained script called in the CI:\n\n    ```js\n    import fs from \"fs\" // File system module for file operations\n    import { JSDOM } from \"jsdom\" // JSDOM module to work with the DOM of HTML documents\n\n    // Read the content of the 'zap_report.html' file as a string\n    const html = fs.readFileSync(\"zap_report.html\", \"utf8\")\n\n    // Parse the HTML string into a DOM object\n    const dom = new JSDOM(html)\n\n    // Access the document object from the DOM\n    const document = dom.window.document\n\n    // Find the first DOM element that matches the CSS selector 'td.risk-3 + td div'\n    // This targets a div inside a td, which is immediately preceded by a td with class 'risk-3'\n    const highRiskElement = document.querySelector(\"td.risk-3 + td div\")\n\n    // Extract the text content of the found element, convert it to an integer\n    // If the element doesn't exist, set the count to 0\n    const highRiskCount = highRiskElement\n      ? parseInt(highRiskElement.textContent, 10)\n      : 0\n\n    // Check if there are any high-risk issues\n    if (highRiskCount \u003e 0) {\n      // If there are high-risk issues, log an error message with the count\n      console.error(`Found high risk issues: ${highRiskCount}`)\n\n      // Exit the process with an error code (1)\n      process.exit(1)\n    } else {\n      // If there are no high-risk issues, log a success message\n      console.log(\"No high risk issues found.\")\n\n      // Exit the process normally (0)\n      process.exit(0)\n    }\n    ```\n\n  - Finally, I'm going to show you the configuration of my config.toml file **for running zap_scan because a particular volume is expected:**\n\n    ```yml\n      [[runners]]\n        name = \"owasp\"\n        url = \"\u003chttps://gitlab.com\u003e\"\n        id = 30268258\n        token = \"\u003cmytoken\u003e\"\n        token_obtained_at = 2023-12-08T18:11:26Z\n        token_expires_at = 0001-01-01T00:00:00Z\n        executor = \"docker\"\n        [runners.cache]\n          ...\n        [runners.docker]\n          ...\n          volumes = [\"/cache\", \"/var/run/docker.sock:/var/run/docker.sock\",\"/tmp/builds:/zap/wrk\"] # mapping of a volume pointing from /tmp/builds to the directory requested by the scan script, which is /zap/wrk\n          ...\n    ```\n\n#### 🔎 The different results are analyzed\n\n- When the job succeeds, **the dependencies are used to launch the staging and production deployment**. Here is a pipeline to the merge of my branch to develop to analyse the triggering of the job:\n\n  - [Link of pipline succeed on staging env](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1101257678)\n    ![Capture d’écran 2023-12-09 à 11.20.12](https://i.imgur.com/wES75nY.png)\u003cbr/\u003e\u003cbr/\u003e\n  - [Link of pipline succeed on production env](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1101264873)\n    ![Capture d’écran 2023-12-09 à 11.41.42](https://i.imgur.com/dAg3Ewu.png)\u003cbr/\u003e\u003cbr/\u003e\n\n- In the piplines below I'm going to put the reaction of the pipeline when **the scan fails and it finds a vulnerability:**\n  - [Link of pipline fail on staging env](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1101271852)\n    ![Capture d’écran 2023-12-09 à 12.05.00](https://i.imgur.com/uPKREVr.png)\u003cbr/\u003e\u003cbr/\u003e\n  - [Link of pipeline fail on production env](https://gitlab.com/william-wtr92/m1-ci-cd/-/pipelines/1101285652)\n    ![Capture d’écran 2023-12-10 à 17.45.02](https://i.imgur.com/GhU0nDe.png)\n- We can see that when the scan fails it blocks the following stages of the pipeline and therefore the deployment, **the behavior is the same for the production deployment**.\n\n## Additionnal content : Playwright e2e tests for components\n\nThis repository contains automated tests using Playwright to check if our components are rendered correctly or not.\n\nYou can find each test right here in the `/e2e` folder.\n\nIf you reached this step, we're assuming you already have the project cloned into your PC.\n\nFirst, you must have the app running : `npm run dev`.\n\nNow you can run the tests :\n\n- **individually** by running this command : `npx playwright test fileName.spec.js`, replacing `fileName` by the name of a file in `/e2e` folder,\n- **globally** by running this command: `npm run test:e2e`, it will run the tests for **all** the components (for all the tests in the `/e2e` folder).\n\n### Playwright tests in CI\n\nAs tests can be runned manually, they can be runned automatically too, like inside the CI, here's the job used to run our e2e tests inside our `.gitlab-ci.yml` file :\n\n```yml\ne2e-tests:\n  stage: test # Stage to which the job belongs\n  image: mcr.microsoft.com/playwright:v1.40.0-jammy # Docker image to use for the job (Playwright)\n  script:\n    - npm install # Installing project dependencies\n    - npm run test:e2e # Running end-to-end tests\n  rules:\n    - if: '$CI_PIPELINE_SOURCE != \"merge_request_event\"' # Condition to execute the job only when the pipeline source is not a merge request event\n      when: always # Job execution condition when the rule is met\n  allow_failure: false # Whether the job is allowed to fail without impacting the pipeline\n```\n\nThis job won't be runned on merge requests, however it will be runned in any other case\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliamw-dev%2Fgitlab-ci-cd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwilliamw-dev%2Fgitlab-ci-cd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilliamw-dev%2Fgitlab-ci-cd/lists"}