Note: You do not need to clone the repository. The whole practical session can be completed directly on GitHub.
The goal of this practical session is to complete two GitHub Actions workflows:
.github/workflows/ci.yml.github/workflows/cd.yml
The two workflows have different roles:
- CI (Continuous Integration) checks that the CV is valid and that the website can be correctly generated.
- CD (Continuous Deployment) takes the website produced by CI and deploys it to GitHub Pages.
The final pipeline should work like this:
cv.yml
↓
CI
├── Validate CV
├── Build website
└── Upload website artifact
↓
CI succeeds
↓
CD
├── Download artifact
└── Deploy to GitHub Pages
Important: cd.yml must depend on ci.yml succeeding. It must not run independently on every push, and it must never deploy if CI has failed.
Do not start cd.yml until ci.yml works correctly.
Before creating the workflows, you should understand what happens when you modify the CV.
The main files and folders are:
_data/cv.yml
This file contains the CV data: name, education, experience, skills, etc.
It is not an HTML file. You only provide structured data in YAML.
The file schemas/cv-schema.yml defines the expected structure of cv.yml.
It specifies which fields are required and what type of value they must contain.
For example, a name should be a string, not a number.
The website itself is generated using Jekyll.
Jekyll uses the data from cv.yml together with HTML templates. These templates use Liquid, which allows values from cv.yml to be inserted automatically into the HTML.
When Jekyll builds the project:
cv.yml + templates
↓
Jekyll
↓
_site/
↓
HTML / CSS / other static files
The _site directory therefore contains the actual static website that can be deployed to GitHub Pages.
In this practical session, you will automate this process:
You edit cv.yml
↓
CI checks the CV
↓
Jekyll builds the website
↓
CI stores the generated website (as an artifact)
↓
CD retrieves it
↓
GitHub Pages publishes it
Before creating the workflows:
- Create your own repository from this repository using Use this template.
- Open Settings → Pages.
- Set Source to GitHub Actions.
- Go into _config.yml and set the baseurl and url as the comment explain it
Commit your changes.
The first workflow you must complete is:
.github/workflows/ci.yml
!! (You must delete the job named placeholder in ci.yml before starting, same for workflow_dispatch) !!
The purpose of CI is to check that the CV is valid and that the website can be generated successfully.
The workflow must run:
- on every push;
- on every pull request targeting
main.
A CI job named build must perform the following steps in this order.
( runs-on: ubuntu-latest )
Retrieve the repository contents on the GitHub Actions runner.
Use:
actions/checkout
The workflows must use the GrantBirki/json-yaml-validate action to validate the _data/cv.yml file against the yaml schema schemas/cv-schema.yml
Action details : https://github.com/marketplace/actions/json-yaml-validate
The workflow must fail if:
cv.ymlcontains invalid YAML;cv.ymldoes not respect the schema.
(You will test that later)
The project uses Ruby/Jekyll.
Use:
ruby/setup-ruby
Action details : https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
(Enable bundler caching)
Run the project's build command :
bundle exec jekyll build
The build generate the static website in:
_site/
The CI job must fail if the website cannot be generated (next step).
Verify that the expected website files have actually been generated.
For example, check that _site/index.html exists with this command :
test -f _site/index.html
To upload _site as a GitHub Actions artifact.
Use:
actions/upload-artifact
Action details : https://github.com/marketplace/actions/upload-a-build-artifact
Give the artifact an explicit name (ex: jekyll-site) and the proper path (here its: ./_site)
You will need this exact name later in cd.yml.
Important: cd.yml workflow must deploy this artifact. It must not build the website again.
Only start this part once your CI workflow works correctly.
The purpose of CD is to deploy the website generated by CI to GitHub Pages.
!! (You must delete the job named placeholder in cd.yml before starting, same for workflow_dispatch) !!
CD must use the website produced by CI.
It must not rebuild the website.
The final process must therefore be:
CI
↓
Build website
↓
Upload artifact
↓
CI succeeds
↓
CD starts
↓
Download CI artifact
↓
Deploy artifact
CD must start when the CI workflow completes.
It must only run when:
- the CI workflow completed
- the CI workflow ran for
main.
Use the GitHub Actions workflow_run event.
A CD job named deploy must perform the following steps in this order.
( runs-on: ubuntu-latest )
Use:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
Retrieve the artifact produced by the corresponding CI run.
Use:
actions/download-artifact
Action details : https://github.com/marketplace/actions/download-a-build-artifact
The artifact must come from the same CI run that triggered the CD workflow.
Prepare the downloaded website for GitHub Pages.
Use:
actions/upload-pages-artifact
Action details : https://github.com/marketplace/actions/upload-github-pages-artifact
Deploy the Pages artifact.
Use:
actions/deploy-pages
Action details : https://github.com/marketplace/actions/deploy-github-pages-site
Configure only the permissions required for GitHub Pages deployment.
Also configure a concurrency group to prevent overlapping deployments.
Once both workflows are implemented, test the complete pipeline.
You can go to Actions to check if your workflows succed or not.
-
Does the complete pipeline succeed with
cv.yml? Do you notice any errors or inconsistencies ?→ you can check the CV at https://[YOUR_USERNAME].github.io/[REPO_NAME]/
(Reload the page after a new deployment to apply modifications)
A file named cv_broken.yml is provided. It contains several intentional errors.
Copy the content of cv_broken.yml into your _data/cv.yml and run the pipeline again.
For each error you find:
- Was it detected by the CI/CD pipeline?
- If it was detected, fix it and explain why it caused an error.
- If it was not detected, explain why and suggest how the pipeline could be improved to detect this type of error.
You can now modify _data/cv.yml with your own information.
Commit your changes, then verify that your CV is correctly built and deployed to GitHub Pages (on https://[YOUR_USERNAME].github.io/[REPO_NAME]/)
(Reload the page after a new deployment to apply modifications)
permissions:
actions: read
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false- name: Download site artifact from CI
uses: actions/download-artifact@v4
with:
name: jekyll-site # must match the artifact name uploaded by upload-artifact in CI
path: ./_site
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
run-id: ${{ github.event.workflow_run.id }}