Recent update of GitLab brought renaming of several things. Most notably for us, Issues were generalized into Work items. We will try to update the materials to reflect the new naming as soon as possible.

This page describes how the on-site tests will look like and eventually will also contain description of the (big) homework assignment.

Please, have a look at the course guide page for details how the grading works.

On-site tests

This is the schedule for the on-site tests. The test will be held at the beginning of the lab (duration of the test is 45 minutes).

Week (date) Topic
09 (April 13 - April 17) T01: Git versioning system
12 (May 4 - May 7 + May 15) T02: Shell scripting
14 (May 18 - May 22) T03: make build tool

You are expected to come to the lab you have enrolled to.

Because of state holiday on May 8, the T2 examination for Friday labs will be postponed by a week. We are aware it is not optimal but the schedule for this semester has virtually no complete week (i.e., teaching in all days of a week) during the second half of the semester.

Test will be written on school machines. Make sure you can login there.

You are allowed to use our webpages, off-line manpages and you can consult your notes and solutions to examples that are part of the lab materials.

You are not allowed to use any other devices (cell phones, your own laptops etc.), consult other on-line resources (the machines will have restricted access to the Internet anyway) or communicate your solution to other students (and vice versa).

If you are using a password manager for your CAS/SIS account, please, write your password on a paper or temporarily change it to something you can remember for the duration of the exam.

(Allowing use of cell-phones/notebooks/… only at the beginning of the exam has too many drawbacks for the overall organization. Sorry for the incovenience.)

In other words, the on-site tests require that you can solve the tasks on your own with technical documentation only.

We kindly ask you to leave your devices in your backpacks during the exam and leave the backpacks in front of the blackboard or on some other visible (but unreachable) place to ensure equal conditions for everyone. Thank you!

Any attempt to bypass the above rules (e.g. trying to use AI assistant on your cell phone) means failing the course on the spot.

You are free to ask for clarification from your teacher if you do not understand the assignment, obviously. We can provide limited hints if it is clear that you are heading in the right direction and need only a little push.

Please, see also the general rules in the course guide.

Format of the exam

Your solution will be submitted to a Git repository: make sure you can perform a clone via a command-line client.

Test will be written on school machines. During the exam you will use a temporary account: you will not have access to any of your files from the AFS home. At the beginning of the exam, you will generate a new SSH key pair, upload it to our keyserver and then clone the Git repository with the actual exam.

Pro tip: do not add a passphrase to the temporary SSH key. It will be used only during the 45 minutes of the exam and having no passphrase will speed-up your network operations.

The temporary account on the school machines will be prepared for the exam. There will be some shortcuts (see below) for easier access to the repositories you will need but for certain customizations your action will be needed.

Because you will be uploading the solution to a Git repository in Gitolite (you have worked with it during lab 05), there will be an exam alias available. Therefore, you will be able to clone the repositories simply by calling

git clone exam:REPO

instead of

git clone gitolite3@linux.ms.mff.cuni.cz:REPO

Similarly, for uploading your SSH key (that you will need to generate at the beginning of the exam), you would be able to use a shortcut of

ssh-copy-id keyserver

instead of

ssh-copy-id -p 2222 LOGIN@linux.ms.mff.cuni.cz

You will also have a read-only access to the config-LOGIN repository on Gitolite where you can store your own shell and Git customization (e.g., aliases, own prompt etc.).

You can also store your notes into the config-LOGIN repository so that you do not need to print them. Do not store there anything that might be contrary to the course rules (this includes, for example, AI agents or exam solutions from your colleagues). Also, please, keep the repository small (under 5MB). Thank you.

Detailed information about the config-LOGIN repository is on a separate page.

You can try to run the ssh-copy-id -p 2222 LOGIN@linux.ms.mff.cuni.cz even before the exam to try it but you will need to generate a new key pair during the exam anyway.

Notes for the Git CLI exam

Information for students enrolled to the special 25bNSWI177x13 Friday lab.

If your SIS/GitLab username starts with [a-j], please, come at 8:50; if your login starts with [k-z], please, come at 9:40.

Instructions for the exam will be provided in a printed form. They will also include a hint how to generate the SSH key pair and how to upload it to our keyserver.

You will be expected to perform the following tasks in Git from the command-line.

  • Configure your Git environment (author and e-mail)
  • Clone a repository (from gitolite3@linux.ms.mff.cuni.cz or generic HTTPS)
  • Create a commit
  • Create a branch
  • Switch between branches
  • Merge a branch (and solve any conflicts)
  • Push changes (branches) to server

You will not be required to write any script on your own from scratch but we will be working with a repository containing the following script for printing simple bar charts in the console. You will be required to make some small modifications (such as fixing typos) but we will always guide you to the right place in the code.

The focus of the exam is on working with Git but you must be able to make the above mentioned modifications correctly. In other words, the Python script has to be functional all the time (i.e. if you create a branch correctly but the script fails with a syntax error, it is a fundamental error).
import argparse
import sys

def parse_config():
    args = argparse.ArgumentParser(description='Console bar plot')
    args.add_argument('--columns', default=60, type=int, metavar='N')
    return args.parse_args()

def load_input(inp):
    values = []
    for line_raw in inp:
        line = line_raw.strip()
        if line.startswith('#') or not line:
            continue
        try:
            val = float(line)
        except ValueError:
            print(f"WARNING: ignoring invalid line '{line}'.", file=sys.stderr)
            continue
        values.append(val)
    return values

def print_barplot(values, scale, symbol):
    for val in values:
        print(symbol * round(val / scale))

def main():
    config = parse_config()
    values = load_input(sys.stdin)
    if not values:
        sys.exit(0)
    coef = max(values) / config.columns
    print_barplot(values, coef, '#')

if __name__ == '__main__':
    main()

Notes for the Shell scripting exam

Information for students enrolled to the special 25bNSWI177x13 Friday lab.

If your SIS/GitLab username starts with [a-j], please, come at 8:50; if your login starts with [k-z], please, come at 9:40.

The following list capture the topics (constructs, commands, …) you are expected to know for the exam. The list is not exhaustive (for example, we do not mention all the commands from our mini manual but covers all the major parts.

  • Construct a short pipeline with basic utilities such as cut, uniq, paste, bc or sort.
  • Use I/O redirection.
  • Iterate through lines of a file in a manner of while read ...; do ...; done < input.txt.
  • Use if, for and while constructs.
  • Use test or [ for controlling shell loops and conditions.
  • Capture standard output via $( cmd ).
  • Source external scripts via source or . (dot).
  • Use shell variables and shell functions to better capture the intent of data flow.
  • Understand getopts argument parsing.
  • Use basic regular expressions for searching (grep) or trivial replacements (via sed).
You will submit your solution again through a Git repository (as for T01). Make sure you remember Git basics (you will not need branching but you will not be able to submit without knowing at least about clone, commit and push).
Unless explicitly allowed, you cannot escape to another language (such as Python, AWK or PERL) during your implementation. In other words, submitting the solution as python3 -c 'import sys; for line in sys.stdin ... is not allowed.

The format of the exam will follow this pattern. You will receive an almost complete implementation of a certain assignment. Your task will be to implement the missing functions to complete the assignment.

The assignment will be split into different shell functions that you will implement. We will provide some basic (automated) tests that will be checking correctness of the individual functions (i.e. while it is recommended to read the whole script to understand the intent of it, it will be possible to implement some of the functions in isolation).

The code that we will work with, including example tasks and automated tests, is available at gitolite3@linux.ms.mff.cuni.cz:t02-example in the 2026 subdirectory.

During the exam we will work with the same baseline code but for each lab there will be slight modifications of the actual assignment.

Please, use this opportunity to see how the code looks like (the skeleton will be the same) or how the tests are organized. It can save you some time during the exam and let you focus on the important aspects instead of deciphering how the files are organized.

Inside the same repository is also an archive subdirectory with exams from last year that you can use for practice: they are built around a different codebase but the complexity of the assignments is about the same as we plan for this year.

Notes for the make build tool exam

Information for students enrolled to the special 25bNSWI177x13 Friday lab.

If your SIS/GitLab username starts with [a-j], please, come at 8:50; if your login starts with [k-z], please, come at 9:40.

You will be expected to perform the following operations with Makefile (some might be required to execute on the remote machine linux.ms.mff.cuni.cz).

  • Build a project (or its component) using make
  • Understand existing Makefile
  • Make updates to the Makefile
    • Fix list of dependencies
    • Fix command invocation for a particular target
    • Merge multiple rules into a pattern rule
    • Add a new target to Makefile with correctly derived dependencies
  • Create a simple Makefile from scratch with dependencies derived from provided commands
  • It will not be necessary to use non-portable extensions such as $(addsuffix ...)
You will submit your solution again through a Git repository (as for T01). Make sure you remember Git basics (you will not need branching but you will not be able to submit without knowing at least about clone, commit and push).

For practices, there are several example in the materials for lab 10.


Furthermore, it is possible to clone gitolite3@linux.ms.mff.cuni.cz:lab10-hp where you can try converting a project to use make instead of a shell script.

The project uses Translate Toolkit to manage translations and your Makefile should take care that translation files are properly updated. More details are in the repository itself.

Quizzes

Quizzes will be given on labs 02, 03, 04, 05, 06 and 07 (and 08 for Friday labs).

Small homework tasks

Big homework: project setup

Setup a CI for Python based project and prepare it for further distribution. This will include the following tasks (explained in more detail below).

  • Make the source code into proper Python package.
  • Create GitLab CI job for pytest (after merging their implementation/fixes).
  • Create GitLab CI job for BATS tests (after some fixes and another Git merge).

We expect you will use external tools to drive your implementation but you must understand all the parts before submitting it and you must mark all parts that were not authored by you personally (and if you are using tools such as ChatGPT, you must submit the whole log of your communication with the tool).

Context

In this task you will be working with a simple Python project that is able to render Jinja templates (install Jinja2 package, not Jinja).

As a trivial example (which you can also find in the examples subdirectory of the project repository) it will be able to perform the following transformation.

We will have the following array (list) in JSON:

[
  {
     "name": "Introduction to Linux",
     "code": "NSWI177",
     "homepage": "https://d3s.mff.cuni.cz/teaching/nswi177/"
  },
  {
     "name": "Linux Administration",
     "code": "NSWI106",
     "homepage": "https://d3s.mff.cuni.cz/teaching/nswi106/"
  }
]

We will have the following input file:

Our courses
===========

Below is a list of (almost) all of our courses.

And we will have the following template. Note that control structures of the template use {% (or {%- to strip surrounding whitespace) and {{ for variable expansion.

{{ content }}

{%- for course in data -%}
 * [{{ course.name }} ({{ course.code }})]({{ course.homepage }}) {{ NL }}
{%- endfor %}

When executed with our renderer (exact command is in the project README), we will get the following output.

Our courses
===========

Below is a list of (almost) all of our courses.

* [Introduction to Linux (NSWI177)](https://d3s.mff.cuni.cz/teaching/nswi177/)
* [Linux Administration (NSWI106)](https://d3s.mff.cuni.cz/teaching/nswi106/)

Source code

The source code for the above implementation was already prepared for you and soon you will have access to a new project under teaching/nswi177/2026 subtree in GitLab where you will work.

Do not copy this code to your normal submission repository and work in the new project-LOGIN repository (except for the ai.log as explained below).

The repository also contains several tests. There are unit tests in Python (using pytest) as well as higher-level tests (let us call them integration tests even that might be a bit overstated) written in BATS.

The invocation is described in the project README.

Commit only files that ought to be committed. Definitely do not commit your virtual environment directories, __pycache__ subdirectories or Pythonic .egg and .whl files.

The assignment

Your main task is to setup basic CI on GitLab for this project and prepare the project for distribution.

The CI must execute the Python unit tests and fail the job on any error. The preparation for distribution means that after your changes we will be able to install the templater via pip and have the templater available as nswi177-jinja-templater command.

Your task is not to copy the project to PyPI but only setup your repository on our GitLab.

In other words, the following commands would install the templater into a fresh virtual environment and the invocation of the last command would print a short help from our program (we assume we are in an empty directory that is not related in any way to any clone of your project).

python3 -m venv templater-venv
. ./templater-venv/bin/activate
pip install git+ssh://git@gitlab.mff.cuni.cz/teaching/nswi177/2026/project-LOGIN
nswi177-jinja-templater --help

And for the CI we expect that your project would have a job unittests running the Python tests.

Please, make sure you name the job unittests and you keep all your CI configuration in a single .gitlab-ci.yml file.

The CI should use the python:3.13-alpine image and should install the versions from requirements.txt file. We expect that pytest (and perhaps other test-related libraries) will not be mentioned in the requirements.txt but rather inside requirements-dev.txt file.

You will notice that the tests are not passing as some of the Jinja filters are not implemented.

Do not worry, though. Your coworker Alice already implemented them in her branch in her repository gitolite3@linux.ms.mff.cuni.cz:templater-alice.

Merge her implementation into your repository to get the full implementation.

The merging is a required part of the task and we require that you perform a normal merge (or a fast-forward) but never a rebase.

If you do everything correctly, your CI job log would look like this (we have blurred the used commands for obvious reasons).

Then you will extend the CI to also execute the BATS tests.

We expect that you will add a new job called integrationtests that installs the package (so that the nswi177-jinja-templater command is available) and run all the BATS files in the tests subdirectory (recall that simple pip install . should work like a charm).

For unittests you install dependencies from requirements.txt for best reproducibility while for integrationtests we install the whole package, thus usually with relaxed requirements on the exact versions of the dependencies.

You will need to install bats via apk add first (it is okay to install this package on every CI run).

Note that the current implementation in common.bash invokes the program via call to env PYTHONPATH=src python3 -m nswi177.templater – change this to call nswi177-jinja-templater instead. You will also need to replace --kill-after switch for the timeout command to plain -k as the long variant is not supported in Alpine.

The amount of BATS tests is quite low so you should also merge the work of your co-workers Bob and Charlie into your repository. Again, perform a normal merge and not a rebase when integrating their work.

Bob has his repository at gitolite3@linux.ms.mff.cuni.cz:templater-bob while Charlie put his copy to our website to https://d3s.mff.cuni.cz/f/teaching/nswi177/202526/templater-charlie.git.

In case of conflicts make sure you resolve them correctly – you certainly do not want to drop any of the tests unless they are the same.

To summarize the subtasks, following list might help you.

  • Merge Alice implementation.
  • Setup pyproject.toml, setup.cfg and requirements.txt (and requirements-dev.txt) for project-login project on GitLab.
  • Setup GitLab CI that runs the Python tests in unittests job.
  • Merge tests from Bob and Charlie.
  • Fix invocation of the command in BATS tests.
  • Fix call to timeout to be timeout -k 30 "${timeout}" "$@".
  • Add integrationtests job to run all the BATS tests.

Submission and grading

Submit your solution into the project-LOGIN repository on GitLab.

We will check that the project can be installed via pip install git+https://gitlab.../project-LOGIN/ and that your CI configuration is correct (after all the merges your jobs should be in the green). We will check that the Python code can be executed after pip install -r requirements.txt via python3 -m src.nswi177.templater (or via python -m nswi177.templater if the package itself is also installed) and that the Pytests can be run after installing from requirements-dev.txt.

When you copy fragments from sites such as StackOverflow we expect you will comment them directly in the appropriate sources, communication with AI-driven sites should be stored into exam/project/ai.log file in your normal submission repository (student-LOGIN), again a plain text file with clearly marked portions with your input and with the answers.

There will be automated tests (for your automated tests) available. The tests will be executed on daily basis and their results will appear in your $HOME on linux.ms.mff.cuni.cz.

(We expect these tests will be setup by the end of April.)

Results of the nightly runs are provided as-is: we believe their format is descriptive enough to point you to any potential problematic spots in your solution.

The submission deadline is 2026-05-31.

We will grade the tasks after the deadline. Please, do not ask us for a manual check: we believe the assignment as well as the tests are explanatory enough to guide you towards the right solution without our help.

If you need to complete the course earlier (e.g. because of state exams), please, contact as ASAP.

Please, make sure (e.g., using the list above) you have not forgotten any part. There are no hidden traps or tricks in this assignment, you only need to follow the instructions to complete it successfully.