diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 550ff59cec24951220335bc0cd1aee4e972f7945..2718f5f24e828c1d3b57a8ca8f66f986bf2a068b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,6 +18,7 @@ build: stage: build image: docker.io/python:3.9.7-alpine before_script: + - apk add --no-cache git - pip install pipenv==${PIPENV_VERSION} - unset PIPENV_VERSION - pipenv sync diff --git a/Pipfile b/Pipfile index 430cac11c0c08d1feedc773c85b28cd73925cacb..7f9073d8a92734e856dea4927b5a2acf91693bc0 100644 --- a/Pipfile +++ b/Pipfile @@ -5,6 +5,8 @@ name = "pypi" [packages] mkdocs = "~=1.2.3" +mkdocs-material = "~=7.3.6" +mkdocs-git-revision-date-localized-plugin = "~=0.10.2" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 2c986f693734baf07614c19e894c82348521be29..894f2f0393b7792f225a212eb890720c4724152f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "73260d73b196eb25c7a8f2eaecfb6af799f8f98ca2a2d5f95c1286f46e2cfba9" + "sha256": "eb241c9baf0e485ff9d3998f6c63add07915fc484b2205252e93222c8edc2422" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,14 @@ ] }, "default": { + "babel": { + "hashes": [ + "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9", + "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.1" + }, "click": { "hashes": [ "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3", @@ -39,21 +47,37 @@ ], "version": "==2.0.2" }, + "gitdb": { + "hashes": [ + "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd", + "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa" + ], + "markers": "python_version >= '3.6'", + "version": "==4.0.9" + }, + "gitpython": { + "hashes": [ + "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647", + "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5" + ], + "markers": "python_version >= '3.7'", + "version": "==3.1.24" + }, "importlib-metadata": { "hashes": [ - "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", - "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" + "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100", + "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb" ], "markers": "python_version >= '3.6'", - "version": "==4.8.1" + "version": "==4.8.2" }, "jinja2": { "hashes": [ - "sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45", - "sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c" + "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", + "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7" ], "markers": "python_version >= '3.6'", - "version": "==3.0.2" + "version": "==3.0.3" }, "markdown": { "hashes": [ @@ -154,6 +178,30 @@ "index": "pypi", "version": "==1.2.3" }, + "mkdocs-git-revision-date-localized-plugin": { + "hashes": [ + "sha256:16ffc10407d5e84f0e5248496191d065d611095a12a48cb5070167b4808ae06a", + "sha256:817dd2c897ede4f801673898d454191b280cf0b21650de82b2144e4774b4cd2a" + ], + "index": "pypi", + "version": "==0.10.2" + }, + "mkdocs-material": { + "hashes": [ + "sha256:1b1dbd8ef2508b358d93af55a5c5db3f141c95667fad802301ec621c40c7c217", + "sha256:1b6b3e9e09f922c2d7f1160fe15c8f43d4adc0d6fb81aa6ff0cbc7ef5b78ec75" + ], + "index": "pypi", + "version": "==7.3.6" + }, + "mkdocs-material-extensions": { + "hashes": [ + "sha256:a82b70e533ce060b2a5d9eb2bc2e1be201cf61f901f93704b4acf6e3d5983a44", + "sha256:bfd24dfdef7b41c312ede42648f9eb83476ea168ec163b613f9abd12bbfddba2" + ], + "markers": "python_version >= '3.6'", + "version": "==1.0.3" + }, "packaging": { "hashes": [ "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966", @@ -162,12 +210,28 @@ "markers": "python_version >= '3.6'", "version": "==21.2" }, + "pygments": { + "hashes": [ + "sha256:b8e67fe6af78f492b3c4b3e2970c0624cbf08beb1e493b2c99b9fa1b67a20380", + "sha256:f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6" + ], + "markers": "python_version >= '3.5'", + "version": "==2.10.0" + }, + "pymdown-extensions": { + "hashes": [ + "sha256:01e4bec7f4b16beaba0087a74496401cf11afd69e3a11fe95cb593e5c698ef40", + "sha256:430cc2fbb30cef2df70edac0b4f62614a6a4d2b06462e32da4ca96098b7c1dfb" + ], + "markers": "python_version >= '3.6'", + "version": "==9.0" + }, "pyparsing": { "hashes": [ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.4.7" }, "python-dateutil": { @@ -175,9 +239,16 @@ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, + "pytz": { + "hashes": [ + "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", + "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326" + ], + "version": "==2021.3" + }, "pyyaml": { "hashes": [ "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", @@ -230,9 +301,26 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, + "smmap": { + "hashes": [ + "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94", + "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + }, + "typing-extensions": { + "hashes": [ + "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", + "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", + "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" + ], + "markers": "python_version < '3.10'", + "version": "==3.10.0.2" + }, "watchdog": { "hashes": [ "sha256:25fb5240b195d17de949588628fdf93032ebf163524ef08933db0ea1f99bd685", diff --git a/README.md b/README.md index cc3f135b074d82e39d2b4dc3a8b7a4191120886a..85c03e9e285f804ffced5db43aae747b44fdd3f4 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,14 @@ - Python >= 3.9 - [`pipenv`](https://pipenv.kennethreitz.org/en/latest/) +- [MkDocs](https://www.mkdocs.org/) and [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) + - Included in the [list of dependencies](./Pipfile) that will be installed by + `pipenv` ## Getting Started Assuming `pipenv` present in the shell, create a new virtual environment and -download all of the required dependencies: +install all of the required dependencies into the new virtual environment: ```shell pipenv sync @@ -38,6 +41,12 @@ mkdocs build By default, the built website is written into `site` directory. +## Adding New Content + +Write the new content into a new text file written using Markdown format and +store them in [`docs/`](./docs/) directory. Then, update the navigation section +(i.e., `nav`) in [`mkdocs.yml`](./mkdocs.yml). + ## License Copyright (c) 2021 Faculty of Computer Science Universitas Indonesia. diff --git a/docs/2020/index.md b/docs/2020/index.md new file mode 100644 index 0000000000000000000000000000000000000000..8f1faa324059bafe556154ce6ffeea11786f8373 --- /dev/null +++ b/docs/2020/index.md @@ -0,0 +1,12 @@ +# Course Information (2020) + +Course instructors: + +- [Dr. Ade Azurat](https://rse.cs.ui.ac.id/?open=staff/ade) + > Responsible for the latter half of the course. +- [Daya Adianto, M.Kom.](https://me.adian.to) + > Responsible for the first half of the course. + +Teaching assistants: + +- TBD diff --git a/docs/2020/midexam1.md b/docs/2020/midexam1.md new file mode 100644 index 0000000000000000000000000000000000000000..1c402802c5710d1b980c6b3a149b82fb1a0f20f9 --- /dev/null +++ b/docs/2020/midexam1.md @@ -0,0 +1,264 @@ +# Midterm Exam - Ansible to Docker DevOps + +Some projects in [Pusilkom UI](https://pusilkom.com) have automated provisioning +and deployment implemented using [Ansible](https://www.ansible.com). The +application and environment configuration are parameterised using Ansible +variables that written in [Jinja](https://jinja.palletsprojects.com/en/2.11.x/) +syntax and stored in YAML files. Since some of the variables might contain +sensitive information such as database password or API key, Ansible Vault is +also used to separate sensitive variables to a new file and encrypt it for +storage in the version control system (Git). The variables will only be +decrypted during provisioning and deployment process. + +In recent times, there are requests to prepare a Docker-based deployment using +Docker Compose. One way to configure an application or a component running in +a container is by providing the configuration through environment variables. +To make it easier for DevOps Engineer or System Administrator to provide the +environment variables, usually they write the variables into a text-based file +called `.env` that subsequently will be read by Docker Compose. + +The problem is how to keep existing Ansible-related artefact in place and make +them still usable for Docker-based deployment. Since most of the configuration +are written in YAML files, there must be a way to reuse the configuration +variables in YAML files and transform them into a `.env` file. In addition, +the values for some of the variables might also get passed through environment +variables when run in CI environment. + +The following example is a program that reads YAML files, merge them into single +structure, and print the content as string that can be written into a `.env` +file: + +```python +#!/usr/bin/env python +# File: create_dotenv.py +import os +import re +import sys + +try: + from yaml import safe_load + from yaml.scanner import ScannerError +except ImportError: + print("Cannot find PyYAML module in the environment.", file=sys.stderr) + print("Please install it first using `pip` or other means", file=sys.stderr) + sys.exit(1) + +def is_valid_yaml_files(files: list) -> bool: + ''' + Checks whether the given list of file paths contain all valid YAML files. + + Suppose that we have two valid YML files. If the paths to both files are + passed to the function, then the function should return True. + + >>> import tempfile + >>> with tempfile.NamedTemporaryFile(mode="w", newline="\\n", suffix=".yml") as file1: + ... with tempfile.NamedTemporaryFile(mode="w", newline="\\n", suffix=".yml") as file2: + ... file1.writelines(["---", "a: 1", "b: 2"]) + ... file2.writelines(["d: 3", "e: 4"]) + ... is_valid_yaml_files([file1.name, file2.name]) + True + + Otherwise, the function should return False. + + >>> import tempfile + >>> with tempfile.NamedTemporaryFile(mode="w", newline="\\n", suffix=".yml") as file1: + ... with tempfile.NamedTemporaryFile(mode="w", newline="\\n", suffix=".yml") as file2: + ... file1.writelines(["{a: 1", "b: 2"]) + ... file2.writelines(["d: 3}", "e: 4"]) + ... is_valid_yaml_files([file1.name, file2.name]) + False + + TODO: Fix doctest when run under Windows + ''' + if len(files) == 0: + return False + + try: + for file in files: + with open(file, 'r') as yaml_file: + safe_load(yaml_file) + except OSError as os_error: + print("Cannot open the given file", file=sys.stderr) + print(os_error, file=sys.stderr) + return False + except ScannerError as scanner_error: + print("Unable to parse the given YAML files correctly", file=sys.stderr) + print(scanner_error, file=sys.stderr) + return False + + return True + +def parse_decrypted_vault(main_yaml: dict, vault_yaml: dict) -> dict: + ''' + Replaces every occurences of Jinja variables with the corresponding values + from a decrypted vault file. + + For example, suppose main_yaml and vault_yaml are illustrated as follows: + + >>> main_yaml = {'app_name': 'example', 'db_user': 'bangtoyib', 'db_pass': '{{ vault_db_pass }}'} + >>> vault_yaml = {'vault_db_pass': 'cepatpulang'} + >>> parse_decrypted_vault(main_yaml, vault_yaml) + {'app_name': 'example', 'db_user': 'bangtoyib', 'db_pass': 'cepatpulang'} + + The function should return the dictionary whose keys are the same as the + original dictionary and all of the values with Jinja variables have been + replaced. + + TODO: Handle YAML structure with > 1 level (nested) + ''' + from copy import deepcopy + result_yaml = deepcopy(main_yaml) + + for key, value in main_yaml.items(): + if isinstance(value, str) and re.match(r'{{ vault_(\w)+ }}', value): + result_yaml[key] = vault_yaml[f'vault_{key}'] + + return result_yaml + +def main() -> None: + if is_valid_yaml_files(sys.argv[1:]): + with open(sys.argv[1], 'r') as vars_file: + with open(sys.argv[2], 'r') as vault_file: + yaml = parse_decrypted_vault( + safe_load(vars_file), + safe_load(vault_file) + ) + + for key, value in yaml.items(): + if isinstance(value, str): + contain_variable = re.match(r"{{ (?P<variable>\w+) }}", value) + + if contain_variable: + # Assume environment variable is written in all uppercase + os_variable_name = contain_variable.group('variable').upper() + print(f'{key.upper()}={os.getenv(os_variable_name, "")}') + else: + print(f'{key.upper()}={value}') + else: + print(f'{key.upper()}={value}') + else: + print("One or more YAML files are invalid", file=sys.stderr) + sys.exit(1) + +if __name__ == '__main__': main() +``` + +Actual, but redacted running example: + +```bash +$ python create_dotenv.py \ + ../ansible/inventories/develop/group_vars/all/vars.yml \ + ../ansible/inventories/develop/group_vars/all/vault.yml +APP_DIR=/opt/unhan/euis +APP_USER=unhan +APP_THEME=unhan +APP_SOURCE= +APP_SUPERPASS=bangtoyib! +DATABASE_HOST=192.168.0.162 +DATABASE_PORT=5432 +DATABASE_NAME=euis_demo2 +DATABASE_USERNAME=euis_demo2 +DATABASE_PASSWORD=cepatpulang! +EMAIL_HOST=192.168.0.174 +EMAIL_PORT=25 +EMAIL_USERNAME=no-reply@pusilkom.com +EMAIL_PASSWORD=None +EMAIL_ENCRYPTION=None +PHP_VERSION=7.0 +``` + +The example above reads two YAML files named `vars.yml` and `vault.yml`. +The program replaces all occurences of Jinja variables in the `vars.yml` with +values read from `vault.yml`. In addition, if there are still some Jinja +variables left in the `vars.yml`, the program reads the OS' environment +variables to obtain the values for the remaining Jinja variables. Finally, +any remaining Jinja variables will be assigned with empty values then +printed to the standard output. + +## SQA Problem - Input Space Partitioning + +> _Estimated time: 5 minutes_ + +You are asked to **design an input space model for the API by following a functionality-based approach.** +The information required to develop the model can be derived by reading the code +snippet. + +Your tasks are as follows: + +1. Determine the characteristics and the partition for a function chosen by the + proctor. + > Possible functions: + > + > - `is_valid_yaml_files()` + > - `main()` + > - The whole script, i.e. `create_dotenv.py` + +2. Based on the input space model that you have created, create the test + requirement and the test cases based on certain coverage criteria chosen by + the proctor. + + > Possible coverage criteria choices: + > + > - All Combinations Coverage (ACoC) + > - Each Choice Coverage (ECC) + > - Pair-Wise Coverage (PWC) + > - Base Choice Coverage (BCC) + > + > _Note: **You do not have to write all test cases due to the time limit.** + > However, make sure you can justify your subset of test cases match with + > the chosen coverage criteria!_ + +Write your answer in a sheet of paper or Microsoft Word/Google Docs document. +You may include illustrations in your answer. Please prepare to present your +answer remotely via Zoom/Google Hangouts during discussion time. + +## SQA Problem - Graph Coverage + +> _Estimated time: 5 minutes_ + +You are asked to design a **control flow graph (CFG), prepare the test +requirement, and create the test paths.** + +Your tasks are as follows: + +1. Create the CFG for a function chosen by the proctor. + > Possible functions: + > + > - `is_valid_yaml_files()` + > - `main()` + > - The whole script, i.e. `create_dotenv.py` + +2. Based on the CFG that you have created, create the test requirement and the + test paths based on certain coverage criteria chosen by the proctor. + > Possible coverage criteria choices: + > + > - Node Coverage (NC) + > - Edge Coverage (EC) + > - Edge-Pair Coverage (EPC) + > + > _Note: **You do not have to write all test paths due to the time limit.** + > However, make sure you can justify your subset of test paths match with + > the chosen coverage criteria!_ + +Write your answer in a sheet of paper or Microsoft Word/Google Docs document. +You may include illustrations in your answer. Please prepare to present your +answer remotely via Zoom/Google Hangouts during discussion time. + +## SQA Problem - Discussion + +> _Estimated time: 10 minutes_ + +You are asked to present your answers to the given problems and also to have +one-on-one interview with the proctor during the discussion time. + +The list of topics that might be discussed is as follows: + +- Code coverage (line coverage) +- Test-Driven Development (TDD) +- Test isolation +- Writing test cases in Java (JUnit)/Python (`unittest` and Django)/PHP + (PHPUnit) +- Your experience in conducting SQA activities in academics and/or work + environment +- The ideas of mutation testing +- And many more that may still related to SQA diff --git a/docs/2020/midexam2.md b/docs/2020/midexam2.md new file mode 100644 index 0000000000000000000000000000000000000000..842cd99b54558ad9ae3bb8ed0829052d1c4ca4a2 --- /dev/null +++ b/docs/2020/midexam2.md @@ -0,0 +1,100 @@ +# Midterm Exam - Lion Game (Backend) + +This project provides an API that allows Lion Game communicate with Google +Sheets-based backend for storing play session analytics. The source code is +available [here](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend). + +## SQA Problem - Input Space Partitioning + +> _Estimated time: 5 minutes_ + +You are asked to **design an input space model for the API by following a functionality-based approach.** +The minimal information required to develop the model can be derived by +reading the API documentation available in [`README.md`](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend/-/blob/master/README.md) +file. + +Your tasks are as follows: + +1. Determine the characteristics and the partition for a function chosen by the + proctor. + > Possible functions: + > + > - The request handler function for `/api/logs/` endpoint. + > - The request handler function for `/api/logs/batch` endpoint. + > + > The body of both functions can be inspected in [`App.php`](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend/-/blob/master/src/App.php). + +2. Based on the input space model that you have created, create the test + requirement and the test cases based on certain coverage criteria chosen by + the proctor. + + > Possible coverage criteria choices: + > + > - All Combinations Coverage (ACoC) + > - Each Choice Coverage (ECC) + > - Pair-Wise Coverage (PWC) + > - Base Choice Coverage (BCC) + > + > _Note: **You do not have to write all test cases** due to the time limit. + > However, make sure you can justify your subset of test cases match with + > the chosen coverage criteria!_ + +Write your answer in a sheet of paper or Microsoft Word/Google Docs document. +You may include illustrations in your answer. Please prepare to present your +answer remotely via Zoom/Google Hangouts during discussion time. + +## SQA Problem - Graph Coverage + +> _Estimated time: 5 minutes_ + +You are asked to design a **control flow graph (CFG), prepare the test +requirement, and create the test cases.** + +Your tasks are as follows: + +1. Create the CFG for a function chosen by the proctor. + > Possible functions: + > + > - The request handler function for `/api/logs/` endpoint. + > - The request handler function for `/api/logs/batch` endpoint. + > - `isValidData()` function. + > - `appendValues()` function. + > + > The definition of request handler functions and `isValidData()` can be + > inspected in [`App.php`](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend/-/blob/master/src/App.php). + > The `appendValues()` function definition is available in [`SheeetsService.php`](https://gitlab.cs.ui.ac.id/bukan-macan-ternak/liongame-backend/-/blob/master/src/service/SheetsService.php). +2. Based on the CFG that you have created, create the test requirement and the + test paths based on certain coverage criteria chosen by the proctor. + + > Possible coverage criteria choices: + > + > - Node Coverage (NC) + > - Edge Coverage (EC) + > - Edge-Pair Coverage (EPC) + > + > _Note: **You do not have to write all test paths due to the time limit.** + > However, make sure you can justify your subset of test paths match with + > the chosen coverage criteria!_ + +Write your answer in a sheet of paper or Microsoft Word/Google Docs document. +You may include illustrations in your answer. Please prepare to present your +answer remotely via Zoom/Google Hangouts during discussion time. + +## SQA Problem - Discussion + +> _Estimated time: 10 minutes_ + +You are asked to present your answers to the given problems and also to have +one-on-one interview with the proctor during the discussion time. + +The list of topics that might be discussed is as follows: + +- Code coverage (line coverage) +- Test-Driven Development (TDD) +- Test isolation +- Writing test cases in Java (JUnit)/Python (`unittest` and Django)/PHP + (PHPUnit) +- Your experience in conducting SQA activities in academics and/or work + environment +- The ideas of mutation testing +- And many more that may still related to SQA diff --git a/docs/2021/ex1.md b/docs/2021/exercise1.md similarity index 84% rename from docs/2021/ex1.md rename to docs/2021/exercise1.md index 826bc1b50bcf49907bf36b1201377d887e6ccf69..766f2c4ff99f71811c47dc263f90ed7a5aff704d 100644 --- a/docs/2021/ex1.md +++ b/docs/2021/exercise1.md @@ -3,17 +3,18 @@ You are asked to set up a CI/CD pipeline of the your group project **individually** by forking the existing group project codebase and updating the CI/CD configuration. As part of the exercise, you also need to prepare -your own VM on Google Cloud Platform (GCP) and explore how to use Static -Application Security Testing (SAST) on self-hosted GitLab (GitLab CSUI). +your own VM on GCP and explore how to use SAST on a self-hosted GitLab (i.e. +GitLab CSUI). For your information when setting up the GitLab CI/CD configuration that will be run on GitLab CSUI, the following is the overview of the CI infrastructure in our faculty: - We run GitLab CSUI using GitLab Enterprise Edition version 13.12.15. -- The CI server runs 8 instances of GitLab Runner version 13.12.0. +- The CI server runs 8 instances of [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) + version 13.12.0. - Each instance is running as a container with limited resources (2 CPU per - container) and disabled the privileged mode. Hence, it is not possible to + container) and the privileged mode disabled. Hence, it is not possible to run a Docker-in-Docker (DIND) type of CI job. - Each instance shares the cache between CI jobs using [Minio](https://min.io/). - Each instance is also limited to run single CI job at a time. @@ -39,7 +40,8 @@ with a teaching assistant to demonstrate your work. 5. [ ] Add the SAST job into the CI/CD pipeline of your own fork and make sure it runs. > Due to [an ongoing issue on running the latest SAST image](https://gitlab.com/gitlab-org/gitlab/-/issues/344022), - > pin the version of SAST analyser image to version 2.28.5. + > pin the version of SAST analyser image to version 2.28.5 in the CI/CD + > configuration file. 6. [ ] Arrange an one-on-one meeting with a teaching assistant to demonstrate your work. You are expected to be able to: - Explain the process of setting up the deployment environment of your group @@ -54,3 +56,8 @@ with a teaching assistant to demonstrate your work. - [GitLab CI/CD Reference on GitLab CSUI](https://gitlab.cs.ui.ac.id/help/ci/yaml/README.md) - [SAST Documentation on GitLab CSUI](https://gitlab.cs.ui.ac.id/help/user/application_security/sast/index.md) + +*[CSUI]: Faculty of Computer Science Universitas Indonesia +*[GCP]: Google Cloud Platform +*[SAST]: Static Analysis Security Testing +*[VM]: Virtual Machine diff --git a/docs/images/favicon.png b/docs/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..b0c8719e1546b0910d76d7cbb89f00fff1e2d562 Binary files /dev/null and b/docs/images/favicon.png differ diff --git a/docs/images/logo.png b/docs/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..60f6f753178d383bb61644f9044ffb7be8d17df7 Binary files /dev/null and b/docs/images/logo.png differ diff --git a/mkdocs.yml b/mkdocs.yml index 7f56b24c84338a4fdfea3a1e3c87a6a05e0a66be..47e6be703a81fd8207dcd62ee98abf72fef646e4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,9 +8,52 @@ copyright: Copyright © 2021 Faculty of Computer Science Universitas Indones repo_url: https://gitlab.cs.ui.ac.id/pmpl/course-site repo_name: GitLab @ CSUI +edit_uri: "" + +theme: + name: material + features: + - navigation.tabs + - navigation.indexes + - navigation.top + logo: images/logo.png + favicon: images/favicon.png + icon: + repo: fontawesome/brands/gitlab + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deep orange + toggle: + icon: material/toggle-switch-off-outline + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: deep orange + toggle: + icon: material/toggle-switch + name: Switch to light mode + +plugins: + - git-revision-date-localized: + type: iso_datetime + enable_creation_date: true + +markdown_extensions: + - abbr + - pymdownx.highlight: + linenums: true + - pymdownx.superfences + - pymdownx.snippets + - pymdownx.tasklist: + custom_checkbox: true nav: - Home: index.md - Year 2021: - - Course Page: 2021/index.md - - Exercise 1: 2021/ex1.md + - 2021/index.md + - Exercise 1: 2021/exercise1.md + - Year 2020: + - 2020/index.md + - Midterm Exam 1: 2020/midexam1.md + - Midterm Exam 2: 2020/midexam2.md