| size | 14580 |
|---|
Alexandre Abadie, Thierry Martinez (SED) Two-hours training, 15 december 2022
- A continuous integration (CI) platform for GitHub-hosted projects, launched on 16 October 2018.
-
Providing GitHub-hosted runners for Linux, MacOS and Windows.
-
File-based workflow specification:
.github/workflows/*.yml. A command-line tool,actis available for running workflows locally (or from other continuous integration platforms): https://github.com/nektos/act -
Very easy to extend (new reusable actions can be defined in git repositories), Linux runners can run docker containers, user-provided runners can be used.
Continuous integration (CI): practice of short-lived development cycles, automatically tested and shared regularly between developers involved in a project.
Continuous integration platforms: Github Actions, ci.inria.fr, gitlab.inria.fr.
Automating testing (and CI in general) relies on version control and automated builds.
-
speed up development process,
-
ease collaboration
-
allow programmers to be more confident for not introducing regression and bugs.
This is a step towards broader goals such as reproducible builds and reproducible research.
About version control
Version control systems are software dedicated for managing
- history and
- collaborative edition of source code or any other kind of documents.
The prominent software for version control is now git, initially developed in 2005 by Linus Torvalds to manage the Linux source code.
git is a decentralized tool (where versions are directly exchanged between peers) but most uses of it now rely on software forges, like [GitHub] or gitlab.inria.fr for instance. Software forges provide other services related to version control, such as [CI/CD] facilities.
Keeping the history of a code is central
- to make change in the code without losing information and
- to identify where regressions have been introduced (bisection).
- to allow code to be modified concurrently by offering merging facilities (three-way merge).
-
Hardware specification for Windows and Linux virtual machines:
- 2-core CPU (x86_64)
- 7 GB of RAM
- 14 GB of SSD space
-
Hardware specification for macOS virtual machines:
- 3-core CPU (x86_64)
- 14 GB of RAM
- 14 GB of SSD space
Usage limits, billing: available for free for public repositories,
- up to 20 concurrent jobs (Linux/Windows),
- 5 concurrent jobs for macOS.
In .github/workflows/example.yml:
on: [push]
jobs:
build-example:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Compile
run: |
gcc -o hello_word hello_world.c
- name: Test
run: |
./hello_word > output.txt
diff output.txt excepted.txt- Workflow can have arbitrary complex directed acyclic graph as dependency graph.
- On repository index
- In
README.mdbadges:
[![CI][ci-badge]][ci-link]
- In pull requests (in addition, posts can generated by bots invoked from CI)
-
We will use GitHub command line: https://cli.github.com/
-
Fork training course repository:
gh repo fork --clone aabadie/github-actions-python-example
(to create a new repository instead: gh repo create <repo name> --public --clone)
- Edit workflow in
github-actions-primer/.github/workflows/continuous-integration.yml
See Choosing GitHub hosted runners for a list of available platforms
for runs-on entry. Note that ubuntu-latest is currently Ubuntu 20.04.
There is ubuntu-22.04 available in beta.
Build environments can be prepared once for all in a Docker image to reduce build times:
-
docker build -t ghcr.io/‹user›/‹image name› . -
create a personal access token with scope
write:packages, save it in a file -
docker login ghcr.io -u ‹user› --password-stdin < ‹token path› -
docker push ghcr.io/‹user›/‹image name› -
create a personal access token with scope
read:packages, store it in a secret (usinggh secret set) -
reference the container in the job
container:
image: ghcr.io/‹user›/‹image name›
credentials:
username: ${{ github.actor }}
password: ${{ secrets.‹secret name› }}- to run the workflow locally, use
act --secret-file ‹file name›
-
Use
strategy.matrixto build the same job with different combinations of parameters. -
Set
strategy.fail-fast: falseto continue the build of other combinations when a combination failed.
-
Store a personal access token] with scope
write:packagesin a secret. -
Check out the repository! Add the following action
- name: Checkout
uses: actions/checkout@v3
- Steps for
docker buildanddocker push.
⚠️ checkoutaction wipes out the current directory! Should be run before any actions writing useful things in it (local setup, etc.).
-
Checkout with the input
fetch-depth: 2to get the two last commits (by default, only the last commit is checked out, i.e.git fetch --depth=1) -
Use
git diff --quiet --exit-code HEAD^ HEAD -- ‹path›to check if a file changed.
⚠️ Commands should succeed (with return code 0). Useif-then-else-fito control the result ofgit diff.
-
Can be done in another job, using job outputs and conditions.
-
We only want to build the image if
Dockerfilehas changed, but the main job should be run even if the build job has been skipped: usealways()and checkneeds.‹job_id›.resultforsuccessorskipped.
-
Storing workflow data as artifacts:
actions/upload-artifact@v3with inputsnameandpath,actions/download-artifact@v3with inputname. -
softprops/action-gh-release with input
files
-
In Project Settings › Actions › Runners, button New self-hosted runner. Follow the instructions. Tags match the values of
runs-on:field. -
./run.shcan be run intmuxor as a service.
- Annotations: error/notice/warning
echo "::error file=app.js,line=1::Missing semicolon"
echo "::add-matcher::matcher.json"
Matcher for gcc: ammaraskar/gcc-problem-matcher@master
- Grouping log lines
::group::{title}
::endgroup::
- Masking a value
::add-mask::{value}
- Setting an environment variable
echo "{environment_variable_name}={value}" >> $GITHUB_ENV
- Output parameter (steps seeting outputs should have
id:)
echo "{name}={value}" >> $GITHUB_OUTPUT
In subsequent steps, refer to `${{ steps.{id}.outputs.{name} }}"
- Job summary
echo "### Hello world! :rocket:" >> $GITHUB_STEP_SUMMARY
- Adding a system path
echo "{path}" >> $GITHUB_PATH
Docker and registry
Docker is a tool to run programs in containers, that is to say
-
sandboxes that share the same kernel as the running OS,
-
but in a
chroot(isolated filesystem), -
with limited access to resources (process groups, network, and more generally limited system calls).
container: key specifies a Docker image (otherwise, the job runs directly on the VM).
Build environments can be prepared once for all in a Docker image to reduce build times:
-
docker build -t ghcr.io/‹user›/‹image name› . -
create a personal access token with scope
write:packages, save it in a file -
docker login ghcr.io -u ‹user› --password-stdin < ‹token path› -
docker push ghcr.io/‹user›/‹image name› -
create a personal access token with scope
read:packages, store it in a secret (usinggh secret set) -
reference the container in the job
container:
image: ghcr.io/‹user›/‹image name›
credentials:
username: ${{ github.actor }}
password: ${{ secrets.‹secret name› }}- to run the workflow locally, use
act --secret-file ‹file name›
-
Store a personal access token with scope
write:packagesin a secret. -
Check out the repository! Add the following action
- name: Checkout
uses: actions/checkout@v3
- Steps for
docker buildanddocker push.
⚠️ checkoutaction wipes out the current directory! Should be run before any actions writing useful things in it (local setup, etc.).
-
Storing workflow data as artifacts:
actions/upload-artifact@v3with inputsnameandpath,actions/download-artifact@v3with inputname. -
softprops/action-gh-release with input
files
- name: Deploy
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: build
-
3 types of actions can be created: Docker, Javascript and Composite
-
Docker actions can only be used on Linux runners
-
Composite actions combines multiple workflow steps in a single action
-
An action is described by a single
action.ymlfile -
One can define the inputs, outputs end environnement variables of an action
-
If the action is designed to be reusable and public, use a dedicated public repository for the action The name of the action corresponds to the name of the repo, e.g
orga/repo name@branch/tag name -
If the action is local to a repository, place the yml file in
.github/actions/‹action name›/action.yml -
Local actions are used in a workflow as follows, the checkout action must be called before:
- uses: actions/checkout@master
- name: Run local custom action
uses: ./.github/actions/local-action
...-
The Docker action can use a
Dockerfile=> GitHub will build the image when the action is run
-
javascript actions require
node_modules/to be commited
-
GitHub automatically detect that the repo contain an action




