How to access previous GitLab CI artifacts, process them and save file in "main" repository?

Viewed 1770

My application for this is to visualize the performance of my software. Therefore I briefly describe what I'm doing and where I'm stuck.

  1. I have my source code in GitLab
  2. Compile and run some tests in the CI for each commit
  3. Measure the time it took for the test run and save it to a file
  4. Upload the file with the time as an artifact

--------- From here on I don't know how to achieve it.

  1. Run some new job that reads all timing files of the previous artifacts
  2. Plot the times, probably with Python and save the image as SVG in the "main" repository
  3. Show the image on the GitLab start page (README.md should probably include it)
  4. Now I see which commits had which impact on my software's performance

No idea whether I'm asking for the impossible or not. I hope someone can help me as I'm not an CI expert. Maybe a single expression is already enough to google the solution but I don't even know how to formulate this.

Thanks everyone :)

1 Answers

Committing Images to Main

You can't just save an SVG image to the main repo from a pipeline job. You would need to make a commit. Not only would that pollute your git history and bulk up your repo, but it could also trigger a new pipeline, resulting in an endless loop.

There are ways around the endless loop, e.g. by controlling which sources/branches trigger pipelines or by prefixing the commit message with [skip ci], but it can get complicated and is probably not worth it. The truth is GitLab cannot do exactly what you want, so you will have to compromise somewhere.

Generate Metrics Graphs From Artifacts

You can collect metrics from past pipelines in a CSV file and save it as an artifact.

Add this to a reusable script called add_metrics.sh:

#!/bin/bash
HTTP_HEADER="PRIVATE-TOKEN: $YOUR_ACCESS_TOKEN"
URL_START="https://gitlab.example.com/api/v4/projects/$CI_PROJECT_ID/jobs/artifacts"
URL_END="raw/<path/to/artifact>/metrics.csv?job=$CI_JOB_NAME"

COLUMN_HEADERS=Date,Time,Branch,Commit SHA,Test Time(s),Code Coverage (%)

# download latest artifact
if curl --location --header $HTTP_HEADER $URL_START/$CI_COMMIT_BRANCH/$URL_END
then echo "Feature branch artifact downloaded."
elif curl --location --header $HTTP_HEADER $URL_START/master/$URL_END
then echo "Master branch artifact downloaded."
else echo $COLUMN_HEADERS >> metrics.csv
fi

# add data sample row to CSV
NOW_DATE=$(date +"%F")
NOW_TIME=$(date +"%T")
echo $NOW_DATE,$NOW_TIME,$CI_COMMIT_BRANCH,$CI_COMMIT_SHA,$TEST_TIME,$CODE_COVERAGE >> metrics.csv

# keep last 50 lines
echo "$(tail -50 metrics.csv)" > metrics.csv

Then call it from your pipeline in gitlab-ci.yml:

job_name:
  script:
    - TEST_TIME=10
    - CODE_COVERAGE=85
    - chmod +x add_metrics.sh
    - bash add_metrics.sh
  artifacts:
    paths:
      - metrics.csv
    expire_in: 1 month

Note: You will have to create a personal token and add it to a masked variable. I will also leave it up to you to populate the data metrics, like test time, code coverage, etc.

Explanation of Code

  1. Download the latest artifact for the current branch.
  2. The first commit of a feature branch will not find a "latest" artifact. If that happens, download the latest artifact from master.
  3. The first time the script runs, master won't even have a "latest" artifact, so create a new CSV file.
  4. APPEND the current sample to the end of the CSV file. Delete old samples to keep a fixed number of data points. You can add date, pipeline ID and other metrics.
  5. Store the updated artifact.
  6. To view the graph, download the artifact from the GitLab UI and view it in a spreadsheet app.

Publish to Pages

Using Python (pandas, matplotlib), you can generate an image of the plot and publish it to Gitlab Pages from your master branch pipeline. You can have a static HTML page in your repository referencing the same image filename, and keep replacing the same image from your pipeline. You can also add more useful metrics, such as code coverage.

Related