├── .gitignore ├── Workshop - CI_CD ├── 01_introduction.md ├── 02_understanding.md ├── 03_recapping.md ├── 04_setup.md ├── 05_pipeline.md ├── 06_automation.md ├── 07_environments.md ├── 08_deploying.md ├── 09_monitoring_and_logging.md ├── 10_best_practices_and_pitfalls.md ├── 11_resources.md └── assets │ ├── images │ ├── 01 How it works.svg │ ├── 02 Feature branches.svg │ ├── 03 Release branches.svg │ ├── 04 Hotfix branches.svg │ ├── actions-menu.png │ ├── add_environment.png │ ├── big_bang_deployment.svg │ ├── blue_green_deployment.svg │ ├── canary_deployment.svg │ ├── cd_overview.svg │ ├── ci-meme.png │ ├── ci_cd_overview.svg │ ├── ci_overview.svg │ ├── code-coverage.png │ ├── environment_overview.png │ ├── extended-action-wtih-testing.png │ ├── feature_deployment.svg │ ├── finished-job-example.png │ ├── python-application-action.png │ ├── rolling_deployment.svg │ ├── running-job-example.png │ └── settings.png │ ├── plantuml │ ├── cd.puml │ ├── ci.puml │ ├── ci_cd.puml │ └── deployment_strategies │ │ ├── big_bang.puml │ │ ├── blue_green.puml │ │ ├── canary.puml │ │ ├── feature.puml │ │ └── rolling.puml │ └── python-app.yml ├── Workshop - GIT ├── 01_introduction.md ├── 02_setup.md ├── 03_basics.md ├── 04_repositories.md ├── 05_branching.md ├── 06_collaboration.md ├── 07_tips.md └── 08_resources.md ├── Workshop - Operating systems and Bash ├── 01_introduction.md ├── 02_navigation.md ├── 03_manipulation.md ├── 04_text.md ├── 05_permissions.md ├── 06_scripting.md ├── 07_ssh.md ├── 08_tips.md ├── 09_resources.md └── assets │ └── images │ ├── bash.png │ ├── dash.png │ ├── fish.png │ ├── powershell.png │ ├── ssh-example.webp │ └── zshell.png ├── Workshop - Refactoring ├── 01_introduction.md ├── 02_clean_code.md ├── 03_refactoring.md ├── 04_tools.md ├── 05_extra.md ├── 06_resources.md ├── sphinx-example │ ├── .DS_Store │ ├── docs │ │ ├── Calculator.rst │ │ ├── Makefile │ │ ├── _build │ │ │ ├── .DS_Store │ │ │ ├── doctrees │ │ │ │ ├── Calculator.doctree │ │ │ │ ├── environment.pickle │ │ │ │ ├── index.doctree │ │ │ │ └── modules.doctree │ │ │ └── html │ │ │ │ ├── .buildinfo │ │ │ │ ├── Calculator.html │ │ │ │ ├── _modules │ │ │ │ ├── Calculator.html │ │ │ │ ├── calculator │ │ │ │ │ └── Calculator.html │ │ │ │ └── index.html │ │ │ │ ├── _sources │ │ │ │ ├── Calculator.rst.txt │ │ │ │ ├── index.rst.txt │ │ │ │ └── modules.rst.txt │ │ │ │ ├── _static │ │ │ │ ├── alabaster.css │ │ │ │ ├── basic.css │ │ │ │ ├── custom.css │ │ │ │ ├── doctools.js │ │ │ │ ├── documentation_options.js │ │ │ │ ├── file.png │ │ │ │ ├── language_data.js │ │ │ │ ├── minus.png │ │ │ │ ├── plus.png │ │ │ │ ├── pygments.css │ │ │ │ ├── searchtools.js │ │ │ │ └── sphinx_highlight.js │ │ │ │ ├── genindex.html │ │ │ │ ├── index.html │ │ │ │ ├── modules.html │ │ │ │ ├── objects.inv │ │ │ │ ├── py-modindex.html │ │ │ │ ├── search.html │ │ │ │ └── searchindex.js │ │ ├── conf.py │ │ ├── index.rst │ │ ├── make.bat │ │ └── modules.rst │ ├── src │ │ └── calculator │ │ │ ├── Calculator.py │ │ │ └── __init__.py │ └── workshop.md └── tools-example │ ├── main.py │ └── mod.py ├── Workshop - Requirements Specification ├── 01_introduction.md ├── 02_requirements.md ├── 03_REST.md ├── 04_combining.md ├── 05_specification.md ├── 06_resources.md └── images │ └── smile-32.png ├── Workshop - Software Testing ├── 01_introduction.md ├── 02_techniques.md ├── 03_automation.md ├── 04_reporting.md ├── 05_tracking.md └── 06_resources.md ├── Workshop - UML ├── 01_introduction.md ├── 02_uml_diagrams.md ├── 03_generating_diagrams.md ├── 04_swagger.md ├── 05_resources.md ├── draw_io │ ├── voyager_1.drawio │ ├── voyager_1.svg │ ├── voyager_2.drawio │ └── voyager_2.svg ├── images │ ├── activity-ingredients.jpeg │ ├── class-ingredients.webp │ ├── class-relationship.webp │ ├── go-share.jpeg │ └── use-case-ingredients.webp ├── plant_uml │ ├── activity_diagram.puml │ ├── activity_diagram │ │ └── GO Sharing Scooter Renting.svg │ ├── class_diagram.puml │ ├── class_diagram │ │ └── GO Sharing Class Diagram.svg │ ├── deployment_diagram.puml │ ├── deployment_diagram │ │ └── GO Sharing Deployment Architecture.svg │ ├── sequence_diagram.puml │ ├── sequence_diagram │ │ └── GO Sharing Money Deposit.svg │ ├── state_diagram.puml │ ├── state_diagram │ │ └── GO Sharing Scooter Rental.svg │ ├── use_case_diagram.puml │ ├── use_case_diagram │ │ └── GO Sharing Use Case Diagram.svg │ ├── voyager_chatgpt.puml │ ├── voyager_chatgpt │ │ └── Voyager Probe ChatGPT.svg │ ├── voyager_message.puml │ ├── voyager_message │ │ └── Voyager Message Description.svg │ ├── voyager_protocol.puml │ └── voyager_protocol │ │ └── Voyager Communication Protocol.svg └── swagger │ ├── app.py │ └── swagger.yaml └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 110 | .pdm.toml 111 | .pdm-python 112 | .pdm-build/ 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ 163 | -------------------------------------------------------------------------------- /Workshop - CI_CD/01_introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction to CI/CD 2 | CI/CD (Continuous Integration and Continuous Deployment/Delivery) is a set of practices in software development that automates integration, testing, and deployment processes. It ensures faster feedback loops, reduces manual tasks, and improves code quality. Developers frequently merge code changes into a shared repository (CI), followed by automated deployment to production or staging environments (CD) 3 | 4 | ## What is CI/CD? 5 | ![CI/CD Overview](assets/images/ci_cd_overview.svg) 6 | 7 | #### Continuous Integration (CI) 8 | Continuous integration is the practice of integrating all your code changes into the main branch of a shared source code repository early and often, automatically testing each change when you commit or merge them, and automatically kicking off a build. With continuous integration, errors and security issues can be identified and fixed more easily, and much earlier in the development process. 9 | 10 | #### Continuous Delivery (CD) 11 | Continuous delivery is a software development practice that works in conjunction with CI to automate the infrastructure provisioning and application release process. Once code has been tested and built as part of the CI process, CD takes over during the final stages to ensure it's packaged with everything it needs to deploy to any environment at any time. CD can cover everything from provisioning the infrastructure to deploying the application to the testing or production environment. 12 | 13 | #### What about Continuous Deployment? 14 | Continuous deployment enables organizations to deploy their applications automatically, eliminating the need for human intervention. With continuous deployment, DevOps/software teams set the criteria for code releases ahead of time and when those criteria are met and validated, the code is deployed into the production environment. This allows organizations to be more nimble and get new features into the hands of users faster. 15 | 16 | :star: Within this course we will only focus on Continous Delivery, but you are free to experiment or expand:smile:! 17 | 18 | > While you can do continuous integration without continuous delivery or deployment, you can't really do CD without already having CI in place. That's because it would be extremely difficult to be able to deploy to production at any time if you aren't practicing CI fundamentals like integrating code to a shared repo, automating testing and builds, and doing it all in small batches on a daily basis. 19 | 20 | ### Significance of CI/CD in Software Development 21 | CI/CD is a set of practices that streamline the software development lifecycle by automating various processes. 22 | It ensures that code changes are integrated, tested, and deployed swiftly and consistently. 23 | The main goals are to improve collaboration, reduce risk, and accelerate software delivery. 24 | 25 | ## How Does CI/CD Work? 26 | 1. **Automated Builds:** Developers commit code changes to a version control system (e.g., Git). CI tools (e.g., Jenkins, GitLab CI/CD) automatically trigger builds when changes are detected. 27 | 28 | 2. **Testing:** Automated tests (unit, integration, and acceptance tests) run during the build process. Any failures are reported immediately. 29 | 30 | 3. **Artifact Generation:** Successful builds produce deployable artifacts (e.g., Docker images, JAR files). 31 | 32 | 4. **Deployment Pipeline:** CD pipelines orchestrate the deployment process. They include stages like staging, testing, and production. 33 | 34 | 5. **Automated Deployment:** CD tools (e.g., AWS CodePipeline, GitOps) deploy artifacts to target environments based on predefined rules. 35 | 36 | ## Benefits of CI/CD 37 | - **Reduced Errors:** Frequent integration and automated testing catch issues early, reducing bugs in production. This leads to improved customer satisfaction and a better reputation for your company. 38 | 39 | - **Improved Quality:** Consistent builds and rigorous testing lead to higher-quality software. Testing code more often, in smaller batches, and earlier in the development cycle can seriously cut down on fire drills. This results in a smoother development cycle and less team stress. Results are more predictable, and it's easier to find and fix bugs. 40 | 41 | - **Faster Releases:** Shorter feedback loops enable faster feature delivery. By automating the delivery (deployment) we can reduce intervention and have frequent relesaes that keep the product up-to-date. 42 | 43 | - **Risk Mitigation:** Smaller, incremental changes minimize the impact of failures. If something fails (with auto deployment enabled) it would only affect a small portion of the system. Rollbacks are simpler because of these small changes. 44 | 45 | - **Efficient Collaboration:** CI/CD encourages collaboration among developers, testers, and operations teams. Because developers work in smaller, manageable increments, it makes it easier to coordinate efforts. -------------------------------------------------------------------------------- /Workshop - CI_CD/02_understanding.md: -------------------------------------------------------------------------------- 1 | ## Understanding the CI/CD Pipeline 2 | 3 | Pipelines are fundamental to continuous integration and delivery (CI/CD). Learn how CI/CD pipelines work and how they automate code tests and builds. 4 | 5 | ### Continuous Integration (CI): Frequent code integration, automated builds, and unit testing. 6 | CI ensures that code changes are frequently integrated into a shared repository, allowing early detection of issues and promoting collaboration among developers. 7 | 8 | ![CI Overview](assets/images/ci_overview.svg) 9 | 10 | #### Components: 11 | 1. Version Control System (VCS): Developers commit their code changes to a central repository (e.g., Git). 12 | 2. Automated Build System: When changes are pushed to the repository, an automated build process triggers. It compiles the code, runs tests, and generates artifacts (e.g., binaries, libraries). 13 | 3. Unit Testing: Automated tests validate the correctness of individual code units (functions, classes, etc.). 14 | 4. Code Linting and Formatting: Tools check code for adherence to coding standards. 15 | 5. Artifact Repository: The build artifacts are stored in a repository (e.g., Nexus, Artifactory). 16 | 6. Notification System: Developers receive notifications about build status and test results. 17 | 18 | ### Continuous Delivery (CD): Automated deployment to staging or production environments. 19 | CD extends CI by automating the deployment process, ensuring that code changes are ready for production. 20 | 21 | ![CD Overview](assets/images/cd_overview.svg) 22 | 23 | ### Components: 24 | 1. Staging Environment: A replica of the production environment where code changes are tested. 25 | 2. Deployment Pipeline: A series of automated steps that take code from the repository to production. 26 | 3. Automated Testing (Beyond Unit Tests): 27 | - Integration Tests: Validate interactions between different components. 28 | - Functional Tests: Verify that the application behaves as expected. 29 | - Performance Tests: Assess system performance under load. 30 | 4. Configuration Management: Tools (e.g., Ansible, Puppet, Chef) manage server configurations. 31 | 5. Infrastructure as Code (IaC): Define infrastructure using code (e.g., Terraform, CloudFormation). 32 | 6. Deployment Strategies: 33 | - Blue-Green Deployment: Spin up a new environment (green) alongside the existing one (blue) and switch traffic. 34 | - Canary Deployment: Gradually roll out changes to a subset of users. 35 | - Rolling Deployment: Incremental updates. 36 | 7. Feature Flags: Enable/disable specific features without deploying new code. 37 | 8. Monitoring and Logging: Monitor application health and log events. 38 | 9. Automated Deployment to Production: 39 | If all tests pass, the code is automatically deployed to production. 40 | Manual approval gates can be added for critical changes. 41 | 42 | ### Flow from Code Changes to Deployment: 43 | Developers commit code changes to the VCS. 44 | CI server detects the changes and triggers a build. 45 | Automated tests (unit, integration, functional) run. 46 | If tests pass, artifacts are stored in the repository. 47 | CD pipeline picks up the artifacts. 48 | 49 | In the staging environment: 50 | - Infrastructure is provisioned (IaC). 51 | - Application is deployed. 52 | - Additional tests (performance, security) are conducted. 53 | 54 | If staging tests pass, the CD pipeline deploys to production (based on the chosen deployment strategy). 55 | Monitoring and logging track the application’s behavior in production. 56 | -------------------------------------------------------------------------------- /Workshop - CI_CD/06_automation.md: -------------------------------------------------------------------------------- 1 | ## Automated Testing 2 | 3 | Automated testing plays a crucial role in CI/CD pipelines for several reasons: 4 | 5 | #### Early Detection of Issues 6 | Automated tests run with every code change, catching bugs and regressions early in the development process. This prevents issues from propagating downstream. 7 | 8 | ##### Consistent and Reliable Builds 9 | Automated tests ensure that each build is consistent and reliable. Developers can trust that the application behaves as expected across different environments. 10 | 11 | ##### Faster Feedback Loop 12 | Automated tests provide rapid feedback on code changes. Developers can address issues promptly, reducing the time between writing code and receiving feedback. 13 | 14 | ##### Reduced Manual Effort 15 | Manual testing is time-consuming and error-prone. Automation frees up testers to focus on exploratory testing and other critical tasks. 16 | 17 | ##### Increased Confidence 18 | A robust test suite gives confidence that the application works as intended. It’s especially important when deploying to production. 19 | 20 | ##### Regression Prevention 21 | Automated tests prevent regressions by verifying existing functionality after code changes. This avoids breaking features unintentionally. 22 | 23 | --------- 24 | 25 |
26 | 27 | ### Integrating testing into the pipeline. 28 | 29 | We are going to expand our YAML file we created before by adding an extra job to it. 30 | > You could also just add a step, which is fine for this example, but seperation could help for bigger projects. 31 | 32 | ```yaml 33 | name: Python application 34 | 35 | ... 36 | 37 | jobs: 38 | build: 39 | ... 40 | 41 | test: 42 | needs: build 43 | runs-on: ubuntu-latest 44 | steps: 45 | - uses: actions/checkout@v4 46 | - name: Set up Python 3.10 47 | uses: actions/setup-python@v5 48 | with: 49 | python-version: "3.10" 50 | cache: 'pip' 51 | - name: Install dependencies 52 | run: | 53 | python -m pip install --upgrade pip 54 | pip install flake8 pytest 55 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 56 | - name: Test with pytest 57 | run: | 58 | pytest 59 | pytest --cov --cov-report term --cov-report xml:coverage.xml 60 | ``` 61 | 62 | This should create an extra job on your GitHub Actions page as shown below 63 | 64 | !["Extended workflow with test job"](assets/images/extended-action-wtih-testing.png) 65 | 66 | > Creating a new job will also create a new runner (which wil bill you twice), for this scenario you could also just include a new step that does the testing. If you are going to implement more tests and want parallel execution in the future, seperation of jobs is adviced, 67 | 68 |
69 | 70 | ### How about that coverage? 71 | 72 | To add code coverage we need to add the dependency `coverage` to our `requirements.txt`.
73 | After adding the dependency we need to add an extra command to the run part of our Test: 74 | 75 | ```yaml 76 | ... 77 | - name: Test with pytest 78 | run: | 79 | coverage run -m pytest 80 | - name: Run code coverage 81 | run: | 82 | # Run coverage report 83 | #coverage xml 84 | 85 | # Report and write to summary. 86 | coverage report --format=markdown >> $GITHUB_STEP_SUMMARY 87 | 88 | # Report again and fail if under 100%. 89 | coverage report --fail-under=100 90 | - name: Store coverage report 91 | uses: actions/upload-artifact@v4 92 | with: 93 | path: coverage.xml 94 | if: ${{ failure() }} 95 | ``` 96 | 97 | This will run the code coverage based on the pytest we've created.
98 | In our case it will fail since it does not match the `100%` code coverage requirement.
99 | Our workflow output will also have a summary available for the code coverage. 100 | 101 | 102 | ![Code Coverage Summary](assets/images/code-coverage.png) 103 | 104 | The script will also upload the `coverage.xml` file to the artifact so we can use it in other tools.
105 | This will only happen if the coverage does not match the given amount of percentage.\ 106 | 107 | ```yaml 108 | ... 109 | - name: Store coverage report 110 | uses: actions/upload-artifact@v4 111 | with: 112 | path: coverage.xml 113 | if: ${{ failure() }} 114 | ``` 115 | 116 |
117 | 118 | ## :tada: Congratulations! 119 | 120 | You have learnt : 121 | 122 | 1. Integrate testing into the pipeline 123 | 2. Integrate code coverage into the pipeline -------------------------------------------------------------------------------- /Workshop - CI_CD/07_environments.md: -------------------------------------------------------------------------------- 1 | # Environment Management 2 | 3 | ## Environment types 4 | 5 | ### Development 6 | Developers use this environment to write, modify, and test code. It’s where they build new features, fix bugs, and experiment. 7 | 8 | - Isolation: Developers work independently without affecting other team members. 9 | - Fast Iteration: Frequent code changes and quick feedback. 10 | - Integration with Version Control: Code is committed to a version control system (e.g., Git). 11 | - Local Development: Often runs on developers’ local machines. 12 | - Mock Data: Simulated data for testing. 13 | 14 | > The challenge of a development environment is ensuring consistency across different developers’ environments. 15 | 16 |
17 | 18 | ### Staging 19 | A replica of the production environment where changes are tested before deployment. 20 | 21 | - Similarity to Production: Configuration, infrastructure, and data closely resemble production. 22 | - Testing Scenarios: Comprehensive testing, including performance, security, and user acceptance. 23 | - Pre-Production Testing: Identifies issues specific to the production setup. 24 | - Limited Access: Restricted to authorized users. 25 | 26 | > The challenge of a staging environment is to keep the staging environment in sync with production. 27 | 28 |
29 | 30 | ### Production 31 | The live environment where the application runs for end-users. 32 | 33 | - High Availability: Must be reliable and scalable. 34 | - Monitoring and Logging: Continuous monitoring for performance, errors, and security. 35 | - Security Measures: Firewalls, access controls, encryption. 36 | - Rolling Deployments: Gradual deployment of changes to minimize impact. 37 | - Backup and Recovery: Regular backups and disaster recovery plans. 38 | 39 | > The challenge of a production environment is balancing it's stability with frequent updates. 40 | 41 |
42 | 43 | > Can you think of any other environments that could be useful? 44 | 45 |
46 | 47 | ## Pipeline integration 48 | 49 | We can add an environment inside our repository so we can set differente jobs based on that environment.
50 | On the main page of the repository, navigate to the settings tab 51 | ![Settings tab](assets/images/settings.png) 52 | 53 | On the left menu in the settings tab, you have the option of "Environments", this will open the overview of all environments of this repository 54 | ![Environment overview](assets/images/environment_overview.png) 55 | 56 | From there we can add a new Enviroment, let's say `production`: 57 | ![Production environment](assets/images/add_environment.png) 58 | 59 | > Discover what extra options you can set when you create/edit an enivornment 60 | 61 |
62 | 63 | From within our `YAML`-file we can now address this environment as shown below 64 | 65 | ```yaml 66 | name: Deployment 67 | 68 | on: 69 | push: 70 | branches: 71 | - main 72 | 73 | jobs: 74 | deployment: 75 | runs-on: ubuntu-latest 76 | environment: production 77 | steps: 78 | - name: deploy 79 | # ...deployment-specific steps 80 | ``` 81 | 82 | When the above workflow runs, the deployment job will be subject to any rules configured for the production environment. For example, if the environment requires reviewers, the job will pause until one of the reviewers approves the job. 83 | 84 | > Each job in a workflow can reference a single environment. -------------------------------------------------------------------------------- /Workshop - CI_CD/09_monitoring_and_logging.md: -------------------------------------------------------------------------------- 1 | # Monitoring and Logging 2 | 3 | Monitoring and logging are crucial aspects of any CI/CD pipeline. 4 | 5 | 6 | ## Monitoring 7 | Monitoring is crucial for understanding the health and performance of your software and CI/CD pipeline. Here are some key points to cover: 8 | 9 | **System Reliability:**
10 | Monitoring ensures that your system remains reliable by tracking performance metrics, uptime, and response times. It helps prevent unexpected failures. 11 | 12 | **Identifying Bottlenecks:**
13 | Monitoring reveals bottlenecks in your software or pipeline. By analyzing metrics (e.g., CPU usage, memory, network), you can optimize resource allocation. 14 | 15 | **Detecting Anomalies:**
16 | Monitoring alerts you to abnormal behavior. Whether it’s sudden traffic spikes or unusual error rates, early detection allows timely intervention. 17 | 18 | ### Monitoring Tools: 19 | GitHub Actions Workflow runs generate real-time graphs that illustrate progress. Use these graphs to monitor and debug workflows. 20 | View logs for each run, including status for jobs and steps in the workflow. 21 | Enable additional debug logging if needed. 22 | 23 | #### Datadog CI Visibility: 24 | Integrating Datadog with GitHub Actions provides insights into your CI/CD pipeline, allowing you to optimize performance and detect bottlenecks2. 25 | 26 | ## Logging 27 | Logging helps you capture relevant information about your software and pipeline execution. Here’s what to cover: 28 | 29 | **Recording Events:**
30 | Logging captures events, such as user interactions, errors, and system activities. These records are essential for auditing and debugging. 31 | 32 | **Error Tracking:**
33 | Logs help pinpoint errors, exceptions, and unexpected behavior. Developers can analyze logs to identify root causes and fix issues. 34 | 35 | **Relevant Data:**
36 | Logging provides context. It records relevant data like timestamps, user IDs, and request details, aiding troubleshooting and forensic analysis. 37 | 38 | ### Logging Tools and Options: 39 | 40 | ### GitHub Actions Logs 41 | View, search, and download logs for each job in a workflow run. 42 | 43 | ### Custom Logging Libraries: 44 | - Log4j; 45 | - Winston; 46 | - Serilog. 47 | 48 | ### Centralized Logging Solutions: 49 | - ELK Stack (Elasticsearch, Logstash, Kibana); 50 | - Splunk 51 | 52 | 53 | ## Monitoring 54 | 55 | ### Tools 56 | Monitoring tools (e.g., Prometheus, Grafana). 57 | 58 | 59 | ## Logging 60 | Discuss logging practices for troubleshooting. 61 | 62 |
63 | 64 | > Remember that effective monitoring and logging help you identify issues early, optimize performance, and ensure the reliability of your CI/CD pipeline. -------------------------------------------------------------------------------- /Workshop - CI_CD/10_best_practices_and_pitfalls.md: -------------------------------------------------------------------------------- 1 | # Best Practices and Pitfalls 2 | 3 | ### :zap: Commit, commit and commit some more 4 | It’s much easier to fix small problems than big problems, as a general rule. One of the biggest advantages of continuous integration is that code is integrated into a shared repository against other changes happening at the same time. If a development team commits code changes early and often, bugs are easier to identify because there is less code to sort through. 5 | 6 | By testing in small batches, code quality is improved and teams can iterate more effectively. 7 | 8 | ### :eyeglasses: Read the documentation (and then read it again) 9 | Continuous integration systems make documentation widely available, and this documentation can be very helpful long after you’ve implemented CI into your workflow. 10 | 11 | > It can be helpful to reference the documentation in READMEs or in other accessible formats. Encourage team members to read the documentation first, bookmark links, create FAQs, and incorporate these resources into onboarding for new team members. 12 | 13 | ### :gem: Optimize pipeline stages 14 | CI pipelines contain jobs and stages: Jobs are the activities that happen within a particular stage, and once all jobs pass, code moves to the next stage. To get the most out of your CI pipelines, optimize stages so that failures are easy to identify and fix. 15 | 16 | Stages are an easy way to organize similar jobs, but there may be a few jobs in your pipeline that could safely run in an earlier stage without negatively impacting your project if they fail. Consider running these jobs in an earlier stage to speed up CI pipelines. 17 | 18 | ### :rocket: Make builds fast and simple 19 | Nothing slows down a pipeline like complexity. Focus on keeping builds fast, and the best way to do that is by keeping things as simple as possible. 20 | 21 | Every minute taken off build times is a minute saved for each developer every time they commit. Since CI demands frequent commits, this time can add up. Martin Fowler discusses a guideline of the ten-minute build that most modern projects can achieve. Since continuous integration demands frequent commits, saving time on commit builds can give developers a lot of time back. 22 | 23 | ### :factory: Use failures to improve processes 24 | Improvement is a process. When teams change their response to failures, it creates a cultural shift for continuous improvement. Instead of asking who caused the failure, ask what caused the failure. This means shifting from a blaming culture to a learning culture. 25 | 26 | If teams are doing frequent commits, it becomes much easier to identify problems and solve them. If there are patterns in failed builds, look at the underlying causes. Are there non-code errors that are causing builds unnecessarily? Maybe incorporate an allow_failure parameter. Look for ways to continually improve, make failures blameless, and look for causes (not culprits). 27 | 28 | ### :computer: Test environment should mirror production 29 | In continuous integration, every commit triggers a build. These builds then run tests to identify if something will be broken by the code changes you introduce. The test pyramid is a way for developers to think of how to balance testing. End-to end testing is mostly used as a safeguard, with unit testing being used most often to identify errors. One important thing to keep in mind with testing is the environment. When the testing and production environments match, it means that developers can rely on the results and deploy with confidence. 30 | 31 | > Continuous integration helps developers deploy faster and get feedback sooner. Ultimately, the best continuous integration system is the one you actually use. Find the right CI for your needs and then incorporate these best practices to make the most of your new CI workflow. -------------------------------------------------------------------------------- /Workshop - CI_CD/11_resources.md: -------------------------------------------------------------------------------- 1 | ### Resources for further learning 2 | 3 | For more in depth information about CI/CD, pipelines, workflows, the following resources could help. 4 | 5 | - https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions 6 | - https://about.gitlab.com/topics/ci-cd/ 7 | - https://docs.gitlab.com/ee/ci/ 8 | - https://docs.github.com/en/actions/quickstart 9 | - https://about.gitlab.com/topics/ci-cd/cicd-pipeline/ 10 | - https://docs.github.com/en/actions/using-workflows/about-workflows 11 | - https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment 12 | - https://peps.python.org/pep-0008/ 13 | - https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs 14 | - https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications 15 | - https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow 16 | - https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners 17 | 18 | Run your GitHub Workflows local on your own machine (handy to test your workflow) 19 | - https://nektosact.com/introduction.html -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/actions-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/actions-menu.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/add_environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/add_environment.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/big_bang_deployment.svg: -------------------------------------------------------------------------------- 1 | v1.0v2.0B1B2B3G1G2G3UsersProxybefore deploymentafter deployment -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/cd_overview.svg: -------------------------------------------------------------------------------- 1 | Continuous DeliveryStagingTestingMonitoringProductionArtifact -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/ci-meme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/ci-meme.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/ci_cd_overview.svg: -------------------------------------------------------------------------------- 1 | Continuous IntegrationContinuous DeliveryBuildTestArtifactStagingProduction -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/ci_overview.svg: -------------------------------------------------------------------------------- 1 | Continuous IntegrationBuildTestArtifact -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/code-coverage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/code-coverage.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/environment_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/environment_overview.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/extended-action-wtih-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/extended-action-wtih-testing.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/feature_deployment.svg: -------------------------------------------------------------------------------- 1 | FeaturesFeature 1Feature 2UsersProxyflag=A go to new featureflag=B -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/finished-job-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/finished-job-example.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/python-application-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/python-application-action.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/running-job-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/running-job-example.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - CI_CD/assets/images/settings.png -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/cd.puml: -------------------------------------------------------------------------------- 1 | @startuml CD overview 2 | skinparam backgroundcolor transparent 3 | 4 | rectangle "Continuous Delivery" { 5 | agent Staging 6 | agent Testing #line.dashed 7 | agent Monitoring #line.dashed 8 | agent Production 9 | 10 | Artifact -> Staging 11 | Staging -> Testing 12 | Testing-> Production 13 | Production -> Monitoring 14 | } 15 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/ci.puml: -------------------------------------------------------------------------------- 1 | @startuml CI overview 2 | skinparam backgroundcolor transparent 3 | 4 | rectangle "Continuous Integration" { 5 | agent Build 6 | agent Test 7 | agent Artifact 8 | 9 | Build -> Test 10 | Test -> Artifact 11 | } 12 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/ci_cd.puml: -------------------------------------------------------------------------------- 1 | @startuml CI/CD overview 2 | skinparam backgroundcolor transparent 3 | 4 | rectangle "Continuous Integration" { 5 | agent Build 6 | agent Test 7 | agent Artifact 8 | 9 | Build -> Test 10 | Test -> Artifact 11 | } 12 | 13 | rectangle "Continuous Delivery" { 14 | agent Staging 15 | agent Production 16 | 17 | Artifact -> Staging 18 | Staging -> Production 19 | } 20 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/deployment_strategies/big_bang.puml: -------------------------------------------------------------------------------- 1 | @startuml Big Bang Deployment 2 | skinparam backgroundcolor transparent 3 | 4 | left to right direction 5 | 6 | actor Users 7 | agent Proxy 8 | 9 | rectangle "v1.0" as V1 { 10 | card B1 #CornflowerBlue 11 | card B2 #CornflowerBlue 12 | card B3 #CornflowerBlue 13 | 14 | [B1] -[hidden]-> [B2] 15 | [B2] -[hidden]-> [B3] 16 | } 17 | 18 | rectangle "v2.0" as V2 { 19 | card G1 #LightGreen 20 | card G2 #LightGreen 21 | card G3 #LightGreen 22 | 23 | [G1] -[hidden]-> [G2] 24 | [G2] -[hidden]-> [G3] 25 | } 26 | 27 | Users --> Proxy 28 | Proxy ---> V1 : before deployment 29 | Proxy ---> V2 : after deployment 30 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/deployment_strategies/blue_green.puml: -------------------------------------------------------------------------------- 1 | @startuml Blue-Green Deployment 2 | skinparam backgroundcolor transparent 3 | 4 | left to right direction 5 | 6 | actor Users 7 | agent Proxy 8 | 9 | rectangle " " as 1 #line.dotted { 10 | rectangle "v1.0" as V1 { 11 | card B1 as V1B1 #CornflowerBlue 12 | card B2 as V1B2 #CornflowerBlue 13 | card B3 as V1B3 #CornflowerBlue 14 | 15 | [V1B1] -[hidden]-> [V1B2] 16 | [V1B2] -[hidden]-> [V1B3] 17 | } 18 | 19 | rectangle "v2.0 (standby)" as V2S { 20 | card G1 as V2SG1 #LightGreen 21 | card G2 as V2SG2 #LightGreen 22 | card G3 as V2SG3 #LightGreen 23 | 24 | [V2SG1] -[hidden]-> [V2SG2] 25 | [V2SG2] -[hidden]-> [V2SG3] 26 | } 27 | 28 | V1 --[hidden]--> V2S 29 | } 30 | 31 | rectangle " " as 2 #line.dotted { 32 | rectangle "v2.0" as V2 { 33 | card G1 as V2G1 #LightGreen 34 | card G2 as V2G2 #LightGreen 35 | card G3 as V2G3 #LightGreen 36 | 37 | [V2G1] -[hidden]-> [V2G2] 38 | [V2G2] -[hidden]-> [V2G3] 39 | } 40 | 41 | rectangle "v1.0 (standby)" as V1S { 42 | card B1 as V1SB1 #CornflowerBlue 43 | card B2 as V1SB2 #CornflowerBlue 44 | card B3 as V1SB3 #CornflowerBlue 45 | 46 | [V1SB1] -[hidden]-> [V1SB2] 47 | [V1SB2] -[hidden]-> [V1SB3] 48 | } 49 | 50 | 51 | 52 | V2 --[hidden]--> V1S 53 | } 54 | 55 | Users --> Proxy 56 | Proxy ---> 1 : before deployment 57 | Proxy ---> 2 : after deployment 58 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/deployment_strategies/canary.puml: -------------------------------------------------------------------------------- 1 | @startuml Canary Deployment 2 | skinparam backgroundcolor transparent 3 | 4 | left to right direction 5 | 6 | actor Users 7 | agent Proxy 8 | 9 | rectangle "v1.0" as V1 { 10 | card B1 #CornflowerBlue 11 | card B2 #CornflowerBlue 12 | card B3 #CornflowerBlue 13 | 14 | [B1] -[hidden]-> [B2] 15 | [B2] -[hidden]-> [B3] 16 | } 17 | 18 | rectangle "v1.0 / v2.0" as V2 { 19 | card G1 #LightGreen 20 | 21 | rectangle " " as O1 #line.dotted { 22 | card B2 as G2 #CornflowerBlue 23 | card B3 as G3 #CornflowerBlue 24 | } 25 | 26 | [G1] -[hidden]-> [G2] 27 | [G2] -[hidden]-> [G3] 28 | } 29 | 30 | 31 | Users --> Proxy 32 | Proxy --> V1 33 | Proxy --> G1 : some users 34 | Proxy --> O1 : most users 35 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/deployment_strategies/feature.puml: -------------------------------------------------------------------------------- 1 | @startuml Feature Deployment 2 | skinparam backgroundcolor transparent 3 | 4 | left to right direction 5 | 6 | actor Users 7 | agent Proxy 8 | rectangle "Features" as F { 9 | card "Feature 1" as 1 #CornflowerBlue 10 | card "Feature 2" as 2 #CornflowerBlue 11 | } 12 | 13 | Users --> Proxy 14 | Proxy ----> F : flag=A go to new feature 15 | Proxy -----> F : flag=B 16 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/plantuml/deployment_strategies/rolling.puml: -------------------------------------------------------------------------------- 1 | @startuml Rolling Deployment 2 | skinparam backgroundcolor transparent 3 | 4 | left to right direction 5 | 6 | actor Users 7 | agent Proxy 8 | 9 | rectangle "v1.0" as V1 { 10 | card B1 #CornflowerBlue 11 | card B2 #CornflowerBlue 12 | card B3 #CornflowerBlue 13 | 14 | [B1] -[hidden]-> [B2] 15 | [B2] -[hidden]-> [B3] 16 | } 17 | 18 | rectangle "v2.0" as V2 { 19 | rectangle " " as V2B1 { 20 | card G1 as 1G1 #LightGreen 21 | card B2 as 1B2 #CornflowerBlue 22 | card B3 as 1B3 #CornflowerBlue 23 | 24 | [1G1] -[hidden]-> [1B2] 25 | [1B2] -[hidden]-> [1B3] 26 | } 27 | 28 | rectangle " " as V2B2 { 29 | card G1 as 2G1 #LightGreen 30 | card G2 as 2G2 #LightGreen 31 | card B3 as 2B3 #CornflowerBlue 32 | 33 | [2G1] -[hidden]-> [2G2] 34 | [2G2] -[hidden]-> [2B3] 35 | } 36 | 37 | rectangle " " as V2B3 { 38 | card G1 as 3G1 #LightGreen 39 | card G2 as 3G2 #LightGreen 40 | card G3 as 3G3 #LightGreen 41 | 42 | [3G1] -[hidden]-> [3G2] 43 | [3G2] -[hidden]-> [3G3] 44 | } 45 | 46 | V2B1 ----> V2B2 47 | V2B2 ----> V2B3 48 | } 49 | 50 | Users --> Proxy 51 | Proxy -----> V1 : before deployment 52 | Proxy ---> V2 : phased deployment 53 | @enduml -------------------------------------------------------------------------------- /Workshop - CI_CD/assets/python-app.yml: -------------------------------------------------------------------------------- 1 | name: Python application 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Set up Python 3.10 13 | uses: actions/setup-python@v3 14 | with: 15 | python-version: "3.10" 16 | cache: 'pip' 17 | - name: Install dependencies 18 | run: | 19 | python -m pip install --upgrade pip 20 | pip install flake8 21 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 22 | - name: Lint with flake8 23 | run: | 24 | # stop the build if there are Python syntax errors or undefined names 25 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 26 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 27 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics -------------------------------------------------------------------------------- /Workshop - GIT/02_setup.md: -------------------------------------------------------------------------------- 1 | # Setting up a Git environment 2 | 3 | 4 | ## Getting Git 5 | 6 | Some house-cleaning here. We assume of course you have Git installed, 7 | (hopefully \>= 1.7.0). 8 | 9 | If you don't you can install it from downloads on the git homepage or you can 10 | install [Github's git GUI](https://help.github.com/articles/set-up-git/). 11 | 12 | 13 | ## Setup 14 | 15 | First thing to do is to setup your identity. This identifies you to 16 | other people who download the project. 17 | 18 | $ git config --global user.name "Your Name" 19 | $ git config --global user.email your.email@example.com 20 | 21 | As a helpful step, you may want to set Git to use your favourite editor 22 | 23 | $ git config --global core.editor vscode -------------------------------------------------------------------------------- /Workshop - GIT/04_repositories.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## GitHub 4 | But, wait. There’s more. What about this distributed sharing thing with 5 | Git ? 6 | 7 | To be able to share, we’ll need a server to host our git repositiories. 8 | GitHub (github.com) is probably the 9 | easiest place to begin with. 10 | 11 | ## Login or sign up with GitHub 12 | 13 | If you've already got an account you can skip on to creating the repo on 14 | github, or forking this repository and cloning it down to your local machine. 15 | 16 | Otherwise... 17 | 18 | Go sign up for an account at 19 | GitHub; Or login into your GitHub account if you had previously signed 20 | up. 21 | 22 | Hint: You may need to setup git cache your GitHub password - see 23 | https://help.github.com/articles/set-up-git 24 | 25 | Then come back here, we’ll wait. 26 | 27 | ## Create your first GitHub repository 28 | 29 | A repository (repo) is a place where you would store your code. You were 30 | practising on your very own repo just now! 31 | 32 | The following 33 | tutorial will show you how to create a GitHub repo - which you can 34 | then share with others 35 | 36 | Then come back here, we’ll wait. 37 | 38 | ## Pushing your local changes 39 | 40 | We have been working on our local branch for now, but what if we want to work further on another location and we forgot our machine? This is where remote repo's like GitHub come in handy. 41 | 42 | Within our local branch we can use `git push` to push commits made on our local branch to a remote repository. 43 | 44 | To push changes from our `main` branch to the remote `origin` we use 45 | 46 | $ git push origin main 47 | 48 | this will push our latest commit to the remote repository so the local changes are reflected on the remote. 49 | 50 | :no_mouth: Stuck?
51 | Ask for help from the teacher 52 | 53 | 54 | ## Pulling the latest remote version 55 | 56 | When we working with a remote repository we used `clone` in a previous part to get the complete remote branch as a fresh new repository to our local machine. This works fine for the first time, but we don't always want a fresh version... we want to get the latest changes. 57 | 58 | #### Fetching changes from a remote repository 59 | Use `git fetch` to retrieve new work done by other people. Fetching from a repository grabs all the new remote-tracking branches and tags without merging those changes into your own branches. 60 | 61 | If you already have a local repository with a remote URL set up for the desired project, you can grab all the new information by using `git fetch *remotename*` in the terminal: 62 | 63 | $ git fetch origin 64 | 65 | ##### :bulb: Setting up remote url 66 | 67 | If we haven't cloned the repository via `git clone` we need to setup a remote url first. 68 | You can check if this the case via 69 | 70 | $ git remote -v 71 | 72 | # Verify new remote 73 | > origin https://github.com/OWNER/REPOSITORY.git (fetch) 74 | > origin https://github.com/OWNER/REPOSITORY.git (push) 75 | 76 | If there is no remote on your current local branch, you can add it via 77 | 78 | $ git remote add origin 79 | 80 | :expressionless: Stuck?
81 | Ask for help from the teacher 82 | 83 | ### Merging changes into your local branch 84 | 85 | Merging combines your local changes with changes made by others. 86 | 87 | Typically, you'd merge a remote-tracking branch (i.e., a branch fetched from a remote repository) with your local branch: 88 | 89 | $ git merge origin/main 90 | # will merge the remote origin into local main 91 | 92 | :neutral_face: Stuck?
93 | Ask for help from the teacher 94 | 95 | ### Pulling changes from a remote repository 96 | 97 | `git pull`` is a convenient shortcut for completing both `git fetch` and `git merge` in the same command: 98 | 99 | $ git pull origin main 100 | # Grabs online updates and merges them with your local work 101 | 102 | Because pull performs a merge on the retrieved changes, you should ensure that your local work is committed before running the pull command. If you run into a merge conflict you cannot resolve, or if you decide to quit the merge, you can use `git merge --abort` to take the branch back to where it was in before you pulled. 103 | 104 | :anguished: Stuck?
105 | Ask for help from the teacher 106 | 107 | ## :tada: Great job! 108 | 109 | You have learnt: 110 | 111 | 1. Forking a repo at GitHub 112 | 2. Git push 113 | 3. Git fetch 114 | 4. Git pull -------------------------------------------------------------------------------- /Workshop - GIT/06_collaboration.md: -------------------------------------------------------------------------------- 1 | ## Collaboration with GitHub 2 | 3 | Explore collaborative workflows using GitHub: 4 | 5 | ## Fork a repo 6 | 7 | Go to [this tutorial](https://help.github.com/articles/fork-a-repo) 8 | Then come back here, we’ll wait. 9 | 10 | 11 | ## Pull requests 12 | 13 | Pull requests let you tell others about changes you've pushed to a branch in a repository on GitHub. Once a pull request is opened, you can discuss and review the potential changes with collaborators and add follow-up commits before your changes are merged into the base branch. 14 | 15 | More in depth information can be found on the [GitHub page about Pull Requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests) 16 | 17 | ### Creating pull requests. 18 | 19 | GitHub has an excellent page on how to create a pull request. 20 | You can find that page here [https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) 21 | 22 | ### Reviewing and merging pull requests. 23 | 24 | In a pull request, you can review and discuss commits, changed files, and the differences (or "diff") between the files in the base and compare branches. 25 | 26 | Find more in depth info on the [GitHub page about Reviewing Pull Requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request) 27 | 28 | :bulb: Sometimes you created a pull request and you want to request a review, [this page](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review) gives you more in depth information on how to ask someone to review your pull request. 29 | 30 | ## Issues 31 | 32 | GitHub Issues are items you can create in a repository to plan, discuss and track work. 33 | 34 | Issues are simple to create and flexible to suit a variety of scenarios. You can use issues to track work, give or receive feedback, collaborate on ideas or tasks, and efficiently communicate with others. 35 | 36 | ### Creating an issue 37 | 38 | Issues let you track your work on GitHub. When you mention an issue in another issue or pull request, the issue's timeline reflects the cross-reference so that you can keep track of related work. To indicate that work is in progress, you can link an issue to a pull request. When the pull request merges, the linked issue automatically closes. 39 | 40 | To create an issue, there are multiple options available in GitHub. Follow the detailed information on the [GitHub page about creating an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue) 41 | 42 | ### Linking a pull request to an issue 43 | 44 | You can link a pull request or branch to an issue to show that a fix is in progress and to automatically close the issue when the pull request or branch is merged. 45 | 46 | You can link an issue to a pull request manually or using a supported keyword in the pull request description. 47 | 48 | When you link a pull request to the issue the pull request addresses, collaborators can see that someone is working on the issue. 49 | 50 | More information about this option can be found on the [GitHub page about linking an Issue to a Pull Request](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword) 51 | 52 | 53 | ### Assigning issues and pull requests 54 | 55 | Sometimes it's handy to know who is working on an issue, or better assign someone to an issue or pull requests because they have the required knowledge. 56 | 57 | If that is the case, you can assign someone to an issue or pull requests, more information can be found on the [GitHub page about assigning Issues and Pull Requests](https://docs.github.com/en/issues/tracking-your-work-with-issues/assigning-issues-and-pull-requests-to-other-github-users) -------------------------------------------------------------------------------- /Workshop - GIT/07_tips.md: -------------------------------------------------------------------------------- 1 | ## :rocket: Best Practices and Tips 2 | 3 | Using Git best practices, teams can coordinate all changes in a software project and utilize fast branching to help teams quickly collaborate and share feedback, leading to immediate, actionable changes. 4 | 5 | ### Make incremental, small changes 6 | 7 | Write the smallest amount of code possible to solve a problem. After identifying a problem or enhancement, the best way to try something new and untested is to divide the update into small batches of value that can easily and rapidly be tested with the end user to prove the validity of the proposed solution and to roll back in case it doesn't work without deprecating the whole new functionality. 8 | 9 | Committing code in small batches decreases the likelihood of integration conflicts, because the longer a branch lives separated from the main branch or codeline, the longer other developers are merging changes to the main branch, so integration conflicts will likely arise when merging. Frequent, small commits solves this problem. Incremental changes also help team members easily revert if merge conflicts happen, especially when those changes have been properly documented in the form of descriptive commit messages. 10 | 11 | ### Keep commits atomic 12 | 13 | Related to making small changes, atomic commits are a single unit of work, involving only one task or one fix (e.g. upgrade, bug fix, refactor). Atomic commits make code reviews faster and reverts easier, since they can be applied or reverted without any unintended side effects. 14 | 15 | The goal of atomic commits isn't to create hundreds of commits but to group commits by context. For example, if a developer needs to refactor code and add a new feature, she would create two separate commits rather than create a monolithic commit which includes changes with different purposes. 16 | 17 | ### Develop using branches 18 | 19 | Using branches, software development teams can make changes without affecting the main codeline. The running history of changes are tracked in a branch, and when the code is ready, it's merged into the main branch. 20 | 21 | Branching organizes development and separates work in progress from stable, tested code in the main branch. Developing in branches ensures that bugs and vulnerabilities don't work their way into the source code and impact users, since testing and finding those in a branch is easier. 22 | 23 | ### Write descriptive commit messages 24 | 25 | Descriptive commit messages are as important as a change itself. Write descriptive commit messages starting with a verb in present tense in imperative mood to indicate the purpose of each commit in a clear and concise manner. Each commit should only have a single purpose explained in detail in the commit message. The Git documentation provides guidance on how to write descriptive commit messages: 26 | 27 | Describe your changes in imperative mood, e.g. “make xyzzy do frotz” instead of “[This patch] makes xyzzy do frotz” or “[I] changed xyzzy to do frotz,” as if you are giving orders to the codebase to change its behavior. Try to make sure your explanation can be understood without external resources. Instead of giving a URL to a mailing list archive, summarize the relevant points of the discussion. 28 | 29 | Writing commit messages in this way forces software teams to understand the value an add or fix makes to the existing code line. If teams find it impossible to find the value and describe it, then it might be worth reassessing the motivations behind the commit. There's always time to commit later, as long changes are stashed and there's consistency in commits. 30 | 31 | ### Obtain feedback through code reviews 32 | 33 | Requesting feedback from others is an excellent way to ensure code quality. Code reviews are an effective method to identify whether a proposal solves a problem in the most effective way possible. Asking individuals from other teams to review code is important, because some areas of the code base might include specific domain knowledge or even security implications beyond the individual contributor's attributions. 34 | 35 | ### Identify a branching strategy 36 | 37 | Determining a single branching strategy is the solution to a chaotic development experience. 38 | 39 | While there are several approaches to development, the most common are: 40 | - Centralized workflow: Teams use only a single repository and commit directly to the main branch. 41 | - Feature branching: Teams use a new branch for each feature and don't commit directly to the main branch. 42 | - GitFlow: An extreme version of feature branching in which development occurs on the develop branch, moves to a release branch, and merges into the main branch. 43 | - Personal branching: Similar to feature branching, but rather than develop on a branch per feature, it's per developer. Every user merges to the main branch when they complete their work. -------------------------------------------------------------------------------- /Workshop - GIT/08_resources.md: -------------------------------------------------------------------------------- 1 | 2 | ### References and Further reading 3 | 4 | We throughly recommend these resources to continue your Git practice: 5 | 6 | - http://try.github.com Another 7 | beginners tutorial for git 8 | - http://git-scm.com Official 9 | website, with very useful help, book and videos 10 | - http://gitref.org 11 | - http://www.kernel.org/pub/software/scm/git/docs/everyday.html 12 | - https://education.github.com/git-cheat-sheet-education.pdf Cheatsheet for Git commands 13 | -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/01_introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction to the Shell 2 | The shell is a crucial component of an operating system, acting as an intermediary between the user and the system’s core functions. 3 | During this workshop you will learn: 4 | 5 | - What is a shell and what is it used for 6 | - How you can use the shell to navigate, manipulate files and directories and more 7 | - How to write shell scripts 8 | - And some tips for using the shell or shell scripts 9 | 10 |
11 | 12 | ## Significance 13 | 1. **User Interface:** The shell provides a user interface, allowing users to interact with the operating system. This can be through a command-line interface (CLI) or a graphical user interface (GUI). 14 | 2. **Command Execution:** It interprets and executes user commands. When you type a command in the terminal, the shell processes it and communicates with the operating system to perform the requested action. 15 | 3. **Scripting and Automation:** Shells support scripting, enabling users to write scripts to automate repetitive tasks. This is particularly useful for system administrators and developers. 16 | 4. **Customization:** Users can customize their shell environment to suit their preferences, such as setting up aliases, functions, and environment variables. 17 | 5. **Process Management:** The shell allows users to manage processes, including starting, stopping, and monitoring them. This is essential for multitasking and system management. 18 | 19 | ## Actions 20 | 1. **Command Interpretation:** The shell interprets the commands entered by the user and translates them into actions that the operating system can execute. 21 | 2. **File Manipulation:** It provides commands for file manipulation, such as creating, deleting, copying, and moving files and directories. 22 | 3. **Program Execution:** The shell can launch and manage the execution of programs. It can run programs in the foreground or background and handle input/output redirection. 23 | 4. **Environment Control:** The shell manages the user environment, including setting environment variables that can affect the behavior of running programs. 24 | 5. **Security:** Shells can enforce security policies by restricting access to certain commands or files, ensuring that only authorized users can perform specific actions. 25 | 26 |
27 | 28 | ## Shells 29 | There are several popular shells used in operating systems, each with its own features and advantages. 30 | 31 | 32 | 33 | ### Bash (Bourne Again Shell) 34 | This is probably the most widely used shell in Linux and macOS. \ 35 | It’s the default shell on many Linux distributions and macOS. 36 | 37 | Top features: 38 | - Supports scripting 39 | - Command history 40 | - Tab completion 41 | 42 |
43 | 44 | 45 | 46 | ### Zsh (Z Shell) 47 | A popular shell among power users and developers. \ 48 | Often used with the Oh My Zsh framework for additional plugins and themes. 49 | 50 | Top features: 51 | - Improved tab completion 52 | - Better scripting capabilities 53 | - Customization 54 | 55 |
56 | 57 | 58 | 59 | ### Fish (Friendly Interactive Shell) 60 | This shell is known for its user-friendly features. \ 61 | It is gaining traction for its ease of use and modern features. 62 | 63 | Top features: 64 | - Syntax highlighting 65 | - Autosuggestions 66 | - Web-based configuration interface 67 | 68 |
69 | 70 | 71 | 72 | ### Powershell 73 | This shell is primarily used in Windows environments. \ 74 | It is the default shell in Windows but is also available for Linux and macOS. 75 | 76 | Top features: 77 | - Object-oriented scripting 78 | - Extensive automation capabilities 79 | - Full integration with .NET 80 | 81 |
82 | 83 | 84 | 85 | ### Dash (Debian Almquist Shell) 86 | A lightweight shell used in Debian-based systems. \ 87 | Mostly used in scripts and system initialization. 88 | 89 | Top features: 90 | - Fast execution 91 | - Minimal resource usage 92 | - POSIX compliance -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/05_permissions.md: -------------------------------------------------------------------------------- 1 | # Permissions and Ownership 2 | In Unix-like operating systems, managing file permissions and ownership is crucial for maintaining system security and ensuring that users have appropriate access to files and directories. Each file and directory has a set of permissions that determine who can read, write, or execute them. These permissions are divided into three categories: owner, group, and others. 3 | 4 | ## File permissions 5 | In Unix-like systems, each file and directory has a set of permissions that determine who can read, write, or execute them. These permissions are divided into three categories: 6 | 7 | - **Owner**: The user who owns the file. 8 | - **Group**: The group that owns the file. 9 | - **Others**: All other users. 10 | 11 | Each category has three types of permissions: 12 | - **Read (r)**: Permission to read the file or list the directory contents. 13 | - **Write (w)**: Permission to modify the file or directory. 14 | - **Execute (x)**: Permission to execute the file or access the directory. 15 | 16 | You can view the permissions of a file using the **ls -l** command: 17 | ```sh 18 | ls -l myfile.txt 19 | ``` 20 | 21 | Output: 22 | 23 | ``` 24 | -rw-r--r-- 1 user group 1234 Oct 3 14:18 myfile.txt 25 | ``` 26 | 27 | In the above example `-rw-r--r--` indicates the permissions. 28 | * `-`: File type (dash means a regular file). 29 | * `rw-`: Owner permissions (read and write). 30 | * `r--`: Group permissions (read only). 31 | * `r--`: Others permissions (read only). 32 | 33 | ### Assignment 34 | Use `ls -l` to view the permissions of files in your home directory. 35 | 36 |
37 | 38 | ## Changing permissions 39 | You can change the permissions of a file using the `chmod` command. There are two ways to use `chmod`: symbolic and numeric. 40 | 41 | **Symbolic Mode**: 42 | * `u`: User (owner) 43 | * `g`: Group 44 | * `o`: Others 45 | * `a`: All (user, group, and others) 46 | 47 | ```sh 48 | # Add execute permission for the owner 49 | chmod u+x myfile.txt 50 | 51 | # Remove write permission for the group 52 | chmod g-w myfile.txt 53 | 54 | # Set read and write permissions for all 55 | chmod a+rw myfile.txt 56 | ``` 57 | 58 | ### Assignment 59 | Create a command that adds execute permission for the owner and removes write permission for others on a file. 60 | > *Hint: Use `chmod u+x` and `chmod o-w`.* 61 | 62 |
63 | 64 | **Numeric Mode** 65 | Permissions can also be represented by numbers: 66 | * `r` = 4 67 | * `w` = 2 68 | * `x` = 1 69 | 70 | Combine these values to set permissions. For example, 7 (4+2+1) means read, write, and execute. 71 | 72 | ```sh 73 | # Set permissions to rwxr-xr-- 74 | chmod 755 myfile.txt 75 | ``` 76 | So, the permissions in the above example are: 77 | 78 | - **7 (Owner)**: `rwx` (4 + 2 + 1 = 7) 79 | - **5 (Group)**: `r-x` (4 + 1 = 5) 80 | - **5 (Others)**: `r-x` (4 + 1 = 5) 81 | 82 | ### Assignment 83 | Permissions (Numeric Mode): Write a command that sets the permissions of a file to rwxr-xr-- 84 | > *Hint: Use `chmod 755`.* 85 | 86 |
87 | 88 | ## Ownership 89 | Each file and directory has an owner and a group. You can change the ownership using the `chown` command. 90 | 91 | ```sh 92 | # Change the owner to 'newuser' 93 | chown newuser myfile.txt 94 | 95 | # Change the owner and group 96 | chown newuser:newgroup myfile.txt 97 | ``` 98 | 99 | ### Assignment 100 | Create a command that changes the owner of a file to a different user. 101 | > *Hint: Use `chown newuser`.* 102 | 103 |
-------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/07_ssh.md: -------------------------------------------------------------------------------- 1 | # SSH (Secure Shell) [*optional*] 2 | 3 | SSH (Secure Shell) is a protocol used to securely connect to remote servers. It provides a secure channel over an unsecured network by using encryption. This guide will cover the basics of using SSH, setting up SSH keys for passwordless authentication, and configuring SSH access for multiple users. 4 | 5 | 6 | 7 |
8 | 9 | ### Basic SSH Usage 10 | To connect to a remote server using SSH, use the following command: 11 | 12 | ssh username@hostname 13 | 14 | `username`: The username on the remote server. \ 15 | `hostname`: The IP address or domain name of the remote server. 16 | 17 | If we would login with the credentials `user` for domain `example.com`, it would look like this: 18 | 19 | ssh user@example.com 20 | 21 |
22 | 23 | ### Running Commands on a Remote Server 24 | You can also run commands on a remote server without logging in interactively 25 | 26 | ssh username@hostname '[command]' 27 | 28 | Let's say you want to run the command `ls -la` on the server of `example.com`, we can use: 29 | 30 | ssh user@example.com 'ls -la' 31 | 32 | 33 | ### Using a Specific Port 34 | If your SSH server is running on a non-standard port (e.g., port 2222): 35 | 36 | ssh -p 2222 username@hostname 37 | 38 | 39 | ### Tunneling with SSH 40 | To create an encrypted tunnel to forward a port: 41 | 42 | ssh -L local_port:remote_address:remote_port username@hostname 43 | 44 | 45 | For example, to forward port 8080: 46 | 47 | ssh -L 8080:localhost:80 john@192.168.1.10 48 | 49 | 50 | ### Transferring Files with SCP 51 | To copy files from your local machine to the remote server: 52 | 53 | scp localfile username@hostname:/path/to/remote/file 54 | 55 | For example: 56 | 57 | scp myfile.txt john@192.168.1.10:/home/john/myfile.txt 58 | 59 | 60 |
61 | 62 | ## Using SSH Keys for Authentication 63 | ### Generating SSH Keys 64 | To generate a new SSH key pair, use the ssh-keygen command: 65 | 66 | ssh-keygen -t rsa -b 4096 -C "your_email@example.com" 67 | 68 | - `-t rsa`: Specifies the type of key to create (RSA). 69 | - `-b 4096`: Specifies the number of bits in the key (4096 bits). 70 | - `-C "your_email@example.com"`: Adds a label to the key. 71 | 72 | Follow the prompts to save the key pair to the default location (~/.ssh/id_rsa). 73 | 74 |
75 | 76 | ### Copying the Public Key to the Server 77 | To use the SSH key for authentication, you need to copy the public key to the remote server. You can use the ssh-copy-id command: 78 | 79 | ssh-copy-id username@hostname 80 | 81 | Example: 82 | 83 | ssh-copy-id user@example.com 84 | 85 | Alternatively, you can manually copy the public key: 86 | 87 | Display the public key: 88 | 89 | cat ~/.ssh/id_rsa.pub 90 | 91 | Copy the output and add it to the ~/.ssh/authorized_keys file on the remote server. 92 | 93 |
94 | 95 | ### Connecting Using SSH Keys 96 | Once the public key is added to the remote server, you can connect without a password: 97 | 98 | ssh username@hostname 99 |
100 | 101 | 102 | ## Configuring SSH Access for Multiple Users 103 | ### Setting Up SSH Keys for Multiple Users 104 | To allow multiple group members to connect to a VPS using SSH keys, each member needs to generate their own SSH key pair and add their public key to the server. 105 | 106 | Generate SSH Keys: Each user generates their own SSH key pair using ssh-keygen. 107 | Copy Public Keys to the Server: Each user copies their public key to the server using ssh-copy-id or manually. 108 | 109 |
110 | 111 | ### Adding Multiple Keys to authorized_keys 112 | On the remote server, the ~/.ssh/authorized_keys file can contain multiple public keys. Each key should be on a new line. 113 | 114 | Example: 115 | 116 | ssh-rsa AAAAB3... user1@example.com 117 | ssh-rsa AAAAB3... user2@example.com 118 | ssh-rsa AAAAB3... user3@example.com 119 | 120 |
121 | 122 | ### Managing Access 123 | To manage access, you can add or remove keys from the authorized_keys file. Ensure that the file permissions are set correctly: 124 | 125 | chmod 600 ~/.ssh/authorized_keys 126 | chmod 700 ~/.ssh 127 | 128 |
129 | 130 | ### Group Management 131 | If you want to manage access for a group of users, you can create a group on the server and add users to that group. Ensure that the authorized_keys file is accessible to all group members. 132 | 133 | Example: 134 | 135 | Create a group: 136 | 137 | sudo groupadd sshusers 138 | 139 | Add users to the group: 140 | 141 | sudo usermod -aG sshusers user1 142 | sudo usermod -aG sshusers user2 143 | 144 | Set the correct permissions for the .ssh directory and authorized_keys file: 145 | 146 | sudo chown -R user1:sshusers /home/user1/.ssh 147 | sudo chmod 770 /home/user1/.ssh 148 | sudo chmod 660 /home/user1/.ssh/authorized_keys 149 | 150 |
151 | 152 | ### Securing Your SSH Server 153 | To enhance the security of your SSH server, consider the following configurations in your `/etc/ssh/sshd_config` file: 154 | 155 | Disable Root Login: 156 | 157 | PermitRootLogin no 158 | 159 | Limit User Logins: 160 | 161 | AllowUsers john 162 | 163 | Use Stronger Encryption Algorithms: 164 | 165 | Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com 166 | 167 | Enable Two-Factor Authentication (2FA): 168 | 169 | AuthenticationMethods publickey,password -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/08_tips.md: -------------------------------------------------------------------------------- 1 | # Best practices and Tips 2 | 3 | You've learned a lot of commands during this workshop, commands designed for the shell and commands to use in Bash scripting. \ 4 | This page gives a brief overview of best practices and tips for using the shell and Bash. 5 | 6 |
7 | 8 | ### Use Tab Completion 9 | Tab completion helps you quickly complete commands, file names, and directory names. \ 10 | Just start typing and press `Tab` to auto-complete or see suggestions. 11 | 12 | ### Command History 13 | Use the up and down arrow keys to scroll through your command history. \ 14 | This saves time by allowing you to reuse previous commands. 15 | 16 | Use `Ctrl + R` to search through your command history. \ 17 | Start typing a part of the command and it will show the most recent match. 18 | 19 | ### Aliases 20 | Create aliases for frequently used commands to save time. 21 | 22 | alias ll='ls -la' 23 | 24 | Add this to your `.bashrc` or `.bash_profile` to make it permanent. 25 | 26 | ### Use Wildcards 27 | Wildcards can help you work with multiple files at once. 28 | - `*` matches any number of characters. 29 | - `?` matches a single character. 30 | - `[abc]` matches any one of the characters inside the brackets. 31 | 32 | ### Use man and --help 33 | Use the man command to read the manual pages for commands. 34 | 35 | man ls 36 | 37 | Most commands also support `--help` to display a summary of options. 38 | 39 | ls --help 40 | 41 | ### Redirecting Output 42 | Redirect standard output and error to different files. 43 | 44 | command > output.txt 2> error.txt 45 | 46 | ### Background Processes 47 | Run commands in the background by appending `&` at the end. 48 | 49 | long_running_command & 50 | 51 |
52 | 53 | ## Bash Scripting 54 | 55 | 56 | ### Start with a Shebang 57 | Always start your script with a shebang to specify the interpreter. 58 | ```sh 59 | #!/bin/bash 60 | ``` 61 | 62 | ### Make Scripts Executable 63 | Make your script executable using chmod. 64 | 65 | chmod +x script.sh 66 | 67 | ### Use Comments 68 | Use comments to explain your code. This makes it easier to understand and maintain. 69 | ```sh 70 | # This is a comment 71 | echo "Hello, World!" 72 | ``` 73 | 74 | ### Use Variables 75 | Use variables to store and reuse values. 76 | ```sh 77 | name="Alice" 78 | echo "Hello, $name" 79 | ``` 80 | 81 | ### Use Functions 82 | Use functions to organize your code and avoid repetition. 83 | ```sh 84 | greet() { 85 | echo "Hello, $1" 86 | } 87 | greet "Alice" 88 | ``` 89 | 90 | ### Error Handling 91 | Check the exit status of commands to handle errors. 92 | ```sh 93 | if [ $? -ne 0 ]; then 94 | echo "An error occurred" 95 | fi 96 | ``` 97 | 98 | ### Use set Options 99 | Use set options to improve script robustness. 100 | ```sh 101 | set -e: Exit immediately if a command exits with a non-zero status. 102 | set -u: Treat unset variables as an error. 103 | set -o pipefail: Return the exit status of the last command in the pipeline that failed. 104 | set -euo pipefail 105 | ``` 106 | 107 | ### Use read for User Input 108 | Use read to get input from the user. 109 | ```sh 110 | read -p "Enter your name: " name 111 | echo "Hello, $name" 112 | ``` 113 | 114 | ### Debugging 115 | Use `bash -x script.sh` to run your script in debug mode and see each command executed. 116 | 117 | ### Use trap for Cleanup 118 | Use `trap` to execute commands when the script exits, which is useful for cleanup tasks. 119 | 120 | trap 'echo "Cleaning up..."; rm -f temp_file' EXIT -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/09_resources.md: -------------------------------------------------------------------------------- 1 | # Resources for further learning 2 | For more in depth information about shells, bash scripting and ssh, the following resources could help. 3 | 4 | - https://www.explainshell.com/ 5 | 6 | - https://phoenixnap.com/kb/bash-commands 7 | 8 | - https://dev.to/devrx/shell-scripting-101-essential-commands-for-every-developer-j3p 9 | 10 | - https://www.gnu.org/software/bash/manual/bash.html 11 | 12 | - https://github.com/awesome-lists/awesome-bash 13 | 14 | - https://www.howtogeek.com/362409/what-is-zsh-and-why-should-you-use-it-instead-of-bash/ 15 | 16 | - https://www.sitepoint.com/zsh-tips-tricks/ 17 | 18 | - https://fishshell.com/docs/current/cmds/fish 19 | 20 | - https://github.com/jorgebucaran/awsm.fish 21 | 22 | - https://learn.microsoft.com/en-us/powershell/scripting/learn/more-powershell-learning?view=powershell-7.4 23 | 24 | - https://wiki.archlinux.org/title/Dash 25 | 26 | - https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys 27 | 28 | - https://www.cloudflare.com/learning/access-management/what-is-ssh/ 29 | 30 | - https://opensource.com/article/20/9/ssh -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/assets/images/bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Operating systems and Bash/assets/images/bash.png -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/assets/images/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Operating systems and Bash/assets/images/dash.png -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/assets/images/fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Operating systems and Bash/assets/images/fish.png -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/assets/images/powershell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Operating systems and Bash/assets/images/powershell.png -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/assets/images/ssh-example.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Operating systems and Bash/assets/images/ssh-example.webp -------------------------------------------------------------------------------- /Workshop - Operating systems and Bash/assets/images/zshell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Operating systems and Bash/assets/images/zshell.png -------------------------------------------------------------------------------- /Workshop - Refactoring/01_introduction.md: -------------------------------------------------------------------------------- 1 | # Hands-On Code Refactoring 2 | 3 | ## Code gets "dirty" 4 | It's the programmer's task to ship features. Once finished with the current feature we move on to the next and the next. But as a project progresses entropy kicks in. This means that code becomes harder to read and to maintain. As a result bugs creep in, the performance goes down and our feature velocity grinds to a halt. 5 | 6 | Code gets "dirty" because of 7 | 8 | - Inexperience 9 | - Hard deadlines 10 | - Shortcuts 11 | - Unknowns 12 | 13 | Another word for "dirty code" is "technical debt" and it's our task to fight it proactively during the development process by refactoring our code. 14 | 15 | ## What is code refactoring? 16 | Refactoring means (re)organizing your code **without modifying its original functionality**. Refactoring is the process of making **small** changes or adjustments to your code without affecting or changing how the code functions while in use. 17 | 18 | ## Benefits of refactoring 19 | 20 | ### It helps improve structure and coherence 21 | Refactoring helps you **improve the design** of your software. Developing applications is a difficult task. As you add additional functions, the relevance of your design may be affected. Then, abstractions are no longer as pure as they once were. 22 | 23 | #### Example 24 | 25 | > We started with a `Bird` class which contains a `fly()` method. From it we derived the `Swan`, `Eagle` and the `Dove` type. All works fine, but then a `Pinguin` enters the scence, followed by a `Kiwi` and an `Ostrich`. So the `fly()` method needs to moved to adjust for the latter type of birds. It's a general rule that we will encounter stuff we did not account for. 26 | 27 | You can improve the structure and coherence of your programs by refactoring your code **regularly**. 28 | 29 | ### It gives a better understanding of the code 30 | If you refactor properly, your code will be more easily understandable afterwards. Your code will also be easier to understand by improving the design. 31 | 32 | #### Example 33 | 34 | > If you find pieces of code where you need to do a lot of "pointer chasing" it is generally a good idea to refactor the code. Same is true for a lot of functions calling each other to model simple functionality. Chasing functions and pointers makes your code hard to understand. 35 | 36 | It is common knowledge that developers read code far more frequently than they write it. As a result, it's in your best interest to keep things as simple as possible, which considerably improves maintainability. Also, people who read it in the future will be grateful. 37 | 38 | ### Refactoring broadens your knowledge 39 | Finally, refactoring is a method of **active learning**. Even if you didn't write the code, refactoring it gives you a better grasp of what it does. And by reading the code of your collegues you will learn other possible ways to write code and absorb good practices. 40 | 41 | **Warning** 42 | > It may be tempting to show-off your skills and impress your collegues by introducing "superstar code". Don't do that or you'll enter into an arms race and the readability of your code spirals out of control. Again: keep things as simple as possible. 43 | 44 | ## Quick discussion 45 | Briefly share your experiences with refactoring during Project B. -------------------------------------------------------------------------------- /Workshop - Refactoring/04_tools.md: -------------------------------------------------------------------------------- 1 | # Refactoring and IDE Support 2 | Because refactoring is so important all modern Integrated Developer Environments (IDEs) have refactor capabilities built-in or have plugins available. Here we will explore the refactoring capabilities of Visual Studio Code (VSCode). We assume you have the **Python** and **Pylance** plugins installed. 3 | 4 | ## Renaming functions and variables 5 | VSCode makes renaming functions and variables extremely easy. 6 | 7 | ### Preparation 8 | Open a new VSCode window (`File > New Window`) and open the folder `tools-example`. The example files contain multiple typos, which we want to correct. 9 | 10 | ### Rename strategy 11 | We have to correct variable names, function names, text in comments and text in strings. For fixing typos we have two methods to our disposal: 12 | 13 | - Rename symbol 14 | - Find & replace 15 | 16 | Our strategy is first to rename our functions, then our variables and lastly strings and comments. 17 | 18 | ### Rename symbol 19 | Let's start with `rename symbol`. To show the power of this feature, turn the `printString()` function into camel casing. 20 | 21 | Select the function name and press `F2`. This let's us rename the function over the **entire** code base. Any reference to this function will be renamed. 22 | 23 | Let's also rename the misspelled `nam` variable. 24 | 25 | **Limitation** 26 | > You cannot globally rename comments. Try it. 27 | 28 | **Warning** 29 | > You cannot rename built-in class methods (try renaming the `Dict.strip()` method), but be aware that you *can* rename functions and methods in the standard modules. 30 | > 31 | > Try renaming the `random.choices()` function and check that it is indeed changes in the random module. And change it back to its original form to prevent problems in other code that depends on the random module. 32 | 33 | ### Find & replace 34 | With our variables and functions renamed, we can now safely rename our strings and comments. Here we have two options: 35 | 36 | 1. Use `ctrl or cmd` + `shift` + `f` to find & replace inside a single file 37 | 2. Use `ctrl or cmd` + `shift` + `h` to find & replace inside all files 38 | 39 | Since both files contain a misspelled 'nam' in the comments, we use `ctrl or cmd` + `shift` + `h`. 40 | 41 | **Tip** 42 | > Never ever rename function or variable names by hand. Not only is it slower, you might also introduce typo's and thereby bugs. 43 | 44 | ## Extracting functions 45 | Another useful feature is the `extract into` functionality. 46 | 47 | To show how this works you need to select the code you want to convert into a function. If we look at the `process_user_data()` function than we see that this is a good candidate for refactoring. So let's refactor this function by splitting it up in multiple, smaller functions. 48 | 49 | 1. Select the code block below: 50 | 51 | ```python 52 | name = user_data['name'] 53 | if not isinstance(name, str) or not name.strip(): 54 | raise ValueError("Invalid name") 55 | name = nam.strip().title() 56 | ``` 57 | 2. Use `ctrl` + `shift` + `r` to extract the function 58 | 59 | 3. Rename the assigned function name `jls_extract_def` to `process_name` 60 | 61 | Repeat the steps above for the code below the comments: 62 | 63 | - Process age 64 | - Process email 65 | - Save to database (simulated) 66 | 67 | > Congratulations: you've mastered some very basic but powerful refactoring techniques. -------------------------------------------------------------------------------- /Workshop - Refactoring/06_resources.md: -------------------------------------------------------------------------------- 1 | # References and Further reading 2 | 3 | This workshop is only an introduction. Here you find more in-depth information, but you are encouraged to dig in further. 4 | 5 | ## Refactoring 6 | 7 | - [Wikipedia](https://en.wikipedia.org/wiki/Code_refactoring) 8 | - [Refactoring Guru](https://refactoring.guru/refactoring) 9 | - [What is Refactoring, and why is it so important?](https://www.youtube.com/watch?v=PGjrn9Ci2aY) 10 | - [Code Refactoring Best Practices](https://www.freecodecamp.org/news/best-practices-for-refactoring-code) 11 | - [Techniques, Tools, and Best Practices](https://www.codesee.io/learning-center/python-refactoring) 12 | - [Refactoring Workshop](https://github.com/benchristel/refactoring-workshop) 13 | - [Red-Green-Refactor method](https://www.youtube.com/watch?v=fx-Ne_s71iY) 14 | - [Clean Code Is Killing Your Projects](https://www.youtube.com/watch?v=1uzlBSL7-UM) 15 | 16 | ## Documentation generation 17 | 18 | - [How to generate documentation from python doc strings](https://www.youtube.com/watch?v=BWIrhgCAae0) 19 | 20 | ## Code conventions 21 | 22 | - [How to Write Beautiful Python Code With PEP 8](https://realpython.com/python-pep8) 23 | 24 | ## Design Patterns 25 | 26 | - [Wikipedia](https://en.wikipedia.org/wiki/Design_Patterns) 27 | - [Design Patterns 101](https://medium.com/@digicore/software-design-patterns-101-a-beginners-guide-c6860ef8bb63) 28 | - [Design Patterns Guru](https://refactoring.guru/design-patterns) 29 | - [Coursera](https://www.coursera.org/learn/design-patterns) -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/.DS_Store -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/Calculator.rst: -------------------------------------------------------------------------------- 1 | Calculator module 2 | ================= 3 | 4 | .. automodule:: calculator.Calculator 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/.DS_Store -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/doctrees/Calculator.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/doctrees/Calculator.doctree -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/doctrees/environment.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/doctrees/environment.pickle -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/doctrees/index.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/doctrees/index.doctree -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/doctrees/modules.doctree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/doctrees/modules.doctree -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 3cff2f7158fb95a5895456a646ad31c5 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_modules/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Overview: module code — Calculator 0.0.0 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | 30 |
31 | 32 |

All modules for which code is available

33 | 35 | 36 |
37 | 38 |
39 |
40 | 84 |
85 |
86 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_sources/Calculator.rst.txt: -------------------------------------------------------------------------------- 1 | Calculator module 2 | ================= 3 | 4 | .. automodule:: calculator.Calculator 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_sources/index.rst.txt: -------------------------------------------------------------------------------- 1 | .. Calculator documentation master file, created by 2 | sphinx-quickstart on Mon May 27 13:32:03 2024. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Calculator's documentation! 7 | ====================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | modules 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_sources/modules.rst.txt: -------------------------------------------------------------------------------- 1 | src 2 | === 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | Calculator 8 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Base JavaScript utilities for all Sphinx HTML documentation. 6 | * 7 | * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | "use strict"; 12 | 13 | const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ 14 | "TEXTAREA", 15 | "INPUT", 16 | "SELECT", 17 | "BUTTON", 18 | ]); 19 | 20 | const _ready = (callback) => { 21 | if (document.readyState !== "loading") { 22 | callback(); 23 | } else { 24 | document.addEventListener("DOMContentLoaded", callback); 25 | } 26 | }; 27 | 28 | /** 29 | * Small JavaScript module for the documentation. 30 | */ 31 | const Documentation = { 32 | init: () => { 33 | Documentation.initDomainIndexTable(); 34 | Documentation.initOnKeyListeners(); 35 | }, 36 | 37 | /** 38 | * i18n support 39 | */ 40 | TRANSLATIONS: {}, 41 | PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), 42 | LOCALE: "unknown", 43 | 44 | // gettext and ngettext don't access this so that the functions 45 | // can safely bound to a different name (_ = Documentation.gettext) 46 | gettext: (string) => { 47 | const translated = Documentation.TRANSLATIONS[string]; 48 | switch (typeof translated) { 49 | case "undefined": 50 | return string; // no translation 51 | case "string": 52 | return translated; // translation exists 53 | default: 54 | return translated[0]; // (singular, plural) translation tuple exists 55 | } 56 | }, 57 | 58 | ngettext: (singular, plural, n) => { 59 | const translated = Documentation.TRANSLATIONS[singular]; 60 | if (typeof translated !== "undefined") 61 | return translated[Documentation.PLURAL_EXPR(n)]; 62 | return n === 1 ? singular : plural; 63 | }, 64 | 65 | addTranslations: (catalog) => { 66 | Object.assign(Documentation.TRANSLATIONS, catalog.messages); 67 | Documentation.PLURAL_EXPR = new Function( 68 | "n", 69 | `return (${catalog.plural_expr})` 70 | ); 71 | Documentation.LOCALE = catalog.locale; 72 | }, 73 | 74 | /** 75 | * helper function to focus on search bar 76 | */ 77 | focusSearchBar: () => { 78 | document.querySelectorAll("input[name=q]")[0]?.focus(); 79 | }, 80 | 81 | /** 82 | * Initialise the domain index toggle buttons 83 | */ 84 | initDomainIndexTable: () => { 85 | const toggler = (el) => { 86 | const idNumber = el.id.substr(7); 87 | const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); 88 | if (el.src.substr(-9) === "minus.png") { 89 | el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; 90 | toggledRows.forEach((el) => (el.style.display = "none")); 91 | } else { 92 | el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; 93 | toggledRows.forEach((el) => (el.style.display = "")); 94 | } 95 | }; 96 | 97 | const togglerElements = document.querySelectorAll("img.toggler"); 98 | togglerElements.forEach((el) => 99 | el.addEventListener("click", (event) => toggler(event.currentTarget)) 100 | ); 101 | togglerElements.forEach((el) => (el.style.display = "")); 102 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); 103 | }, 104 | 105 | initOnKeyListeners: () => { 106 | // only install a listener if it is really needed 107 | if ( 108 | !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && 109 | !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS 110 | ) 111 | return; 112 | 113 | document.addEventListener("keydown", (event) => { 114 | // bail for input elements 115 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 116 | // bail with special keys 117 | if (event.altKey || event.ctrlKey || event.metaKey) return; 118 | 119 | if (!event.shiftKey) { 120 | switch (event.key) { 121 | case "ArrowLeft": 122 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 123 | 124 | const prevLink = document.querySelector('link[rel="prev"]'); 125 | if (prevLink && prevLink.href) { 126 | window.location.href = prevLink.href; 127 | event.preventDefault(); 128 | } 129 | break; 130 | case "ArrowRight": 131 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 132 | 133 | const nextLink = document.querySelector('link[rel="next"]'); 134 | if (nextLink && nextLink.href) { 135 | window.location.href = nextLink.href; 136 | event.preventDefault(); 137 | } 138 | break; 139 | } 140 | } 141 | 142 | // some keyboard layouts may need Shift to get / 143 | switch (event.key) { 144 | case "/": 145 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 146 | Documentation.focusSearchBar(); 147 | event.preventDefault(); 148 | } 149 | }); 150 | }, 151 | }; 152 | 153 | // quick alias for translations 154 | const _ = Documentation.gettext; 155 | 156 | _ready(Documentation.init); 157 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | const DOCUMENTATION_OPTIONS = { 2 | VERSION: '0.0.0', 3 | LANGUAGE: 'en', 4 | COLLAPSE_INDEX: false, 5 | BUILDER: 'html', 6 | FILE_SUFFIX: '.html', 7 | LINK_SUFFIX: '.html', 8 | HAS_SOURCE: true, 9 | SOURCELINK_SUFFIX: '.txt', 10 | NAVIGATION_WITH_KEYS: false, 11 | SHOW_SEARCH_SUMMARY: true, 12 | ENABLE_SEARCH_SHORTCUTS: true, 13 | }; -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/html/_static/file.png -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/html/_static/minus.png -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/html/_static/plus.png -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/genindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index — Calculator 0.0.0 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 29 | 30 |
31 | 32 | 33 |

Index

34 | 35 |
36 | A 37 | | C 38 | | D 39 | | M 40 | | S 41 | 42 |
43 |

A

44 | 45 | 49 |
50 | 51 |

C

52 | 53 | 57 | 66 |
    58 |
  • 59 | calculator.Calculator 60 | 61 |
  • 65 |
67 | 68 |

D

69 | 70 | 74 |
75 | 76 |

M

77 | 78 | 87 | 91 |
92 | 93 |

S

94 | 95 | 99 |
100 | 101 | 102 | 103 |
104 | 105 |
106 |
107 | 151 |
152 |
153 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Welcome to Calculator’s documentation! — Calculator 0.0.0 documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 | 34 |
35 |

Welcome to Calculator’s documentation!

36 |
37 |

Contents:

38 | 44 |
45 |
46 |
47 |

Indices and tables

48 | 53 |
54 | 55 | 56 |
57 | 58 |
59 |
60 | 105 |
106 |
107 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/modules.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | src — Calculator 0.0.0 documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 |
36 |

src

37 |
38 | 50 |
51 |
52 | 53 | 54 |
55 | 56 |
57 |
58 | 107 |
108 |
109 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/docs/_build/html/objects.inv -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Python Module Index — Calculator 0.0.0 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 |
30 |
31 | 32 | 33 |
34 | 35 | 36 |

Python Module Index

37 | 38 |
39 | c 40 |
41 | 42 | 43 | 44 | 46 | 47 | 49 | 52 | 53 | 54 | 57 |
 
45 | c
50 | calculator 51 |
    55 | calculator.Calculator 56 |
58 | 59 | 60 |
61 | 62 |
63 |
64 | 108 |
109 |
110 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Search — Calculator 0.0.0 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 | 36 | 37 |
38 | 39 |

Search

40 | 41 | 49 | 50 | 51 |

52 | Searching for multiple words only shows matches that contain 53 | all words. 54 |

55 | 56 | 57 |
58 | 59 | 60 | 61 |
62 | 63 | 64 |
65 | 66 | 67 |
68 | 69 |
70 |
71 | 105 |
106 |
107 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/_build/html/searchindex.js: -------------------------------------------------------------------------------- 1 | Search.setIndex({"alltitles": {"Calculator module": [[0, "module-calculator.Calculator"]], "Contents:": [[1, null]], "Indices and tables": [[1, "indices-and-tables"]], "Welcome to Calculator\u2019s documentation!": [[1, "welcome-to-calculator-s-documentation"]], "src": [[2, "src"]]}, "docnames": ["Calculator", "index", "modules"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1}, "filenames": ["Calculator.rst", "index.rst", "modules.rst"], "indexentries": {"add() (calculator.calculator.calculator method)": [[0, "calculator.Calculator.Calculator.add", false]], "calculator (class in calculator.calculator)": [[0, "calculator.Calculator.Calculator", false]], "calculator.calculator": [[0, "module-calculator.Calculator", false]], "divide() (calculator.calculator.calculator method)": [[0, "calculator.Calculator.Calculator.divide", false]], "module": [[0, "module-calculator.Calculator", false]], "multiply() (calculator.calculator.calculator method)": [[0, "calculator.Calculator.Calculator.multiply", false]], "subtract() (calculator.calculator.calculator method)": [[0, "calculator.Calculator.Calculator.subtract", false]]}, "objects": {"calculator": [[0, 0, 0, "-", "Calculator"]], "calculator.Calculator": [[0, 1, 1, "", "Calculator"]], "calculator.Calculator.Calculator": [[0, 2, 1, "", "add"], [0, 2, 1, "", "divide"], [0, 2, 1, "", "multiply"], [0, 2, 1, "", "subtract"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method"}, "terms": {"A": 0, "If": 0, "The": 0, "add": [0, 2], "anoth": 0, "arithmet": 0, "b": 0, "base": 0, "basic": 0, "between": 0, "calcul": 2, "class": 0, "denomin": 0, "differ": 0, "divid": [0, 2], "first": 0, "float": 0, "from": 0, "i": 0, "index": 1, "method": 0, "modul": [1, 2], "multipli": [0, 2], "number": 0, "numer": 0, "object": 0, "one": 0, "oper": 0, "page": 1, "paramet": 0, "perform": 0, "product": 0, "provid": 0, "quotient": 0, "rais": 0, "return": 0, "search": 1, "second": 0, "simpl": 0, "sourc": 0, "src": 1, "subtract": [0, 2], "sum": 0, "thi": 0, "two": 0, "type": 0, "zero": 0, "zerodivisionerror": 0}, "titles": ["Calculator module", "Welcome to Calculator\u2019s documentation!", "src"], "titleterms": {"": 1, "calcul": [0, 1], "content": 1, "document": 1, "indic": 1, "modul": 0, "src": 2, "tabl": 1, "welcom": 1}}) -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | 9 | import os 10 | import sys 11 | 12 | sys.path.insert(0, os.path.abspath('../src')) 13 | 14 | project = 'Calculator' 15 | copyright = '2024' 16 | author = 'hoofr' 17 | release = '0.0.0' 18 | 19 | # -- General configuration --------------------------------------------------- 20 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 21 | 22 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] 23 | 24 | templates_path = ['_templates'] 25 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 26 | 27 | 28 | 29 | # -- Options for HTML output ------------------------------------------------- 30 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 31 | 32 | html_theme = 'alabaster' 33 | html_static_path = ['_static'] 34 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Calculator documentation master file, created by 2 | sphinx-quickstart on Mon May 27 13:32:03 2024. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Calculator's documentation! 7 | ====================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | modules 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/docs/modules.rst: -------------------------------------------------------------------------------- 1 | src 2 | === 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | Calculator 8 | -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/src/calculator/Calculator.py: -------------------------------------------------------------------------------- 1 | # src/calculator.py 2 | 3 | class Calculator: 4 | """ 5 | A simple calculator class to perform basic arithmetic operations. 6 | 7 | This class provides methods to add, subtract, multiply, and divide two numbers. 8 | """ 9 | 10 | def add(self, a, b): 11 | """ 12 | Add two numbers. 13 | 14 | :param a: The first number. 15 | :type a: float 16 | :param b: The second number. 17 | :type b: float 18 | :return: The sum of a and b. 19 | :rtype: float 20 | """ 21 | return a + b 22 | 23 | def subtract(self, a, b): 24 | """ 25 | Subtract one number from another. 26 | 27 | :param a: The number to be subtracted from. 28 | :type a: float 29 | :param b: The number to subtract. 30 | :type b: float 31 | :return: The difference between a and b. 32 | :rtype: float 33 | """ 34 | return a - b 35 | 36 | def multiply(self, a, b): 37 | """ 38 | Multiply two numbers. 39 | 40 | :param a: The first number. 41 | :type a: float 42 | :param b: The second number. 43 | :type b: float 44 | :return: The product of a and b. 45 | :rtype: float 46 | """ 47 | return a * b 48 | 49 | def divide(self, a, b): 50 | """ 51 | Divide one number by another. 52 | 53 | :param a: The numerator. 54 | :type a: float 55 | :param b: The denominator. 56 | :type b: float 57 | :return: The quotient of a divided by b. 58 | :rtype: float 59 | :raises ZeroDivisionError: If b is zero. 60 | """ 61 | if b == 0: 62 | raise ZeroDivisionError("The denominator b cannot be zero.") 63 | return a / b -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/src/calculator/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Refactoring/sphinx-example/src/calculator/__init__.py -------------------------------------------------------------------------------- /Workshop - Refactoring/sphinx-example/workshop.md: -------------------------------------------------------------------------------- 1 | # Spinx documentation 2 | Here you find the steps to generate documentation from the docstring in the code. 3 | 4 | ## Prerequisites 5 | 6 | ### Install Sphinx 7 | `pip install sphinx` 8 | 9 | ## Setup 10 | We have already setup the config to speed up the workshop. If you want to do it yourself you must run `sphinx-quickstart` first and then consult the resources for some tutorials. 11 | 12 | ## Generation 13 | 14 | ### 1. Enter the project folder 15 | `cd sphinx-example` 16 | 17 | ### 2. Check the Calculator docstrings 18 | Open the `Calculator` class and see how we have added the docstring. 19 | 20 | ## 3. Generate the documentation 21 | - Make sure you are in the root of the `sphinx-example` folder 22 | - Now run `sphinx-apidoc -o ./docs ./src/` to generate the docs 23 | 24 | ## 4. View the documentation 25 | Find the index.html and open it in your browser. 26 | 27 | ## 5. Extend the documentation 28 | - Play around in the Calculator class, add some new methods 29 | - Add a new module or class and see what it does to your docs 30 | 31 | ## 6. Apply to CargoHub API 32 | Use the `sphinx-example` as a template for your CargoHub API code and start documenting your code base. -------------------------------------------------------------------------------- /Workshop - Refactoring/tools-example/main.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | 4 | from mod import printString 5 | 6 | def process_user_data(user_data): 7 | # Validate user data 8 | if not isinstance(user_data, dict): 9 | raise ValueError("Invalid data format") 10 | if 'nam' not in user_data or 'age' not in user_data or 'email' not in user_data: 11 | raise ValueError("Missing required fields") 12 | 13 | # Process nam 14 | nam = user_data['nam'] 15 | if not isinstance(nam, str) or not nam.strip(): 16 | raise ValueError("Invalid nam") 17 | nam = nam.strip().title() 18 | 19 | # Process age 20 | age = user_data['age'] 21 | if not isinstance(age, int) or age <= 0: 22 | raise ValueError("Invalid age") 23 | 24 | # Process email 25 | email = user_data['email'] 26 | if not isinstance(email, str) or '@' not in email: 27 | raise ValueError("Invalid email") 28 | email = email.lower() 29 | 30 | # Generate user ID 31 | user_id = ''.join(random.choices(string.ascii_letters + string.digits, k=8)) 32 | 33 | # Save to database (simulated) 34 | database = [] 35 | database.append({ 36 | 'user_id': user_id, 37 | 'nam': nam, 38 | 'age': age, 39 | 'email': email 40 | }) 41 | 42 | return user_id 43 | 44 | def main(): 45 | printString("Program starting...") 46 | print("Welcome to the User Data Processing Program!") 47 | print("Please provide the following details:") 48 | nam = input("nam: ") 49 | age = int(input("Age: ")) 50 | email = input("Email: ") 51 | 52 | user_data = { 53 | 'nam': nam, 54 | 'age': age, 55 | 'email': email 56 | } 57 | 58 | try: 59 | user_id = process_user_data(user_data) 60 | print("User data processed successfully.") 61 | print("User ID:", user_id) 62 | except ValueError as e: 63 | print("Error processing user data:", e) 64 | 65 | printString("Program ended.") 66 | 67 | if __name__ == "__main__": 68 | main() -------------------------------------------------------------------------------- /Workshop - Refactoring/tools-example/mod.py: -------------------------------------------------------------------------------- 1 | def printString(s): 2 | # A misspelled 'nam' here to demonstrate 3 | # the find & replace in files feature 4 | print(s) -------------------------------------------------------------------------------- /Workshop - Requirements Specification/01_introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | In this workshop you will learn about requirements, how to collect them and how to write them down. To be able to document the requirements for the CargoHub API we need to develop a basic understanding of RESTful APIs and how to read them. That's why RESTful API reading practice is included in this workshop. But first: requirements. 3 | 4 | ## Objectives: 5 | - Understand the principles of REST and its application in software development. 6 | - Learn how to gather, analyze, and document software requirements. 7 | - Apply REST principles to design and implement a simple RESTful API. 8 | - Integrate software requirements into the development process. 9 | - Retrieve requirements from existing, undocumented software. 10 | 11 | ## Why requirements? 12 | Well, try to build something with just a *single* requirement: 13 | 14 | - We need a bridge to cross over 15 | 16 | ### Activity 17 | Suppose you are tasked to build this bridge. How would you proceed? 18 | 19 | Take some time to write down your strategy. 20 | 21 | ### Possible answer 22 | First you need to recognize that this requirement is not very helpful. You need more information to proceed. For example: where should the bridge be build? Is it to cross a river or a road? From that you could derive how long the bridge would need to be. You should also need to know if the bridge is for pedestrians, for cyclist and/or for cars. This determines the strength, the width and the material, which in turn determines the costs of the bridge. Etcetera. 23 | 24 | > Without requirements we don't know *what* to build and, as a result, *how* to build it. 25 | 26 | Notice the difference between **what** and **how**: 27 | 28 | - Requirements are about *what* to build 29 | - Design is about *how* to build it 30 | 31 | The design (of the system, user experience and interface) always *follows* from the requirements. Given the time, money and resources, it is the task of the (software) engineer to come up with an optimal solution that fits the requirements. 32 | 33 | > Engineering is about building an optimal solution. Every decision you make will be about juggling multiple requirements. 34 | 35 | ## Requirement gathering 36 | Going back to the bridge building example: the asking for clarity is the process of gathering requirements. 37 | 38 | > During the project the technical teacher knows about the details and it is up to you to ask for clarification. 39 | 40 | In reality we start with more than one requirement and during the gathering phase we try te refine the demands and needs such that we can build the right thing. 41 | 42 | Speaking of the 'right thing': 43 | 44 | - Good **requirements** ensure that we build *the right thing* 45 | - Good **design** ensures that that we build *the thing right* 46 | 47 | It really depends on the experience of the team and the complexity & nature of the project which requirments need be known up front, and which can be left to be refined during the project. 48 | 49 | ### Activity 50 | Try to explain what the items below have in common and what makes them different: 51 | 52 | - Building a chair 53 | - Building an airplane 54 | - Building a thesis evaluation tool for teachers 55 | 56 | ### Possible answers 57 | Although a chair and airplane differ in complexity, their goal is pretty clear. Given the constraints (size, speed, weight, ...), one could start planning the construction process pretty soon: we can adopt a waterfall process. 58 | 59 | This cannot be said about the thesis evaluation tool. What should it even do? Here we need to do a lot of research up front and adjusting during the process to build the right thing: we should choose for an agile approach. 60 | 61 | - With *lots of unknows* an **agile approach** may be preferred 62 | - With *little unknowns* a **waterfall method** may be preferred 63 | 64 | ### Activity 65 | Reading the course manual, what would be a good approach for this project for your team? 66 | 67 | ## Summary 68 | We need requirements else we don't know what to build. 69 | 70 | In the next chapter we will look at different types of requirements. -------------------------------------------------------------------------------- /Workshop - Requirements Specification/04_combining.md: -------------------------------------------------------------------------------- 1 | # Combining REST and Requirements 2 | Now we have a basic understanding of RESTful APIs and requirements, let's combine the two. 3 | 4 | ### Question 5 | Looking back at the different types of requirements, which types apply to APIs? 6 | 7 | Choose from: 8 | 9 | - Business requirements 10 | - User requirements 11 | - Functional requirements 12 | - Non-functional requirements 13 | 14 | ### Answer 15 | In short: they all apply. 16 | 17 | You might think that user requirements don't apply to APIs. Even though we do not directly interact with the end users, the actual users of our API are our collegue developers. 18 | 19 | ### Question 20 | What should they need to be able to work with our API? 21 | 22 | ### Answer 23 | Indeed: good documentation. It is your teams goal to provide good documentation of the CargoHub API during this project. 24 | 25 | ## Mapping Requirements to RESTful API Design 26 | During the project you get an existing API code base and it is your task to reverse engineer the functional requirements it implements. 27 | 28 | ### Question 29 | Given the endpoints below, what kind of app does this RESTful API represent? 30 | 31 | - `https://api.app.com/lists` 32 | - `https://api.app.com/members` 33 | - `https://api.app.com/lists/tasks` 34 | - `https://api.app.com/lists/tasks/members` 35 | 36 | ### Answer 37 | It could be the API of a collaborative to-do app. 38 | 39 | ### Question 40 | The direct users of our API are the developers that need to implement the app. They require that: 41 | 42 | - The API should be easy to understand 43 | - The API should be easy to work with 44 | 45 | Does the endpoint description satisfy this demand? 46 | 47 | ### Answer 48 | Not really. It does describe which resources there are and how they relate, but this is not enough to work with this API. For example: it is not clear what properties a member has and how to update those. 49 | 50 | ### Question 51 | What functional requirements can you deduce from the endpoints and the fact that the API exposes the logic of a collaborative to-do app? 52 | 53 | ### Possible Answer 54 | It's a to-do app so the API should support: 55 | 56 | - Creating a to-do list 57 | - Changing the name of a to-do list 58 | - Remove a to-do list 59 | - Listing the to-do lists 60 | - Adding tasks to a to-do list 61 | - Checking tasks from a to-do list 62 | - Removing tasks from the to-do lists 63 | 64 | Since it is a collaborative to-do list, the API should also support: 65 | 66 | - Inviting new members 67 | - Coupling one or more members to a certain task 68 | - Showing the members attached to a task 69 | - Removing members from a certain task 70 | 71 | ### Question 72 | Can you deduce any non-functional requirement from the information above? 73 | 74 | ### Answer 75 | Not really. It is clear that it is a collaborative to-do app, but it is not clear how many concurrent members the app should support. It is further clear that the API should be well described for our collegue developers, but nothing is mentioned about the code base itself. Are we expected to document our code? Etcetera. 76 | 77 | ## Conclusion 78 | In this lesson we have deduced some basic requirements from endpoint only. It is your task to reverse engineer all requirements from the CargoHub code base. To help you document your reseach we end with some structure, tips and tricks. -------------------------------------------------------------------------------- /Workshop - Requirements Specification/06_resources.md: -------------------------------------------------------------------------------- 1 | ## Requirements 2 | - [Waterfall versus Agile](https://www.youtube.com/watch?v=XP4o0ArkP4s) 3 | - [Types of requirements](https://www.techtarget.com/searchsoftwarequality/answer/What-are-requirements-types) 4 | - [Functional requirements](https://en.wikipedia.org/wiki/Functional_requirement) 5 | - [Non-functional requirements](https://en.wikipedia.org/wiki/Non-functional_requirement) 6 | 7 | ## REST 8 | - [HTTP protocol](https://developer.mozilla.org/en-US/docs/Web/HTTP) 9 | - [HTTP messages](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages) 10 | - [REST versus RPC](https://www.geeksforgeeks.org/difference-between-rest-api-and-rpc-api) 11 | - [REST Explainer](https://www.youtube.com/watch?v=6sUbt-Qp6Pg) 12 | - [Uniform Resource Identifier](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier) 13 | - [Uniform Resource Locator](https://en.wikipedia.org/wiki/URL) 14 | 15 | ## Hoppscotch 16 | - [API explorer](https://hoppscotch.io) 17 | - [Connect to localhost](https://github.com/hoppscotch/hoppscotch-extension) 18 | 19 | ## API & requirements 20 | - [Functional and non-functional](https://www.akana.com/blog/api-requirements-what-consider) 21 | - [How to build an API](https://blog.postman.com/how-to-build-an-api) 22 | 23 | ## Requirements specification 24 | - [Checklist with Examples](https://medium.com/@growsolutions/functional-and-non-functional-requirements-the-ultimate-checklist-with-examples-cde16aba33d7) 25 | - [Hire good writers](https://basecamp.com/gettingreal/08.6-wordsmiths) -------------------------------------------------------------------------------- /Workshop - Requirements Specification/images/smile-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - Requirements Specification/images/smile-32.png -------------------------------------------------------------------------------- /Workshop - Software Testing/03_automation.md: -------------------------------------------------------------------------------- 1 | # Automating tests 2 | Automated testing is a crucial practice in software development. It helps ensure the quality, reliability, and correctness of your codebase. Let’s explore some key aspects related to automating tests. 3 | 4 |
5 | 6 | ## Tools 7 | 8 | ### Pytest 9 | Pytest is a popular testing framework for Python. It provides a simple and efficient way to write and execute test cases. Some of its features include: 10 | 11 | - **Concise Syntax**: Pytest allows you to write test functions using a clean and readable syntax. You can use plain Python assert statements or more advanced assertions. 12 | - **Fixture Support**: Fixtures allow you to set up and tear down resources needed for testing (e.g., database connections, mock services). Pytest makes it easy to define and use fixtures. 13 | - **Powerful Test Discovery**: Pytest automatically discovers and runs all test files in your project directory. No need to explicitly specify test paths. 14 | - **Plugins**: Pytest has a rich ecosystem of plugins that extend its functionality. You can find plugins for coverage reporting, parallel test execution, and more. 15 | 16 | If we look at our `Calculator` class, a simple unittest via the build in `unittest` of Python looked something like: 17 | ```python 18 | import unittest 19 | from calculator import Calculator 20 | 21 | 22 | class TestCalculator(unittest.TestCase): 23 | def setUp(self): 24 | self.calculator = Calculator() 25 | 26 | def test_add(self): 27 | self.assertEqual(self.calculator.add(1, 2), 3) 28 | 29 | def test_subtract(self): 30 | self.assertEqual(self.calculator.subtract(5, 3), 2) 31 | 32 | if __name__ == '__main__': 33 | unittest.main() 34 | ``` 35 | 36 | Running the test would be done via: 37 | ``` 38 | python test_calculator.py 39 | ``` 40 | 41 | ### Converting to pytest 42 | If we want to use `pytest`, we need to install it via `pip` the package-manager of Python. 43 | ``` 44 | pip install pytest 45 | ``` 46 | 47 | We could now convert our unittest as follow 48 | ```python 49 | import pytest 50 | from calculator import Calculator # Assuming you have a Calculator class 51 | 52 | @pytest.fixture 53 | def calculator(): 54 | return Calculator() 55 | 56 | def test_add(calculator): 57 | assert calculator.add(1, 2) == 3 58 | 59 | def test_subtract(calculator): 60 | assert calculator.subtract(5, 3) == 2 61 | ``` 62 | 63 | We run this test by executing the following command: 64 | ``` 65 | pytest test_calculator.py 66 | ``` 67 | 68 |
69 | 70 | > Both pytest and unittest can be used and in the previous example you see no big difference, pytest uses `assert` for most testcases, which makes it easier to write. It also does not need a `if __name__ == "__main__"` that claass the test. 71 | 72 |
73 | 74 | ### Other languages 75 | While Pytest is popular in the Python community, other programming languages also have their own testing frameworks. For example: 76 | 77 | - NUnit/xUnit for .NET 78 | - JUnit for Java 79 | - Mocha for JavaScript 80 | - *many more...* 81 | 82 | Each of these frameworks has its unique features and conventions, but the underlying goal remains the same: to automate testing and catch issues early in the development process. 83 | 84 |
85 | 86 | ## Benefits 87 | Automating tests offers several advantages: 88 | 89 | **Efficiency**:
90 | Automated tests can be run quickly and repeatedly, saving time compared to manual testing. 91 | 92 | **Consistency**:
93 | Automated tests follow predefined steps consistently, reducing human error. 94 | 95 | **Regression Detection**:
96 | Automated tests catch regressions (unexpected issues introduced by code changes) early, preventing them from reaching production. 97 | 98 | **Continuous Integration (CI)**:
99 | Automated tests integrate seamlessly with CI/CD pipelines, ensuring that code changes don’t break existing functionality. 100 | 101 | **Documentation**:
102 | Test cases serve as living documentation, explaining how different parts of your application should behave. 103 | 104 | > In summary, automating tests improves code quality, accelerates development, and provides confidence in your software. 105 | 106 |
107 | 108 | > :memo: **Good to know**, in the next workshop will dive deeper into the subject of test automation via GitHub Actions. -------------------------------------------------------------------------------- /Workshop - Software Testing/05_tracking.md: -------------------------------------------------------------------------------- 1 | # Tracking with GitHub 2 | 3 | When it comes to bug tracking, GitHub provides an easy-to-implement yet powerful way to manage issues related to a code project. 4 | 5 |
6 | 7 | ## GitHub Issue Tracker 8 | GitHub has a built-in issue tracking system that allows you to log and manage issues directly within your repository. [More info about issue tracking](https://docs.github.com/en/issues/tracking-your-work-with-issues/planning-and-tracking-work-for-your-team-or-project) 9 | 10 | 1. **Creating Issues**: You can create new issues by navigating to the `Issues` tab in your repository. Click on the `New Issue` button, and provide details about the issue, including a title, description, and labels (such as “bug,” “enhancement,” etc.). 11 | 2. **Issue Details**: Each issue has a dedicated page where you can discuss the problem, provide additional context, and collaborate with other team members. You can also assign the issue to specific individuals. 12 | 3. **Labels and Milestones**: GitHub allows you to categorize issues using labels. For example, you can label an issue as “bug,” “feature request,” or “documentation.” Additionally, you can set milestones to track progress toward specific goals. 13 | 4. **Comments and Discussions**: Team members can comment on issues, discuss potential solutions, and provide updates. GitHub’s notification system ensures that relevant parties stay informed. 14 | 5. **Closing Issues**: Once an issue is resolved, you can close it. GitHub provides options to reference related pull requests, link to commits, and mark the issue as resolved. 15 | 16 |
17 | 18 | ## Branching 19 | 20 | Branches allow you to develop features, fix bugs, or safely experiment with new ideas in a contained area of your repository. When you create a branch, you’re essentially creating a separate copy of your codebase where you can work independently without affecting the main codebase. Each branch represents a specific task or feature. 21 | [More info about creating a branch in GitHub](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-a-branch-for-an-issue) 22 | 23 | ### Why branch? 24 | 1. **Isolation**: By creating a branch, you isolate your changes from the main codebase. This prevents accidental interference with other ongoing work. 25 | 2. **Collaboration**: Branches facilitate collaboration. Multiple team members can work on different branches simultaneously, and then merge their changes back into the main branch. 26 | 3. **Feature Development**: You can create feature branches to work on specific features or enhancements. Once the feature is complete, you merge it back into the main branch. 27 | 4. **Bug Fixes**: Branches are useful for fixing bugs. You create a branch, make the necessary fixes, and then merge it back. 28 | 5. **Experimentation**: If you want to try out a new idea without affecting the main code, create an experimental branch. 29 | 30 | ### Best practices 31 | Here are some best practies you could follow when creating branches.
32 | 33 | **Create from the Default Branch**
34 | Typically, you create a new branch from the default branch (often named “main” or “master”). This ensures your branch starts with the latest code. 35 | 36 | **Descriptive Names**
37 | Give your branches descriptive names (e.g., “feature/user-authentication” or “bugfix/404-page”). Clear names make it easier to understand the purpose of each branch. 38 | 39 | **Regularly Merge**
40 | Regularly merge changes from the default branch into your feature branch to keep it up-to-date. 41 | 42 | **Pull Requests**
43 | Use pull requests to propose merging your branch into the default branch. This allows for code review and discussion before merging. 44 | 45 | **Delete Stale Branches**
46 | After merging, delete branches that are no longer needed to keep your repository tidy 47 | 48 | > :bulb: **Remember** that every project is different, but it is always necessary to make good agreements about how you formulate things like Issues and Branches and how to deal with Bugs or new Features. [More info about flows](https://docs.github.com/en/get-started/using-github/github-flow) 49 | 50 |
51 | 52 | ## Classification 53 | 54 | Now, let’s discuss the defect life cycle and severity/priority classification: 55 | 56 | ### Defect Life Cycle: 57 | The defect life cycle encompasses various stages, including identification, logging, assignment, fixing, retesting, and closure. Each stage plays a crucial role in managing defects effectively. 58 | 59 | - **Identification**: Detecting defects during testing. 60 | - **Logging**: Creating detailed bug reports. 61 | - **Assignment**: Assigning the issue to the relevant team member. 62 | - **Fixing**: Developers address the issue. 63 | - **Retesting**: Verifying that the fix works. 64 | - **Closure**: Marking the defect as resolved. 65 | 66 | ### Severity and Priority Classification: 67 | #### Severity 68 | Refers to the impact of a defect on the system. It can be categorized as critical, major, minor, or trivial. 69 | - **Critical**: The defect causes system failure or data loss. 70 | - **Major**: Significant functionality is affected. 71 | - **Minor**: Minor functionality issues. 72 | - **Trivial**: Cosmetic issues with minimal impact. 73 | 74 | #### Priority 75 | Indicates the order in which defects should be addressed. Prioritization depends on business needs, user impact, and project timelines. 76 | - **High Priority**: Requires immediate attention. 77 | - **Medium Priority**: Important but not urgent. 78 | - **Low Priority**: Can be addressed later. -------------------------------------------------------------------------------- /Workshop - Software Testing/06_resources.md: -------------------------------------------------------------------------------- 1 | 2 | ### References and Further reading 3 | 4 | We throughly recommend these resources to continue your Testing practice: 5 | 6 | - Creating a branch for an issue 7 | - Planning and tracking work for your team or project 8 | - Follow GitHub flow to collaborate on projects 9 | - unittest - Unit testing framework 10 | - Unittesting via pytest in Python 11 | - Code Coverage via Coverage.py 12 | - Equivalence Partitioning 13 | - Boundary Value Analysis -------------------------------------------------------------------------------- /Workshop - UML/01_introduction.md: -------------------------------------------------------------------------------- 1 | # A need for diagrams 2 | In this workshop we give a brief overview of the Unified Modeling Language (UML), why it is useful and with a focus on its applications. But let's start with a story. 3 | 4 | ## The Voyager probe 5 | In the 1970s, NASA embarked on an ambitious mission to explore the outer planets of our solar system with the Voyager program. The twin spacecraft, Voyager 1 and Voyager 2, were designed to send back invaluable data about Jupiter, Saturn, Uranus, Neptune, and beyond. One of the critical aspects of the mission was ensuring reliable communication between the spacecraft and Earth across billions of miles. The engineers faced the challenge of designing a robust communication system that could handle the vast distances and extreme conditions of space. 6 | 7 | Meanwhile the probes have left our solar system. Due to this distance the communication bandwidth with the probes has dropped to only **120 bits per second** and it takes **22 hours** to reach the them. 8 | 9 | ![NASA’s Voyager 1 soars through interstellar space 40 years after it was launched](https://cdn.mos.cms.futurecdn.net/iNJkfLq8evP5EcbGxvsqhi-1920-80.jpg) 10 | 11 | The Voyager probes send out regular 'pings' but one day the NASA engineers started to receive scrambled rubbish... After restarting the Computer Command System (CSS) it became clear that one of the memory banks was damaged by the high energy particles. Now image that you are tasked to reprogram the CSS. 12 | 13 | ### Activity 14 | What would be the first this you would do? 15 | 16 | #### Answer 17 | You would look for documentation describing the system. 18 | 19 | So you reach for the documentation and find the following diagram: 20 | 21 | ![Block diagram for Voyager CCS](https://www.allaboutcircuits.com/uploads/articles/ccs_viking_voyager_blockdiagram_nasa.jpg) 22 | 23 | Would this diagram be enough to apply your changes? 24 | 25 | #### Learning 1 26 | > Without knowing anything about the diagramming language used in the Block diagram, we were able to judge that it is not helpful for our purpose. So good diagram models are intuitive. 27 | 28 | ### Discussion time 29 | What documentation would we need? 30 | 31 | #### Possible answer 32 | Since we need to communicate with the Voyager probe, we need a communication protocol. 33 | 34 | It should describe: 35 | 36 | - What messages we can send 37 | - What the system does with our messages 38 | - Which response we get back 39 | 40 | #### Example 41 | When we lookup this protocol, we find the following description. 42 | 43 | **Communication Protocol** 44 | 45 | The communication takes place between two participants: 46 | 47 | 1. **Center Center** (referred to as "Center"): The communication control center. 48 | 2. **Voyager Probe** (referred to as "Voyager"): The Voyager space probe. 49 | 50 | The communication between **Center** and **Voyager** takes the following sequence: 51 | 52 | 1. The **Center** initiates a connection to the **Voyager** by sending a "Connect" message. 53 | 2. The **Voyager** receives the connection request and acknowledges it by sending an "Acknowledge Connection" message back to the **Center**. 54 | 3. The **Center** sends data to the **Voyager** with a "Send Data" message. 55 | 4. The **Voyager** processes the received data internally (represented by "Process Data"). 56 | 5. The **Voyager** acknowledges that the data has been received by sending an "Acknowledge Data Received" message to the **Center**. 57 | 6. The **Center** sends a "Disconnect" message to the **Voyager** to terminate the communication session. 58 | 7. The **Voyager** acknowledges the disconnection by sending an "Acknowledge Disconnection" message back to the **Center**. 59 | 60 | #### Activity 61 | What would this look like in a diagram? 62 | 63 | #### Compare results 64 | There are no wrong results here. Pick out some good ones and some unclear ones and discuss their clarity and expressiveness. The diagrams need to be useful. 65 | 66 | #### Possible solution 67 | The protocol could like something like: 68 | 69 | ![Protocol](./plant_uml/voyager_protocol/Voyager%20Communication%20Protocol.svg) 70 | 71 | This protocol is based on the TCP protocol, but would this be handy for the Voyager communication? Why? For those interested, see the [TCP protocol](https://developer.mozilla.org/en-US/docs/Glossary/TCP) for more context. 72 | 73 | #### Learning 2 74 | > Diagrams are much easier to interpret than text. Expressing our documentation in diagrams therefore results in less interpretation errors (bugs) and faster implementation (development speed). 75 | 76 | ### Discussion time 77 | We now know how both participants communicate, but we don't yet know what they are saying. Or, in other words: what messages they pass around. 78 | 79 | - Do they have a header? 80 | - Do they have a built-in integrity check? 81 | 82 | #### Example 83 | The message might be structured like: 84 | 85 | ![Message](./plant_uml/voyager_message/Voyager%20Message%20Description.svg) 86 | 87 | #### Activity 88 | What does this diagram say? 89 | 90 | #### Possible solution 91 | The `opcode` describes the instruction for the CSS to execute and the `checksum` is added to check that the message has not corrupted during its 22 hour flight. The diagram says that the message consists of a header and a body. 92 | 93 | But this raises the question what the possible `opcode`s are. Hopefully this is documented as well... We will come back to this at the end of this workshop when we introduce Swagger documentation. This is documentation specifically designed for describing APIs. 94 | 95 | ## Conclusion 96 | Diagrams make our developer life easier than textual descriptions. -------------------------------------------------------------------------------- /Workshop - UML/04_swagger.md: -------------------------------------------------------------------------------- 1 | # API documentation 2 | In the introduction we were discussing how to describe the communication between NASA's Mission Control and the Voyager probes. We made a start with a Sequence diagram and a Class diagram to describe their communication, but it was not ideal. If we were to use UML for the Mission Control - Voyager interface then it would result in a lot of diagrams without a clear overview. That's why tools like Swagger were invented. 3 | 4 | ## What is Swagger? 5 | Swagger is a way to document your REST API in a **standardized** way. The best way to explore what Swagger really is, is to view Swagger's Petstore example: 6 | 7 | [Swagger Petstore API](https://petstore.swagger.io) 8 | 9 | ## Things to explore 10 | 11 | ### The general description 12 | On top we find a title and a description. You have some freedom here and it is up to you to give a clear description of your API. 13 | 14 | ### Endpoints 15 | Swagger allows you to organize CRUD actions per endpoint. Here we see GET, POST, PUT and DELETE actions for the endpoints **pet**, **store** and **user**. 16 | 17 | ### Requests 18 | The request part describes the request and its response in details. Expanding the pet's PUT we find: 19 | 20 | - The body and that this field is required 21 | - The model that we must send and an example 22 | - When you run `execute` we see the response 23 | 24 | ### Models 25 | The model descriptions are extracted from the endpoint models. 26 | 27 | Anything that is relevant for developers is present in the documentation. Now it's time to build your own Swagger doc. 28 | 29 | ### Activity 30 | Suppose your company needs to build a basic calculator. It should handle: 31 | 32 | - Additions 33 | - Subtractions 34 | - Multiplications 35 | - Divisions 36 | 37 | One of the requirements is that the calculator must be available for mobile, desktop and web. Your company decides not to build the mobile, desktop and web client itself; they leave that to other vendors. But they do provide the calculator API. The code base is provided to you, see `app.py`. 38 | 39 | It's your task to let the other developers know how to use the API: 40 | 41 | - Describe the API with Swagger 42 | - You can use the json or yaml variant for this 43 | - Use the [Swagger specification](https://swagger.io/specification) in combination with [Swagger Petstore](https://petstore.swagger.io) example 44 | 45 | Present your documentation by loading your json/yaml file into [Swagger's online Editor](https://editor.swagger.io). 46 | 47 | Like the Petstore example, Swagger documentation can be made interactive but that is beyond the scope of this workshop. See the resources for a tutorial. -------------------------------------------------------------------------------- /Workshop - UML/05_resources.md: -------------------------------------------------------------------------------- 1 | 2 | ## Voyager Program 3 | - [Voyager program](https://en.wikipedia.org/wiki/Voyager_program) 4 | - [Tachtigers houden Voyager in de vaart](https://www.bnr.nl/podcast/de-technoloog/10549902/tachtigers-houden-voyager-in-de-vaart) 5 | - [The untold truth of the Voyager Program](https://www.grunge.com/949833/the-untold-truth-of-the-voyager-program/) 6 | - [The Brains of the Voyager Spacecraft](https://www.allaboutcircuits.com/news/voyager-mission-anniversary-computers-command-data-attitude-control/) 7 | 8 | ## UML 9 | - [UML Wikipedia](https://en.wikipedia.org/wiki/Unified_Modeling_Language) 10 | - [Geeks For Geeks](https://www.geeksforgeeks.org/structural-diagrams-unified-modeling-languageuml) 11 | - [UML spec](https://www.omg.org/spec/UML) 12 | 13 | ## Diagrams 14 | - [Use Case Diagram](https://www.geeksforgeeks.org/use-case-diagram) 15 | - [Activity Diagram](https://www.geeksforgeeks.org/unified-modeling-language-uml-activity-diagrams) 16 | - [Class Diagram](https://www.geeksforgeeks.org/unified-modeling-language-uml-class-diagrams) 17 | - [Sequence Diagram](https://www.geeksforgeeks.org/unified-modeling-language-uml-sequence-diagrams) 18 | - [State Diagram](https://www.geeksforgeeks.org/unified-modeling-language-uml-state-diagrams) 19 | - [Deployment Diagram](https://www.geeksforgeeks.org/deployment-diagram-unified-modeling-languageuml) 20 | - [Deployment Diagram](https://www.youtube.com/watch?v=IzEzX5HW_CU) 21 | 22 | ## PlantUML 23 | - [PlantUML Site](https://plantuml.com) 24 | - [PlantUML VSCode Plugin](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml) 25 | - [Configuring and Running PlantUML with VS Code](https://medium.com/@sadaf.cuagain/configuring-and-running-plantuml-with-vs-code-8f2f6e64bb8d) 26 | - [PlantUML Github Actions](https://github.com/marketplace/actions/generate-plantuml) 27 | 28 | ## UML Critique 29 | - [Are UML Diagrams Important for Developers?](https://www.youtube.com/watch?v=VZgsxw0Og6c) 30 | 31 | ## Swagger 32 | - [Swagger Site](https://swagger.io) 33 | - [Swagger Open Source Tools](https://swagger.io/tools/open-source) 34 | - [OpenAPI Specification](https://swagger.io/specification) 35 | - [Swagger Parser](https://apitools.dev/swagger-parser) 36 | - [Swagger Tutorial](https://www.youtube.com/watch?v=xQfMARPNycI) 37 | 38 | ## Other 39 | - [Mermaid tool](https://mermaid.js.org/) 40 | -------------------------------------------------------------------------------- /Workshop - UML/draw_io/voyager_1.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Workshop - UML/draw_io/voyager_2.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Workshop - UML/images/activity-ingredients.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - UML/images/activity-ingredients.jpeg -------------------------------------------------------------------------------- /Workshop - UML/images/class-ingredients.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - UML/images/class-ingredients.webp -------------------------------------------------------------------------------- /Workshop - UML/images/class-relationship.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - UML/images/class-relationship.webp -------------------------------------------------------------------------------- /Workshop - UML/images/go-share.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - UML/images/go-share.jpeg -------------------------------------------------------------------------------- /Workshop - UML/images/use-case-ingredients.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hogeschool/Software-Construction/2e068e69e050ab9f885e1dae623a937fd4b95293/Workshop - UML/images/use-case-ingredients.webp -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/activity_diagram.puml: -------------------------------------------------------------------------------- 1 | @startuml GO Sharing Scooter Renting 2 | 3 | |Renter| 4 | start 5 | :Locate Scooter; 6 | :Select Scooter; 7 | 8 | |System| 9 | :Check Money Deposit; 10 | if (Enough Money Deposited?) then (yes) 11 | |Renter| 12 | :Initiate Rent; 13 | :Start Riding Scooter; 14 | stop 15 | else (no) 16 | :Reject Rental; 17 | :Notify Renter to Deposit Money; 18 | |Renter| 19 | stop 20 | endif 21 | 22 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/class_diagram.puml: -------------------------------------------------------------------------------- 1 | @startuml GO Sharing Class Diagram 2 | 3 | class Account { 4 | +username: String 5 | +password: String 6 | +fetchAccount(): void 7 | +createAccount(): void 8 | } 9 | 10 | class Renter { 11 | +depositAmount: Float 12 | +depositMoney(amount: Float): void 13 | +locateScooter(): Scooter 14 | +rentScooter(scooter: Scooter): void 15 | +pauseRenting(reservation: Reservation): void 16 | +resumeRenting(reservation: Reservation): void 17 | +cancelRenting(reservation: Reservation): void 18 | +endRenting(reservation: Reservation): void 19 | } 20 | 21 | class Admin { 22 | +generateUsageReport(): UsageReport 23 | +listBrokenScooters(): List 24 | +getMileagePerScooter(): List 25 | } 26 | 27 | class Finance { 28 | +generateGrossTurnoverReport(): FinancialReport 29 | } 30 | 31 | class Scooter { 32 | +id: String 33 | +location: String 34 | +status: String 35 | +mileage: Float 36 | } 37 | 38 | class Reservation { 39 | +reservationId: String 40 | +renter: Renter 41 | +scooter: Scooter 42 | +startTime: DateTime 43 | +endTime: DateTime 44 | +status: String 45 | } 46 | 47 | class UsageReport { 48 | +dateRange: String 49 | +totalRentals: Float 50 | } 51 | 52 | class MileageReport { 53 | +dateRange: String 54 | +totalMileage: Float 55 | } 56 | 57 | class FinancialReport { 58 | +dateRange: String 59 | +grossTurnover: Float 60 | } 61 | 62 | Account <|-- Renter 63 | Account <|-- Admin 64 | Account <|-- Finance 65 | 66 | Renter "1" -- "0..*" Reservation : makes > 67 | Reservation "1" -- "1" Scooter : includes > 68 | Reservation "1" -- "1" Renter : involves > 69 | Admin "1" -- "0..*" Scooter : manages > 70 | Admin "1" -- "0..*" UsageReport : generates > 71 | Admin "1" -- "0..*" MileageReport : generates > 72 | Finance "1" -- "0..*" FinancialReport : generates > 73 | 74 | Reservation "1" -- "0..*" UsageReport : associated with > 75 | Reservation "1" -- "0..*" MileageReport : associated with > 76 | Reservation "1" -- "0..*" FinancialReport : associated with > 77 | 78 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/deployment_diagram.puml: -------------------------------------------------------------------------------- 1 | @startuml GO Sharing Deployment Architecture 2 | 3 | node "Client Device" { 4 | [Mobile App] 5 | } 6 | 7 | node "Cloud Infrastructure" { 8 | node "Web Server" { 9 | [Scooter Rental System] 10 | } 11 | node "Database Server" { 12 | [Database schema] 13 | } 14 | } 15 | 16 | node "Payment Gateway" { 17 | [Payment Processing Service] 18 | } 19 | 20 | node "Scooter" { 21 | [GPS Module] 22 | [Lock/Unlock Mechanism] 23 | [Battery Controller] 24 | } 25 | 26 | [Mobile App] -(0- [Scooter Rental System] : API Requests 27 | [Scooter Rental System] -(0- [Database schema] : Read/Write 28 | [Scooter Rental System] -left(0- [Payment Processing Service] : Payment Requests 29 | [Scooter Rental System] -(0- [Lock/Unlock Mechanism] : Access Control 30 | [Scooter Rental System] -(0- [GPS Module] : Location Tracking 31 | [Scooter Rental System] -(0- [Battery Controller] : Location Tracking 32 | 33 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/sequence_diagram.puml: -------------------------------------------------------------------------------- 1 | @startuml GO Sharing Money Deposit 2 | 3 | actor Renter 4 | participant "Scooter Rental System" as System 5 | participant "Payment Gateway" as Payment 6 | participant "iDEAL Bank" as Bank 7 | 8 | Renter -> System: Initiate Deposit(amount) 9 | activate System 10 | System -> Payment: Redirect to iDEAL 11 | activate Payment 12 | Payment -> Bank: Request Payment Authorization(amount) 13 | activate Bank 14 | Bank -> Renter: Display Payment Page 15 | Renter -> Bank: Authorize Payment 16 | Bank -> Payment: Payment Authorized 17 | deactivate Bank 18 | Payment -> System: Payment Confirmed 19 | deactivate Payment 20 | System -> System: Update Account Balance(amount) 21 | System -> Renter: Confirm Deposit 22 | deactivate System 23 | 24 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/state_diagram.puml: -------------------------------------------------------------------------------- 1 | @startuml GO Sharing Scooter Rental 2 | 3 | [*] --> Idle 4 | 5 | Idle -down-> Active: Rent Scooter 6 | Active -right-> Paused: Pause Renting 7 | Paused -up-> Active: Resume Renting 8 | Active -up-> Idle: Stop Rental 9 | Paused -left-> Idle: Cancel Rental 10 | 11 | Idle --> [*] 12 | 13 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/state_diagram/GO Sharing Scooter Rental.svg: -------------------------------------------------------------------------------- 1 | IdleActivePausedRent ScooterStop RentalPause RentingResume RentingCancel Rental -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/use_case_diagram.puml: -------------------------------------------------------------------------------- 1 | @startuml GO Sharing Use Case Diagram 2 | 3 | left to right direction 4 | 5 | actor Renter 6 | actor Admin 7 | actor Finance 8 | 9 | rectangle "Scooter Rental System" { 10 | 11 | usecase "Create Account" as UC_CreateAccount 12 | usecase "Sign In User" as UC_SignIn 13 | usecase "Deposit Money" as UC_DepositMoney 14 | 15 | usecase "Locate Scooter" as UC_LocateScooter 16 | usecase "Rent Scooter" as UC_RentScooter 17 | usecase "Pause Renting" as UC_PauseRenting 18 | usecase "End Renting" as UC_EndRenting 19 | 20 | usecase "Display Usage" as UC_DisplayUsage 21 | usecase "List Broken Scooters" as UC_ListBrokenScooters 22 | usecase "Display Mileage Per Scooter" as UC_DisplayMileagePerScooter 23 | 24 | usecase "Display Gross Turnover" as UC_DisplayGrossTurnover 25 | 26 | Renter --> UC_CreateAccount 27 | Renter --> UC_SignIn 28 | Renter --> UC_DepositMoney 29 | Renter --> UC_LocateScooter 30 | Renter --> UC_RentScooter 31 | Renter --> UC_PauseRenting 32 | Renter --> UC_EndRenting 33 | 34 | Admin --> UC_SignIn 35 | Admin --> UC_DisplayUsage 36 | Admin --> UC_ListBrokenScooters 37 | Admin --> UC_DisplayMileagePerScooter 38 | 39 | UC_SignIn -- Finance 40 | UC_DisplayGrossTurnover -- Finance 41 | } 42 | 43 | @enduml 44 | -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/voyager_chatgpt.puml: -------------------------------------------------------------------------------- 1 | @startuml Voyager Probe ChatGPT 2 | 3 | actor "NASA Mission Control" as NASA 4 | actor "Deep Space Network (DSN)" as DSN 5 | participant "Voyager Probe" as Voyager 6 | 7 | NASA -> DSN: Send command 8 | DSN -> Voyager: Relay command 9 | Voyager -> DSN: Acknowledge command 10 | 11 | DSN -> Voyager: Request telemetry data 12 | Voyager -> DSN: Send telemetry data 13 | DSN -> NASA: Forward telemetry data 14 | 15 | NASA -> DSN: Request scientific data 16 | DSN -> Voyager: Relay request 17 | Voyager -> DSN: Send scientific data 18 | DSN -> NASA: Forward scientific data 19 | 20 | NASA -> DSN: Send new instructions 21 | DSN -> Voyager: Relay new instructions 22 | Voyager -> DSN: Acknowledge receipt of instructions 23 | DSN -> NASA: Confirm instructions delivered 24 | 25 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/voyager_message.puml: -------------------------------------------------------------------------------- 1 | @startuml Voyager Message Description 2 | 3 | object Header { 4 | + opcode : uint8 5 | + timestamp : int32 6 | + payloadSize : uint32 7 | } 8 | 9 | object Payload { 10 | + body : uint8[] 11 | + MD5checksum : int32 12 | } 13 | 14 | Header <-- Payload : includes 15 | 16 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/voyager_message/Voyager Message Description.svg: -------------------------------------------------------------------------------- 1 | Headeropcode : uint8timestamp : int32payloadSize : uint32Payloadbody : uint8[]MD5checksum : int32includes -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/voyager_protocol.puml: -------------------------------------------------------------------------------- 1 | @startuml Voyager Communication Protocol 2 | 3 | participant "Center Center" as Center 4 | participant "Voyager Probe" as Voyager 5 | 6 | Center ->> Voyager: Connect 7 | activate Voyager 8 | Voyager --> Center: Acknowledge Connection 9 | deactivate Voyager 10 | Center ->> Voyager: Send Data 11 | activate Voyager 12 | Voyager ->> Voyager: Process Data 13 | Voyager --> Center: Acknowledge Data Received 14 | deactivate Voyager 15 | Center ->> Voyager: Disconnect 16 | activate Voyager 17 | Voyager --> Center: Acknowledge Disconnection 18 | deactivate Voyager 19 | 20 | @enduml -------------------------------------------------------------------------------- /Workshop - UML/plant_uml/voyager_protocol/Voyager Communication Protocol.svg: -------------------------------------------------------------------------------- 1 | Center CenterCenter CenterVoyager ProbeVoyager ProbeConnectAcknowledge ConnectionSend DataProcess DataAcknowledge Data ReceivedDisconnectAcknowledge Disconnection -------------------------------------------------------------------------------- /Workshop - UML/swagger/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask,request 2 | from flask_cors import CORS 3 | import json 4 | 5 | #------------------------------------------------------ 6 | 7 | app = Flask(__name__) 8 | 9 | #------------------------------------------------------ 10 | 11 | CORS(app) 12 | 13 | #------------------------------------------------------ 14 | 15 | @app.route("/add", methods=['POST']) 16 | def add(): 17 | 18 | data = json.loads(request.data) 19 | 20 | return str(data["a"] + data["b"]) 21 | 22 | #------------------------------------------------------ 23 | 24 | @app.route("/sub", methods=['POST']) 25 | def sub(): 26 | 27 | data = json.loads(request.data) 28 | 29 | return str(data["a"] - data["b"]) 30 | 31 | #------------------------------------------------------ 32 | 33 | @app.route("/mul", methods=['POST']) 34 | def mul(): 35 | 36 | data = json.loads(request.data) 37 | 38 | return str(data["a"] * data["b"]) 39 | 40 | #------------------------------------------------------ 41 | 42 | @app.route("/div", methods=['POST']) 43 | def div(): 44 | 45 | data = json.loads(request.data) 46 | 47 | return str(data["a"] / data["b"]) 48 | 49 | #------------------------------------------------------ 50 | 51 | @app.route("/docs", methods=['GET']) 52 | def read_file(): 53 | 54 | with open("Workshops/Workshop - UML/swagger/swagger.yaml", "r") as f: 55 | 56 | response = f.read() 57 | 58 | return response 59 | 60 | #------------------------------------------------------ 61 | 62 | if __name__ == '__main__': 63 | 64 | app.run() 65 | 66 | #------------------------------------------------------ -------------------------------------------------------------------------------- /Workshop - UML/swagger/swagger.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.0 2 | info: 3 | title: Calculator API 4 | version: 1.0.0 5 | servers: 6 | - url: http://127.0.0.1:5000 7 | description: dev server 8 | tags: 9 | - name: General 10 | description: Basic calculator methods 11 | paths: 12 | /add: 13 | post: 14 | tags: 15 | - General 16 | summary: addition 17 | description: Will add two values 18 | requestBody: 19 | content: 20 | application/json: 21 | schema: 22 | type: object 23 | required: 24 | - a 25 | - b 26 | properties: 27 | a: 28 | type: number 29 | b: 30 | type: number 31 | example: 32 | a: 1 33 | b: 2 34 | responses: 35 | '200': 36 | description: Successful response 37 | content: 38 | application/json: 39 | schema: 40 | type: object 41 | properties: 42 | result: 43 | type: number 44 | example: 45 | result: 3 46 | /sub: 47 | post: 48 | tags: 49 | - General 50 | summary: subtraction 51 | description: Will subtract two values 52 | requestBody: 53 | content: 54 | application/json: 55 | schema: 56 | type: object 57 | required: 58 | - a 59 | - b 60 | properties: 61 | a: 62 | type: number 63 | b: 64 | type: number 65 | example: 66 | a: 1 67 | b: 2 68 | responses: 69 | '200': 70 | description: Successful response 71 | content: 72 | application/json: 73 | schema: 74 | type: object 75 | properties: 76 | result: 77 | type: number 78 | example: 79 | result: -1 80 | /mul: 81 | post: 82 | tags: 83 | - General 84 | summary: multiplication 85 | description: Will multiply two values 86 | requestBody: 87 | content: 88 | application/json: 89 | schema: 90 | type: object 91 | required: 92 | - a 93 | - b 94 | properties: 95 | a: 96 | type: number 97 | b: 98 | type: number 99 | example: 100 | a: 3 101 | b: 2 102 | responses: 103 | '200': 104 | description: Successful response 105 | content: 106 | application/json: 107 | schema: 108 | type: object 109 | properties: 110 | result: 111 | type: number 112 | example: 113 | result: 6 114 | /div: 115 | post: 116 | tags: 117 | - General 118 | summary: division 119 | description: Will divide two values 120 | requestBody: 121 | content: 122 | application/json: 123 | schema: 124 | type: object 125 | required: 126 | - a 127 | - b 128 | properties: 129 | a: 130 | type: number 131 | b: 132 | type: number 133 | example: 134 | a: 6 135 | b: 3 136 | responses: 137 | '200': 138 | description: Successful response 139 | content: 140 | application/json: 141 | schema: 142 | type: object 143 | properties: 144 | result: 145 | type: number 146 | example: 147 | result: 2 -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Software Construction: Process and Tools 2 | Welcome to the course Software Construction: Process and Tools of the Computer Science program at Rotterdam University of Applied Sciences. 3 | 4 |
5 | 6 | ## General 7 | You will work as a developer in a small team (max 4 students), where you will work together on existing (legacy) software in Python based on the available case. 8 | During this course, you will have to analyze, map, test and then refactor the software. At the same time, you will set up a CI/CD pipeline to continue testing, logging and monitoring during the development process. 9 | If everything goes well, you will expand the application with extra functionality. 10 | 11 |
12 | 13 | ## Workshops 14 | 15 | ### Workshop 1 - REST + Requirements Specifications 16 | In this workshop we will look at how to draw up requirements. 17 | What are good requirements and what should they meet, among other things. 18 | What is REST and how do APIs work, a short introduction and how to draw up requirements for it. 19 | Using examples, you will look at how you could analyze requirements from existing software, among other things. 20 | 21 | ### Workshop 2 – Git 22 | In this workshop we will look at the use of Git and GitHub. What terms are used and 23 | what are they for, what is the normal way of working with Git and what is the difference with GitHub. 24 | Throughout the course Git is the lifeblood of CI/CD and now we look at what, why and 25 | how you use it. 26 | 27 | ### Workshop 3 - Software Testing 28 | In this workshop we will look at testing software. 29 | What do you test when, what methods are there to test and what do you need to take into account. 30 | What tools can you use and how will this help within our CI/CD pipeline. 31 | 32 | ### Workshop 4 – Refactoring 33 | In this workshop we will look at refactoring, what is it, what do you use it for and how do you apply it? 34 | How does refactoring contribute to making your software more maintainable and how can we apply this to an existing project? 35 | 36 | ### Workshop 5 - CI/CD 37 | In this workshop we will look at Continuous Integration (CI) and Continuous Development (CD), 38 | what is it, what do we use it for and what is the difference between Continuous Development and Continuous Delivery. 39 | We will look at tools, settings and start with the setup. 40 | 41 | ### Workshop 6 - Operating Systems + Bash 42 | In this workshop we will look at the use of Bash and its power within CI/CD. 43 | How different Operating Systems differ from each other. 44 | How to navigate between folders, how to create files, how to move and delete files and how to set permissions. 45 | 46 | ### Workshop 7 – UML 47 | In this workshop we will delve deeper into the use and power of UML as a language for visually representing software or changes in software. 48 | We will look at the following components: Context diagram, ERD, Deployment diagram, Flowchart, State diagram, Swagger/OpenAPI --------------------------------------------------------------------------------