From e8508e7eac60024f6418c829e28f2667a84bb7a8 Mon Sep 17 00:00:00 2001 From: GitHub Date: Fri, 19 Apr 2024 13:13:53 +0000 Subject: [PATCH] Deployed 5841ca6 with MkDocs version: 1.5.3 --- index.html | 2 +- search/search_index.json | 2 +- sitemap.xml.gz | Bin 326 -> 326 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 670f587..6e17106 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ - GitHub DevSecOps Fundamentals
Skip to content

GitHub DevSecOps Fundamentals | Workshop

This self-paced workshop will enable you acquire the capabilities to implement a DevSecOps mindset, leveraging the GitHub platform for a seamless developer experience.

GitHub Platform

GitHub Platform

Learning Objectives

  • Collaborate effectively for high-velocity productivity
  • Apply preventive security to every aspect of the development process
  • Implement a secure software supply chain
  • Automate product release and business processes in general
  • Remove complications due to tool-bloat


Complete the 👣 Prerequisites checklist!

📚 Resources

Get expert workshop facilitation...

This publicly available workshop is limited to enable you learn with accompanying research. It does not address concepts at an enterprise-scope.

Contact 📧 services@github.com to benefit more from a facilitation of DevSecOps improvements or rollout in your enterprise, by GitHub's expert services.

\ No newline at end of file + GitHub DevSecOps Fundamentals
Skip to content

GitHub DevSecOps Fundamentals | Workshop

This self-paced workshop will enable you acquire the capabilities to implement a DevSecOps mindset, leveraging the GitHub platform for a seamless developer experience.

GitHub Platform

GitHub Platform

Learning Objectives

  • Collaborate effectively for high-velocity productivity
  • Apply preventive security to every aspect of the development process
  • Implement a secure software supply chain
  • Automate product release and business processes in general
  • Remove complications due to tool-bloat


Complete the 👣 Prerequisites checklist!

📚 Resources

Get expert workshop facilitation...

This publicly available workshop is limited to enable you learn with accompanying research. It does not address concepts at an enterprise-scope.

Contact 📧 services@github.com to benefit more from a workshop facilitation by GitHub's expert services to support advancement of DevSecOps implementation in your organisation.

\ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json index 9b9375a..7a7f7c9 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"GitHub DevSecOps Fundamentals | Workshop","text":"

This self-paced workshop will enable you acquire the capabilities to implement a DevSecOps mindset, leveraging the GitHub platform for a seamless developer experience.

GitHub Platform"},{"location":"#learning-objectives","title":"Learning Objectives","text":"

Complete the Prerequisites checklist!

"},{"location":"#resources","title":"\ud83d\udcda Resources","text":"

Get expert workshop facilitation...

This publicly available workshop is limited to enable you learn with accompanying research. It does not address concepts at an enterprise-scope.

Contact \ud83d\udce7 services@github.com to benefit more from a facilitation of DevSecOps improvements or rollout in your enterprise, by GitHub's expert services.

"},{"location":"prerequisites/","title":"Prerequisites","text":"

Prepare before the workshop

To ensure a seamless workshop experience, complete the following checklist items in order.

"},{"location":"prerequisites/#set-up-a-github-account","title":"Set up a GitHub account","text":"

Login to your GitHub account.

You may create a new GitHub account, if you do not already have one. (1)

  1. Clicking the button below will open the page on a new tab, for you to create a new GitHub account. Keep your @handle handy after you have logged in.

Create a new GitHub account

"},{"location":"prerequisites/#clone-the-workshop-project-to-your-own-account","title":"Clone the workshop project to your own account","text":"
  1. Create workshop project
  2. In the new tab, most of the prompts will automatically fill in for you and the default settings should be fine. Otherwise...

    • For owner, choose your personal account or.
    • We recommend creating a public repository. (1)

      1. Public repositories benefit from

        • Free use of GitHub Actions minutes.
        • Free use of GitHub Advanced Security features.
    • Scroll down and click the Create repository button at the bottom of the form.

      Expand for sample view...

  3. After creation of your new repository has begun, wait about 20 seconds, then refresh the page.

"},{"location":"prerequisites/#enable-discussions","title":"Enable Discussions","text":"
  1. On GitHub.com, navigate to the main page of your new repository.
  2. Under your repository name, click Settings.
  3. Scroll down to the \"Features\" section and click Set up discussions"},{"location":"prerequisites/#configure-base-security","title":"Configure base security","text":"
    1. Navigate to the Settings tab on your new workshop repository.
    2. Under the \"Security\" section of the menu, select Code security and analysis. Then configure the settings to match as follows (by clicking Enable where the option is/becomes available).

      Further configurations guide...

      • Dependabot version updates

        When enabling, you will be prompted to edit the .github/dependabot.yml configuration file. Simply navigate back on your browser or click on Cancel changes to leave the prompt, and to continue the base security configuration.

      • CodeQL analysis

        1. From the Set up, select the Default option.
        2. Leave the default settings in the prompt that follows, and simply click on Enable CodeQL to continue.
      • Protection rules

        Select the configuration as shown below.

    "},{"location":"prerequisites/#register-a-github-app","title":"Register a GitHub App","text":"
    1. In the upper-right corner of any page on GitHub, click your profile photo.
    2. Navigate to your account Settings.
    3. In the left sidebar, click Developer settings.
    4. In the left sidebar, click GitHub Apps
    5. Click New GitHub App

      Provide the form fields value as follows

      GitHub App Name..........: <YOUR-HANDLE>-bot\n\nHomepage URL.............: https://github.com/<YOUR-HANDLE>/github-devsecops-fundamentals\n\nWebhook\n  Active.................: DESELECT\n\nRepository permissions\n  Actions................: Read and write\n  Administration.........: Read and write\n  Contents...............: Read and write\n  Deployments............: Read and write\n  Discussions............: Read and write\n  Environments...........: Read and write\n  Pages..................: Read and write\n\nWhere can this GitHub App be installed?\n  Any account.................: SELECT\n
    6. Generate a private key for the new GitHub App as documented in here.

    7. Save the GitHub App private key to your new repository's secrets under the name of APP_PRIVATE_KEY_ACTIONS_ASSISTANT.

      \ud83d\udc40 Creating secrets for a repository.

    8. Save the GitHub App's appid to your new repository's variables under the name of APP_ID_ACTIONS_ASSISTANT.

      \ud83d\udc40 Creating configuration variables for a repository

    9. Goto https://github.com/apps/<YOUR-HANDLE>-bot. Install the app in the repository you created earlier.

      Expand for additional guide and sample views...

    What is the use of a GitHub App?

    When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.

    If you do want to trigger a workflow from within a workflow run, you can use a GitHub App installation access token or a personal access token instead of GITHUB_TOKEN to trigger events that require a token.

    If you use a GitHub App, you'll need to create a GitHub App and store the app ID and private key as secrets.

    ~ Triggering a workflow from a workflow

    During the course of the workshop exercises, you will discover how the GitHub App is used to trigger the automatic deployment of release artifacts.

    "},{"location":"prerequisites/#create-a-project-board-for-the-repository","title":"Create a project board for the repository","text":"
    1. Open the recently created workshop repository.

    2. Navigate to the Projects tab.

    3. Open the Link a project dropdown menu . Then select the New Project option.

    4. Click on the New project button to start the project creation wizard.

    5. Select the Team backlog template.
    6. Give a name to the project
    7. Finally click on the Create button.

    "},{"location":"prerequisites/#provision-a-new-cloud-development-environment-for-the-workshop","title":"Provision a new cloud development environment for the workshop","text":"

    GitHub Codespaces enables you to instantly start coding on the workshop project. Personal accounts on GitHub can benefit from a free quota of GitHub Codespaces usage.

    1. Navigate to the Code tab.

    2. Open the Code menu and click on Create codespaces on main.

      Expand for sample view...

    3. Leave the Codespace development environment to initialize and run, we will come back to use it later.

      "},{"location":"exercises/","title":"Introduction","text":"

      Workshop Exercises

      The workshop exercises provide guidance for implementing DevSecOps at the fundamental level with the GitHub platform. On completion, you would have gained the exposure to enable you seamlessly implement DevSecOps capabilities such as

      • Continuous collaboration
      • Continuous planning
      • Continuous integration
      • Continuous delivery
      • Continuous quality
      • Continuous security

      This workshop site also serves as the product we shall target for development. And During the course of the exercises, you will discover how you can rapidly build and test the site locally, and implement standardized tests to enable automated quality checks on the site.

      "},{"location":"exercises/#workshop-scenario","title":"Workshop Scenario","text":"

      You are working in a team that owns this site, and a new business goal has come into the vision of your organisation. In order to grow engagement with the site...

      ...the goal is to create a Tetris Game to delight our site visitors.

      Outcome: Tetris Game

      "},{"location":"exercises/#milestones","title":"Milestones","text":"

      The workshop objectives will be delivered by completion of the following milestones

      • Collaborate

        Facilitate onboarding into the site project and enable project development at high velocity for stakeholders of different experience with the project.

      • Secure the software supply chain

        Seamlessly implement application security and secure the software supply chain.

      • Automate Deployment of Releases

        Reliably deliver value to the end-user at high velocity.

      "},{"location":"exercises/01.collaborate/","title":"Collaborate","text":"

      Continuous Collaboration

      Continuous collaboration enables working together across technical and cultural boundaries as a unified team, reducing frictions and increasing the velocity to accomplish common goals.

      "},{"location":"exercises/01.collaborate/#objectives","title":"Objectives","text":"

      Behaviors that enable addressing the challenge include

      • Facilitate tracking of business goal delivery
      • Enable rapid onboarding to project development
      • Provide a standardized validation of work done
      • Enable collaborative validation of done requirement
      "},{"location":"exercises/01.collaborate/01/","title":"Project Management","text":"

      Facilitate collaborative tracking of business goal delivery

      As part of the prerequisite steps, you had created a project management board. You will now build on that step and keep stakeholders in the loop through the full course of the development process.

      "},{"location":"exercises/01.collaborate/01/#exercise-create-an-issue-to-capture-the-goal","title":"Exercise: Create an issue to capture the goal","text":"

      What is GitHub Issues?

      Use GitHub Issues to track ideas, feedback, tasks, or bugs for 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.

      "},{"location":"exercises/01.collaborate/01/#refer-back-to-the-project-created-in-the-prerequisite-to-the-workshop","title":"Refer back to the project created in the prerequisite to the workshop","text":""},{"location":"exercises/01.collaborate/01/#create-an-issue-to-capture-the-goal","title":"Create an issue to capture the goal","text":"
      1. Identify the Backlog column
      2. Click on + Add item at the bottom of the column
      3. Click on the + button
      4. Select Create new issue from the menu
      5. Choose the repository you created earlier
      6. Choose Feature request (1)

        1. The issue creation was facilitated with an \ud83d\udc40 issue template.

          .github/ISSUE_TEMPLATE/feature_request.md
          ---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n
      7. Fill the form. Feel free to be creative \ud83d\ude42 with your inputs.

        For the title...

        You may for instance enter \"Create a Tetris game to delight our site visitors\".

        After filling the form in, click Create to create the issue. (1)

        1. Things you can do in an issue include but are not limited to
          • Assign the issue to yourself or other stakeholders.
          • Mention other stakeholders (people and teams) to notify them for awareness.
      "},{"location":"exercises/01.collaborate/01/#take-note-of-the-issue-number","title":"Take note of the issue number","text":"

      We will use the issue number to link the the issue to subsequent work later. If you are too curious and cannot wait, see \ud83d\udc40 Linking a pull request to an issue.

      Moreover, having created the issue, we can update the issue with comments to keep collaborating stakeholders in the loop.

      "},{"location":"exercises/01.collaborate/01/#resources","title":"\ud83d\udcda Resources","text":"
      • Project planning for developers
      • Planning and tracking work for your team or project
      • Linking a pull request to an issue
      • Create diagrams to convey information through charts and graphs
      "},{"location":"exercises/01.collaborate/02/","title":"Implement Features","text":"

      Enable rapid onboarding to project development

      Our goal is to create a Tetris Game to delight our site visitors, without losing time to complex project onboarding process nor complications due to tool-bloat.

      Currently, navigating to the Tetris Game page of the workshop site shows that the feature is currently missing. We will address that issue in this exercise.

      "},{"location":"exercises/01.collaborate/02/#exercise-integrate-the-tetris-game","title":"Exercise: Integrate the Tetris Game","text":"

      Refer back to the Codespaces development environment created in the prerequisite to the workshop.(1)

      1. Your Codespace may have stopped due to inactivity. Do not worry, it is quite easy to get back on track...

        • If the browser tab with your Codespace remains open and you can find it, click Restart codespace to resume.
        • Otherwise, you can find it at the new repository you had created.
      "},{"location":"exercises/01.collaborate/02/#explore-your-codespace","title":"Explore your Codespace","text":""},{"location":"exercises/01.collaborate/02/#understand-your-codespace","title":"Understand Your Codespace","text":"

      .devcontainer/devcontainer.json describes the provisioning of your codespace. Some of the configuration entries are explained below, with annotations next to the respective entry. You can learn more about the Development Container Specification at your convenience.

      .devcontainer/devcontainer.json
      {\n  \"hostRequirements\": {//(1)!\n    \"cpus\": 4,\n    \"memory\": \"16gb\",\n    \"storage\": \"32gb\"\n  },\n  \"build\": {\n    \"dockerfile\": \"./Dockerfile\",//(2)!\n    \"context\": \"..\"\n  },\n  \"postAttachCommand\": \"python -m mkdocs serve --clean --dev-addr 127.0.0.1:8080\",//(3)!\n  \"forwardPorts\": [\n    8080\n  ],\n  \"containerEnv\": {\n    \"TETRIS_APP_HOST\": \"127.0.0.1\",\n    \"TETRIS_APP_PORT\": \"8080\",\n    \"TETRIS_APP_PATH\": \"github-devsecops-fundamentals\"\n  },\n  ...\n
      1. You can customize the compute resource to be made available for the Codespace environment, to suit your project.
      2. A Dockerfile can be used to customize the Codespace container image, for instance you may choose to consistently pre-install dependencies required for the development environment.
      3. Tasks may be configured to be executed at the start of each development session e.g. running a development server.

      On the TERMINAL view at the bottom, notice that a local site server is already running. This is as a result of the postAttachCommand configuration entry in .devcontainer/devcontainer.json.

      Looking at the build log in the terminal, you can see a warning like the one in the following example.(1)

      1. \ud83d\udca1 The warning gives a cue to addressing the Tetris Game integration issue. We shall implement the fix in later steps!

      The log INFO entry that reads INFO - [05:36:30] Watching paths for changes: 'docs', 'mkdocs.yml' informs you that thelocal site will rebuild whenever there is a change in the docs folder.

      "},{"location":"exercises/01.collaborate/02/#enable-quick-collaboration-feedback","title":"Enable Quick Collaboration Feedback","text":"

      Switch to the PORTS view on the bottom panel, notice there is a Site (8080) entry in the table.

      1. Focus your mouse pointer on the Site (8080) to reveal additional contexts.
      2. Click the Preview in Editor icon to browse the local build of the site inside of the editor's browser.(1)

          • Only you currently have access to the published site.
        1. You may instead click the icon associated with Site (8080) entry to view the site in your normal browser.

      Open access to other stakeholders for collaboration.

      1. Right click on the Site (8080) entry
      2. In the popup menu, set the mouse pointer on the Port Visibility item and select the Public option.

      Now, other stakeholders you share the site URL with can access the site. Consequently, they can also assess your ongoing work and can collaborate with timely feedbacks.

      "},{"location":"exercises/01.collaborate/02/#implement-automated-checks","title":"Implement Automated Checks","text":"

      GitHub as a platform, is event-driven. Beyond the ordinary, you can generally automate your actual business processes by modelling activities to produce changes on GitHub, thus triggering execution of certain automated tasks depending on the nature of a change. If you already familiar with the concept of GitOps, think of how the idea can be extended beyond the scopes of provisioning infrastructure and implementing continuos deployment.

      At this fundamentals phase of introduction to DevSecOps, we shall focus our leverage of GitHub's powerful event system to drive continuous integration checks and tests with GitHub Workflows.

      "},{"location":"exercises/01.collaborate/02/#learn-github-actions","title":"Learn GitHub Actions","text":"

      What is GitHub Actions?

      GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.

      GitHub Actions goes beyond just DevOps and lets you run workflows when other events happen in your repository. For example, you can run a workflow to automatically add the appropriate labels whenever someone creates a new issue in your repository.

      GitHub provides Linux, Windows, and macOS virtual machines to run your workflows, or you can host your own self-hosted runners in your own data center or cloud infrastructure.

      ~ Understanding GitHub Actions

      Anatomy of a GitHub Workflow
      name: Learn GitHub Actions #(1)!\n\nrun-name: ${{ github.actor }}  is learning GitHub Actions #(2)!\n\non: [push] #(3)!\n\npermissions: #(12)!\n    contents: read\n\nenv: #(13)!\n    LEARNER_NAME: Igwe\n\njobs: #(4)!\n\n    check-bats-version: #(5)!\n\n        runs-on: ubuntu-latest #(6)!\n\n        steps: #(7)!\n\n            - uses: actions/checkout@v4 #(8)!\n\n            - uses: actions/setup-node@v3 #(9)!\n              with:\n                  node-version: '14'\n\n            - run: npm install -g bats #(10)!\n\n            - run: bats -v #(11)!\n\n            - run: echo \"Hey ${LEARNER_NAME}, you're good... You've mastered GitHub Actions\\!\"\n
      1. Optional - The name of the workflow as it will appear in the \"Actions\" tab of the GitHub repository. If this field is omitted, the name of the workflow file will be used instead.
      2. Optional - The name for workflow runs generated from the workflow, which will appear in the list of workflow runs on your repository's \"Actions\" tab. This example uses an expression with the github context to display the username of the actor that triggered the workflow run. For more information, see \"Workflow syntax for GitHub Actions.\"
      3. Specifies the trigger for this workflow. This example uses the push event, so a workflow run is triggered every time someone pushes a change to the repository or merges a pull request. This is triggered by a push to every branch; for examples of syntax that runs only on pushes to specific branches, paths, or tags, see \"Workflow syntax for GitHub Actions\" and \"Events that trigger workflows\" .
      4. Groups together all the jobs that run in the learn-github-actions workflow.
      5. Defines a job named check-bats-version. The child keys will define properties of the job.
      6. Configures the job to run on the latest version of an Ubuntu Linux runner. This means that the job will execute on a fresh virtual machine hosted by GitHub. For syntax examples using other runners, see \"Workflow syntax for GitHub Actions\"
      7. Groups together all the steps that run in the check-bats-version job. Each item nested under this section is a separate action or shell script.
      8. The uses keyword specifies that this step will run v4 of the actions/checkout action. This is an action that checks out your repository onto the runner, allowing you to run scripts or other actions against your code (such as build and test tools). You should use the checkout action any time your workflow will use the repository's code.

        Actions are the building blocks that power your workflow. A workflow can contain actions created by the community, or you can create your own actions directly within your application's repository.

        To learn more, see:

        • Finding and customizing actions
        • About custom actions
      9. This step uses the actions/setup-node@v3 action to install the specified version of the Node.js. (This example uses version 14.) This puts both the node and npm commands in your PATH.

      10. The run keyword tells the job to execute a command on the runner. In this case, you are using npm to install the bats software testing package.
      11. Finally, you'll run the bats command with a parameter that outputs the software version.
      12. At the start of each workflow job, GitHub automatically creates a unique GITHUB_TOKEN secret to use in your workflow. You can use the GITHUB_TOKEN to authenticate in the workflow job.

        When you enable GitHub Actions, GitHub installs a GitHub App on your repository. The GITHUB_TOKEN secret is a GitHub App installation access token. You can use the installation access token to authenticate on behalf of the GitHub App installed on your repository. The token's permissions are limited to the repository that contains your workflow.

        You can modify the permissions for the GITHUB_TOKEN in individual workflow files. If the default permissions for the GITHUB_TOKEN are restrictive, you may have to elevate the permissions to allow some actions and commands to run successfully. If the default permissions are permissive, you can edit the workflow file to remove some permissions from the GITHUB_TOKEN. As a good security practice, you should grant the GITHUB_TOKEN the least required access.

        Learn more about the default Permissions for the GITHUB_TOKEN.

      13. This defines a map of variables that are available to the steps of all jobs in the workflow. You can also set variables that are only available to the steps of a single job or to a single step. Learn more at Defining environment variables for a single workflow.

      "},{"location":"exercises/01.collaborate/02/#implement-automated-pull-request-checks","title":"Implement Automated Pull Request Checks","text":"

      What is a Pull Request (also known as PR)?

      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.

      ~ About pull requests

      To enable quality checks in the project at high velocity, implement a workflow that standardizes automated checks as follows.

      .github/workflows/continuous.integration.yml
      name: Run Checks on PR\n\non:\n  pull_request:\n    branches:\n      - main\n\npermissions:\n  actions: write\n  checks: write\n  contents: read\n  security-events: write\n  pull-requests: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n  TETRIS_APP_HOST: \"127.0.0.1\"\n  TETRIS_APP_PORT: \"8080\"\n  TETRIS_APP_PATH: \"github-devsecops-fundamentals\"\n\njobs:\n  quality-checks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n\n      - name: Install Dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.ci.txt\n          npm ci\n          # Install browsers for running functional tests\n          npx playwright install --with-deps chromium\n\n      - name: Build\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n\n      - name: Functional Test\n        run: npx playwright test\n\n      - name: Upload Functional Test Report\n        uses: actions/upload-artifact@v3\n        if: always()\n        with:\n          name: playwright-report\n          path: playwright-report/\n          retention-days: 30\n
      "},{"location":"exercises/01.collaborate/02/#analysis","title":"Analysis","text":"
      • Lines 3 - 6

        The workflow will be triggered when a pull request is created targeting the main branch. Additional, changes to a pull request will cause the workflow to rerun.

      • Lines 43 - 45

        First check: The site is built with the --strict option, such that the occurrence of any WARNING results in a failed check. As it is, we can expect the automated checks to flag the pull request as non-compliant at this step.

      • Lines 47 - 48

        Second check: Provided the build step had been successful, this next step tests the correctness of the feature implementation in accordance to customer-value expectations. So far, we should not get to this point in the workflow run as the Build should have failed because the Tetris game feature implementation has not been completed.

      DEPRECATED EXERCISE STEP Optionally Implement Merge Queue for GitHub Enterprise

      What is a Merge Queue?

      A merge queue helps increase velocity by automating pull request merges into a busy branch and ensuring the branch is never broken by incompatible changes.

      The merge queue provides the same benefits as the Require branches to be up to date before merging branch protection, but does not require a pull request author to update their pull request branch and wait for status checks to finish before trying to merge.

      Using a merge queue is particularly useful on branches that have a relatively high number of pull requests merging each day from many different users.

      Once a pull request has passed all required branch protection checks, a user with write access to the repository can add the pull request to the queue. The merge queue will ensure the pull request's changes pass all required status checks when applied to the latest version of the target branch and any pull requests already in the queue.

      \ud83d\udcda Learn more...

      • Managing a merge queue
      • Merging a pull request with a merge queue

      The previously implemented pull request checks will be executed in isolation. However, to provide assurance of stability on the target branch as different changes are being introduced to it at a fast pace by multiple collaborators, we want to aggregate isolated changes and re-validate them in batches i.e. the Merge Queue.

      Is this like a Daily Build?

      You probably recognize this concept as similar to the implementation of a daily/nightly build. Except you do not have to wait ~ 24 hours or there about to validate your project's quality status.

      Configure Merge Queue

      A Merge Queue is ideal for rolling out continuous integration at scale, enabling larger projects and teams to be optimally productive -- delivering high quality value without compromising product stability.

      You can reserve execution of expensive checks in a merge queue, to save cost and time.

      To effectively leverage Merge Queue, you must first configure your repository to require it for pull requests as follows.

      1. On GitHub.com, navigate to the main page of the repository you have created.
      2. Under your repository name, click Settings. If you cannot see the \"Settings\" tab, select the dropdown menu, then click Settings.
      3. In the \"Code and automation\" section of the sidebar, click Branches.
      4. Next to \"Branch protection rules\", click Add branch protection rule.
      5. Under \"Branch name pattern\", type the branch name main for the branch you want to protect.
      6. Select Require merge queue.
      7. Click Create to complete Merge Queue configuration

      Finally implement the checks in merge queue as follows.

      .github/workflows/continuous.integration.merge.queue.yml
      name: Run Checks on Merge Queue\n\non:\n  merge_group:\n    types: [checks_requested]\n\npermissions:\n  actions: write\n  checks: write\n  contents: read\n  security-events: write\n  pull-requests: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n  TETRIS_APP_HOST: \"127.0.0.1\"\n  TETRIS_APP_PORT: \"8080\"\n  TETRIS_APP_PATH: \"github-devsecops-fundamentals\"\n\njobs:\n  run-acceptance:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n\n      - name: Install Dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.ci.txt\n          npm ci\n          # Install browsers for running functional tests\n          npx playwright install --with-deps chromium\n\n      - name: Build\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n\n      - name: Functional Test\n        run: npx playwright test\n\n      - name: Upload Functional Test Report\n        uses: actions/upload-artifact@v3\n        if: always()\n        with:\n          name: playwright-report\n          path: playwright-report/\n          retention-days: 30\n
      "},{"location":"exercises/01.collaborate/02/#publish-your-changes","title":"Publish your changes","text":"

      You can link your changes to an issue

      Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

      1. Commit and push the changes.

        git checkout -b feature/tetris-game\ngit add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n- Implement continuous integration\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push -u origin feature/tetris-game\n
      2. Create a pull request by clicking on the GitHub icon in the sidebar menu, and then clicking the Create Pull Request icon.

        Check that the local branch and repository you're merging from, and the remote branch and repository you're merging into, are correct. You may leave the pre-filled pull request title and description as they are.

        Click \"Create\", and if prompted then click \"Always\" or \"Publish Branch\".

      3. The pull request you created will be listed at https://github.com/<YOUR-HANDLE>/github-devsecops-fundamentals/pulls.

        Opening the pull request for exploration you should observe the following

        • Conversation

          Particularly enables and summarizes discussions/reviews on your changes with other collaborators and stakeholders. And additionally summarizes outcome of checks on the pull request. - Commits

          Summarizes all the commits contributing to the pull request.

        • Checks

          Lists the checks run on the pull request and their respective outcomes.

        • Files changed

          Shows a diff of files modified and added due to the pull request.

        Note

        Observe the 3 executed checks.

        • 1 failure due to error in site build.
        • 2 code scanning check passes.
      "},{"location":"exercises/01.collaborate/02/#implement-feature-changes","title":"Implement Feature Changes","text":"

      The Build step in the previously implemented automated checks should identify a failure ultimately pointing to incompletion of the expected Tetris game feature. In the current phase, we will take steps to integrate the Tetris game as follows.

      1. Rename the docs/.tetris.game folder to docs/tetris.game, i.e. simply remove the . prefix from the name.
      2. Find and open the file mkdocs.yml in the File Explorer (it's at the root of the file tree)

      3. Confirm that the Tetris Game relevant entry points to an index file in the tetris.game folder

         nav:\n   - Home: index.md\n   - Prerequisites: prerequisites.md\n   - Exercises:\n       - Introduction: exercises/index.md\n       - Collaborate:\n           - exercises/01.collaborate/index.md\n           - exercises/01.collaborate/01.md\n           - exercises/01.collaborate/02.md\n       - Secure the Software Supply Chain:\n           - exercises/02.secure.the.software.supply.chain/index.md\n           - exercises/02.secure.the.software.supply.chain/01.md\n           - exercises/02.secure.the.software.supply.chain/02.md\n       - Automate Release:\n           - exercises/03.automate.release/index.md\n           - exercises/03.automate.release/01.md\n           - exercises/03.automate.release/02.md\n       - \u2728 Recap:\n           - exercises/recap/index.md\n   - Tetris Game: tetris.game/index.html\n
      "},{"location":"exercises/01.collaborate/02/#manual-test","title":"Manual Test","text":"
      1. Observe the local build in the terminal, there should not be any WARNING in the log.
      2. Manually confirm that the Tetris Game integration was effective.
      "},{"location":"exercises/01.collaborate/02/#automated-test","title":"Automated Test","text":"

      Before publishing our new changes, we will implement and execute a functional test to validate the feature implementation.

      1. Open the terminal and install test dependencies.(1)

        1. \ud83d\udca1 You can create additional terminal session by clicking at the top right side of the TERMINAL panel.
        # Install Node.js\nnvm install --lts #(1)!\n# Install packages required for running the functional UI test\nnpm install\n# Install the browser(s) against which the functional UI test should run\nnpx playwright install --with-deps chromium #(2)!\n
        1. A codespace environment can be customized as needed. In this case, we customized the running session by installing the latest version of Node.js.
        2. This command installs browsers required for the functional test. Please be patient, it may take 1 to 2 minutes to complete the installation.

        Then implement the functional test as follows.

        tests/tetris.spec.js
        import { test, expect } from \"@playwright/test\";\n\ntest(\"Tetris Game\", async ({ page }) => {\n  const { TETRIS_APP_HOST, TETRIS_APP_PORT, TETRIS_APP_PATH } = process.env;\n\n  // should be similar to http://127.0.0.1:8080/github-devsecops-fundamentals/\n  console.log(\n    `http://${TETRIS_APP_HOST}:${TETRIS_APP_PORT}/${TETRIS_APP_PATH}`\n  );\n  await page.goto(\n    `http://${TETRIS_APP_HOST}:${TETRIS_APP_PORT}/${TETRIS_APP_PATH}`\n  );\n\n  await page.getByRole(\"link\", { name: \"Tetris Game\" }).click();\n  await expect(page.getByText(\"score 00000\")).toBeVisible();\n  await expect(page.getByText(\"rows 0\")).toBeVisible();\n  await expect(page.locator(\"#upcoming\")).toBeVisible();\n  await expect(\n    page.getByRole(\"link\", { name: \"Press Space to Play.\" })\n  ).toBeVisible();\n\n  await page.getByRole(\"link\", { name: \"Press Space to Play.\" }).click();\n  await expect(page.getByText(\"score 00000\")).not.toBeVisible({\n    timeout: 0.5 * 60 * 1000,\n  });\n});\n

        Finally execute the automated test.

        npx playwright test\n

        When everything has been done right, the test should pass.

      2. Commit the changes to the current feature/tetris-game branch and publish it for a review.

        You can link your changes to an issue

        Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

        git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Integrate Tetris game implementation\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin\n

        Observe that all checks have passed.

      "},{"location":"exercises/01.collaborate/02/#resources","title":"\ud83d\udcda Resources","text":"
      • Creating a GitHub Pages site
      • Introduction to dev containers
      • Workflow syntax for GitHub Actions
      • Events that trigger workflows
      • Finding and customizing actions
      • Code scanning
      • Security hardening for GitHub Actions
      "},{"location":"exercises/02.secure.the.software.supply.chain/","title":"Secure the Software Supply Chain","text":"

      Continuous Delivery and Secure Supply Chain

      Supply chain security is integral to continuous delivery. With the accelerated use of open source, most projects depend on hundreds of open-source dependencies. This poses a security problem: what if the dependencies you're using are vulnerable? You could be putting your users at risk of a supply chain attack. One of the most important things you can do to protect your supply chain is to patch your vulnerable dependencies and replace any malware.

      Building on the progress from previous exercises, we will apply supply chain security and continuously deliver the product by fulfilling the following objectives.

      "},{"location":"exercises/02.secure.the.software.supply.chain/#objectives","title":"Objectives","text":"
      • Create Integration Checks for the Tetris app using GitHub Actions.
      • Create a Continuous Delivery workflow for the Tetris app using GitHub Actions.
      • Create a new release tag for the Tetris app using GitHub Actions.
      • Create a Compliance using CodeQL, Dependency Review, and Dependabot.
      "},{"location":"exercises/02.secure.the.software.supply.chain/01/","title":"Dependency Review","text":"

      Add Security Checks

      Dependency review helps you understand dependency changes and the security impact of these changes at every pull request. It provides an easily understandable visualization of dependency changes with a rich diff on the \"Files Changed\" tab of a pull request. Dependency review informs you of:

      • Which dependencies were added, removed, or updated, along with the release dates.
      • How many projects use these components.
      • Vulnerability data for these dependencies.

      "},{"location":"exercises/02.secure.the.software.supply.chain/01/#exercise-automate-enforcement-of-dependency-review","title":"Exercise: Automate Enforcement of Dependency Review","text":""},{"location":"exercises/02.secure.the.software.supply.chain/01/#understand-the-dependency-review-configurations","title":"Understand the Dependency Review Configurations","text":".github/dependency-review-config.yml
      fail-on-severity: moderate #(1)!\n\ncomment-summary-in-pr: always #(2)!\n\nallow-licenses: #(3)!\n  - MIT\n  - GPL-3.0\n  - BSD-3-Clause\n\ndeny-licenses: #(4)!\n  - LGPL-2.0\n  - BSD-2-Clause\n\nallow-ghsas: #(5)!\n  - GHSA-abcd-1234-5679\n  - GHSA-efgh-1234-5679\n\nfail-on-scopes: #(6)!\n  - development\n  - runtime\n  - unknown\n
      1. Possible values: \"critical\", \"high\", \"moderate\", \"low\"
      2. Post summary as a comment to respective pull request
      3. Only allow the listed licenses (optional). Possible values: Any spdx_id value(s) from https://docs.github.com/en/rest/licenses
      4. Block the pull request on these licenses (optional). Possible values: Any spdx_id value(s) from https://docs.github.com/en/rest/licenses

        You can only include one of either of these two options: allow-licenses and deny-licenses.

      5. Skip these GitHub Advisory Database IDs during detection (optional). Possible values: Any valid GitHub Advisory Database ID from https://github.com/advisories

      6. Block pull requests that introduce vulnerabilities in the scopes that match this list (optional). Possible values: \"development\", \"runtime\", \"unknown\"
      "},{"location":"exercises/02.secure.the.software.supply.chain/01/#implement-dependency-review-check","title":"Implement Dependency Review Check","text":"

      Open the .github/workflows/continuous.integration.yml file in the editor and add the highlighted content as follows:

      .github/workflows/continuous.integration.yml
      name: Run Checks on PR\n\non:\n  pull_request:\n    branches:\n      - main\n\npermissions:\n  actions: write\n  checks: write\n  contents: read\n  security-events: write\n  pull-requests: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n  TETRIS_APP_HOST: \"127.0.0.1\"\n  TETRIS_APP_PORT: \"8080\"\n  TETRIS_APP_PATH: \"github-devsecops-fundamentals\"\n\njobs:\n  quality-checks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n\n      - name: Install Dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.ci.txt\n          npm ci\n          # Install browsers for running functional tests\n          npx playwright install --with-deps chromium\n\n      - name: Build\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n\n      - name: Functional Test\n        run: npx playwright test\n\n      - name: Upload Functional Test Report\n        uses: actions/upload-artifact@v3\n        if: always()\n        with:\n          name: playwright-report\n          path: playwright-report/\n          retention-days: 30\n\n  security-checks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Dependency Review\n        uses: actions/dependency-review-action@v3\n        with:\n          config-file: >-\n            ./.github/dependency-review-config.yml\n
      "},{"location":"exercises/02.secure.the.software.supply.chain/01/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

      Pushing your changes will apply the check on the existing pull request.

      You can link your changes to an issue

      Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

      git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Add dependency review as a security check\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n

      When you navigate to the repository on GitHub and open the existing pull request, you can confirm that the check was executed. As there are no compliance violations currently in the PR, the check is successful.

      Homework

      Can you attempt to make the dependency review check to fail?

      "},{"location":"exercises/02.secure.the.software.supply.chain/01/#resources","title":"\ud83d\udcda Resources","text":"
      • Understanding your software supply chain
      • GitHub Advanced Security - Dependency Graph
      "},{"location":"exercises/02.secure.the.software.supply.chain/02/","title":"Versioning","text":"

      Motivation for Versions

      A pull request represents a single aggregation of multiple significant changes (i.e. commits). When collaborating at scale in a large team or project, pull requests targeting the default (production) branch can be further buffered through a merge queue for further validation. In either cases, it is imperative to keep track of the aggregated changes introduced into the default branch which serves as the basic source of production releases.

      Some versions may eventually be released whereas others are not. Moreover, a released version may be rolled back to an earlier release as business decisions evolve.

      "},{"location":"exercises/02.secure.the.software.supply.chain/02/#exercise-version-changes-added-to-the-main-branch","title":"Exercise: Version Changes Added to the Main Branch","text":"

      Semantic Versioning, semver is a scheme that conveys meaning about the underlying code and what has been modified from one version to the next.

      semver version 2.0.0 is officially summarized as follows.

      Given a version number MAJOR.MINOR.PATCH, increment the:

      1. MAJOR version when you make incompatible API changes
      2. MINOR version when you add functionality in a backward compatible manner
      3. PATCH version when you make backward compatible bug fixes

      Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

      At this fundamentals phase of DevSecOps implementation, we will apply the semver scheme and automate patch increment. There are conventions that can be adopted to equally automate increment in MAJOR and MINOR versions, but for simplicity our intended implementation assumes the understanding that MAJOR and MINOR version bumps will be manually initiated.

      "},{"location":"exercises/02.secure.the.software.supply.chain/02/#implement-patch-versioning","title":"Implement PATCH Versioning","text":"

      In the file explorer, create a new workflow .github/workflows/continuous.versioning.yml as follows.

      .github/workflows/continuous.versioning.yml
      name: Version Changes to the Main Branch\n\non:\n  push:\n    branches:\n      - main\n  workflow_dispatch: {}\n\njobs:\n  version-main-branch-changes:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/create-github-app-token@v1\n        id: generate-app-token\n        with:\n          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}\n          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}\n\n      - name: Checkout\n        uses: actions/checkout@v3\n        with:\n          fetch-depth: 0\n          token: ${{ steps.generate-app-token.outputs.token }}\n\n      - name: Get last version number\n        id: get_last_version\n        run: |\n          # Retrieve the last git tag, as we will only be processing one delivery line.\n          last_version=$(git describe --tags --abbrev=0 2>/dev/null || echo \"0.0.0\")\n          echo \"Last version is $last_version\"\n          echo \"last_version=$last_version\" >> \"$GITHUB_OUTPUT\"\n\n      - name: Get new version number\n        id: get_new_version\n        run: |\n          major=$(echo $last_version | cut -d. -f1)\n          minor=$(echo $last_version | cut -d. -f2)\n          patch=$(echo $last_version | cut -d. -f3)\n\n          new_patch=$((patch+1))\n\n          new_version=\"$major.$minor.$new_patch\"\n\n          echo \"New version is $new_version\"\n          echo \"new_version=$new_version\" >> \"$GITHUB_OUTPUT\"\n        env:\n          last_version: ${{ steps.get_last_version.outputs.last_version }}\n\n      - name: Create tag for the new version\n        run: |\n          git config --global user.name \"${GITHUB_ACTOR}\"\n          git config --global user.email \"${GITHUB_ACTOR}@users.noreply.github.com\"\n\n          if git tag -a \"$new_version\" -m \"Version $new_version\"; then\n            git push --follow-tags origin \"$new_version\"\n          else\n            echo \"Failed to create tag $new_version, it probably already exists\"\n          fi\n        env:\n          new_version: ${{ steps.get_new_version.outputs.new_version }}-release\n
      "},{"location":"exercises/02.secure.the.software.supply.chain/02/#analysis","title":"Analysis","text":"
      • Lines 4 - 6

        We are introduced to a new event that encapsulates the activity of pushing to particular branches, specifically the main branch alone in this implementation.

      • Lines 13 - 17

        A GitHub App will be used as the actor for the operations we shall be executing. Hence the actions/create-github-app-token@v1 action is used here to generate an authorization token for the app.

        What is a GitHub App?

        GitHub Apps, much like service accounts and bots, are tools that extend GitHub's functionality. You can build a GitHub App to provide flexibility and reduce friction in your processes, without needing to sign in a user or create a service account . GitHub Apps can do things on GitHub like open issues, comment on pull requests, and manage projects. They can also do things outside of GitHub based on events that happen on GitHub. For example, a GitHub App can post on Slack when an issue is opened on GitHub.

        The GitHub App actor will later be used to checkout the repository's source code and to push tags.

      • Lines 25 - 31

        The step Get last version number computes the last version and writes it to the step output named last_version.

      • Lines 33 - 47

        The step Get new version number uses reads the output from the previous step by the expression ${{ steps.get_last_version.outputs.last_version }}, and use it to compute the patch increment.

      • Lines 49 - 60

        The step Create tag for the new version creates a new git tag for release. A tag identifies specific points in a repository\u2019s history as being important. Here, the tag is being used to mark a release point.

        Because a persisted app token exists and will be used in the tag push, we can be confident that the push will effectively trigger other relevant automation. On the other hand, if the default GITHUB_TOKEN was used it would not trigger a workflow as GitHub Actions rightly guard against unintentional recursive triggering of workflows .

      "},{"location":"exercises/02.secure.the.software.supply.chain/02/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

      You can link your changes to an issue

      Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

      git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Implement automatic patch versioning\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n
      "},{"location":"exercises/02.secure.the.software.supply.chain/02/#resources","title":"\ud83d\udcda Resources","text":"
      • Semantic Versioning 2.0.0
      "},{"location":"exercises/03.automate.release/","title":"Automate Deployment of Releases","text":"

      Continuous Deployment

      Continuous deployment (CD) is the practice of using automation to publish and deploy software updates. As part of the typical CD process, the code is automatically built and tested before deployment.

      Continuous deployment is often coupled with continuous integration which we have seen earlier. Building on the progress from previous exercises, we will apply continuous deployment mindset by fulfilling the following objectives.

      "},{"location":"exercises/03.automate.release/#objectives","title":"Objectives","text":"
      • Validate releases
      • Execute production deployments on successful validation of respective releases
      "},{"location":"exercises/03.automate.release/01/","title":"Release Version","text":"

      Release

      As streams of changes make it into the production branch and are versioned in batches, an essential part of continuous delivery/deployment is to produce artifacts from versions which can then be deployed to various targets.

      Releases are deployable software iterations you can package and make available for a wider audience to download and use.

      How do we determine when to create a release? Let's see...

      "},{"location":"exercises/03.automate.release/01/#exercise-create-a-release-of-versions","title":"Exercise: Create a Release of Versions","text":"

      As you can guess already, GitHub provides an event that encapsulates the activity of creating a tag and pushing it to a repository. We will automate addressing such events, so that we can create a release when necessary.

      "},{"location":"exercises/03.automate.release/01/#implement-release-creation","title":"Implement Release Creation","text":"

      In the file explorer, create a new workflow .github/workflows/continuous.delivery.yml as follows.

      .github/workflows/continuous.delivery.yml
      name: Package Delivery Artifacts & Create Release\n\non:\n  push:\n    tags:\n      - \"*-release\"\n\npermissions:\n  contents: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n\njobs:\n  package-delivery:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - name: Install Python dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.txt\n      - name: Build Site\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n      - name: Archive Site\n        run: |\n          zip -r ${{ env.SITE_DIR }}.zip ${{ env.SITE_DIR }}\n      - run: |\n          echo \"Site directory ${{ env.SITE_DIR }} content:\"\n          ls -al ${{ env.SITE_DIR }}\n\n      - uses: actions/create-github-app-token@v1\n        id: generate-app-token\n        with:\n          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}\n          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}\n\n      - name: Draft release\n        uses: actions/github-script@v6\n        id: draft-release\n        with:\n          github-token: ${{ steps.generate-app-token.outputs.token }}\n          script: |\n\n            const response = await github.request(\n              'POST /repos/{owner}/{repo}/releases',\n              {\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                draft: true,\n                tag_name: '${{ github.ref }}',\n                discussion_category_name: 'announcements',\n                generate_release_notes: true,\n                make_latest: 'legacy',\n                headers: {\n                  'X-GitHub-Api-Version': '2022-11-28'\n                }\n              }\n            );\n\n            console.dir(response);\n\n            return response.data.id;\n\n      - name: Upload release asset\n        run: |\n          curl -L \\\n            -X POST \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"Authorization: Bearer ${{ steps.generate-app-token.outputs.token }}\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            -H \"Content-Type: application/octet-stream\" \\\n            \"https://uploads.github.com/repos/${{ github.repository }}/releases/${{ steps.draft-release.outputs.result }}/assets?name=${{ env.SITE_DIR }}.zip\" \\\n            --data-binary \"@${{ env.SITE_DIR }}.zip\"\n\n      - name: Publish release\n        uses: actions/github-script@v6\n        id: publish-release\n        with:\n          github-token: ${{ steps.generate-app-token.outputs.token }}\n          script: |\n\n            const response = await github.request(\n              'PATCH /repos/{owner}/{repo}/releases/{release_id}',\n              {\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                release_id: ${{ steps.draft-release.outputs.result }},\n                draft: false,\n                discussion_category_name: 'announcements',\n                make_latest: 'true',\n                headers: {\n                  'X-GitHub-Api-Version': '2022-11-28'\n                }\n              }\n            );\n\n            console.dir(response);\n
      "},{"location":"exercises/03.automate.release/01/#analysis","title":"Analysis","text":"
      • Lines 3 - 6

        The release creation workflow will be triggered by tag pushes and when the pushed tag version is suffixed with the -release metadata.

      • Lines 29 - 34

        In the two steps included here, the site is built and archived as a release artifact.

      • Lines 39 - 43

        A GitHub App will be used as the actor for the operations we shall be executing. Hence the actions/create-github-app-token@v1 action is used here to generate an authorization token for the app.

        What is a GitHub App?

        GitHub Apps, much like service accounts and bots, are tools that extend GitHub's functionality. You can build a GitHub App to provide flexibility and reduce friction in your processes, without needing to sign in a user or create a service account . GitHub Apps can do things on GitHub like open issues, comment on pull requests, and manage projects. They can also do things outside of GitHub based on events that happen on GitHub. For example, a GitHub App can post on Slack when an issue is opened on GitHub.

        When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.

        ~ Using the GITHUB_TOKEN in a workflow

        So, we are authorizing operations as a GitHub App to enable the execution of the operation to further trigger other workflow flow runs, possibly.

      • Lines 45 - 70

        A draft release is created by the respective step, allowing for modification of the release before publishing it. The release references the tag that had triggered the workflow.

      • Lines 72 - 81

        This step leverages GitHub's ReST API to adjust the previously created draft release, specifically adding the archive created in the Archive Site step to the release as an asset.

      • Lines 83 - 105

        Having drafted the release and attached deployable assets to it, the Publish release step ultimately publishes the release by flipping the state of it draft attribute to false.

      "},{"location":"exercises/03.automate.release/01/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

      You can link your changes to an issue

      Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

      git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Implement release automation\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n
      "},{"location":"exercises/03.automate.release/01/#resources","title":"\ud83d\udcda Resources","text":"
      • GitHub Apps documentation
      • GitHub REST API documentation
      • GitHub Packages
      "},{"location":"exercises/03.automate.release/02/","title":"Continuous Deployment","text":"

      Deliver high quality value at speed

      Continuous deployment (CD) is the practice of using automation to publish and deploy software updates.

      To ultimately fulfill our goal on complete development of the feature, we altogether apply the practice of continuous deployment to validate and ship the value to our customers at high velocity.

      "},{"location":"exercises/03.automate.release/02/#exercise-automate-deployment-of-releases","title":"Exercise: Automate Deployment of Releases","text":"

      The previous exercise walked us through automating the publication of release. We will continue to build upon that milestone to automate deployment of published releases.

      "},{"location":"exercises/03.automate.release/02/#implement-deployment-workflow","title":"Implement Deployment Workflow","text":"

      In the file explorer, create a new workflow .github/workflows/continuous.deployment.yml as follows.

      .github/workflows/continuous.deployment.yml
      name: Deploy Release\n\non:\n  release:\n    types:\n      - released\n\nconcurrency:\n  group: github-pages\n  cancel-in-progress: false\n\npermissions:\n  contents: write\n  deployments: write\n  pages: write\n  id-token: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n\n    steps:\n      - uses: actions/create-github-app-token@v1\n        id: generate-app-token\n        with:\n          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}\n          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}\n\n      - name: Setup Pages\n        uses: actions/configure-pages@v3\n        with:\n          enablement: \"true\"\n          token: \"${{ steps.generate-app-token.outputs.token }}\"\n\n      - name: Download release asset\n        id: download-release-asset\n        run: |\n          cat << 'EOF' > event.json\n          ${{ toJson(github.event) }}\n          EOF\n          asset_id=$(cat event.json | jq '.release.assets[] | select(.name == \"${{ env.SITE_DIR }}.zip\") | .id')\n\n          curl --location --output '${{ env.SITE_DIR }}.zip'                          \\\n            -H \"Accept: application/octet-stream\"                                     \\\n            -H \"Authorization: Bearer ${{ steps.generate-app-token.outputs.token }}\"  \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\"                                     \\\n            \"https://api.github.com/repos/${{ github.repository }}/releases/assets/${asset_id}\"\n\n          unzip -o \"${{ env.SITE_DIR }}.zip\" -d .\n\n          echo '##### Debug'\n          ls -al \"${{ env.SITE_DIR }}\"\n\n      - name: Fix site file permissions\n        run: |\n          chmod -c -R +rX \"${{ env.SITE_DIR }}/\" | while read line; do\n            echo \"::warning title=Invalid file permissions automatically fixed::$line\"\n          done\n\n      - name: Upload Pages artifact\n        uses: actions/upload-pages-artifact@v2\n        with:\n          path: \"${{ env.SITE_DIR }}\"\n          retention-days: \"2\"\n\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v2\n        with:\n          token: ${{ steps.generate-app-token.outputs.token }}\n
      "},{"location":"exercises/03.automate.release/02/#analysis","title":"Analysis","text":"
      • Lines 3 - 6

        Deployments will be triggered in the event of a release publication.

      • Lines 8 - 10

        Ensure that only a single job or workflow using the same concurrency group will run at a time.

        When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. Any previously pending job or workflow in the concurrency group will be canceled. If you do not wish to also cancel any currently running job or workflow in the same concurrency group, specify cancel-in-progress: false.

      • Lines 25 - 27

        This will cause the URL of the deployed site to be displayed where the workflow is executed.

      • Lines 36 - 40

        This step enables GitHub Pages and extracts various metadata about a site. It can also be used to configure various static site generators we support as starter workflows.

      • Lines 42 - 65

        Download assets associated with the release publication that triggered this workflow, and where necessary, adjust permissions for the files in the assets.

      • Lines 67 - 71

        Upload the site artifacts to the storage location where it should be ultimately collected by the next step for deployment.

      • Lines 73 - 77

        This step deploys the site.

      "},{"location":"exercises/03.automate.release/02/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

      You can link your changes to an issue

      Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

      git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Implement continuous deployment\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n
      "},{"location":"exercises/03.automate.release/02/#merge-your-open-pull-request","title":"Merge your open pull request","text":"
      • On the pull request page, open the drop-down from the Merge pull request button to choose the Rebase and merge option.

      • Then press the Rebase and merge button to merge your pull request.

      • Finally, press Confirm rebase and merge.

      When you merge the open pull request, you should make the following observations.

      Collaboration

      • The linked issue in your project board automatically gets closed and moved to the \u2705 Done column of the board.

      Automation

      When you head over to the Actions tab on your repository, and notice...

      • The Version Changes to the Main Branch workflow is executed.
      • The Package Delivery Artifacts & Create Release workflow is executed.

        Consequently the release is announced in Discussions.

      • The Deploy Release workflow is executed.

        And on successful completion of the workflow, the public URL to your site is displayed on the job.

      Stakeholder Enablement

      Stakeholders can easily explore deployments of the project.

      • Deployments summary on repository home.

      • Detailed deployment environments list.

      "},{"location":"exercises/03.automate.release/02/#resources","title":"\ud83d\udcda Resources","text":"
      • Using environments for deployment
      • Creating custom deployment protection rules
      • Security harden deployments with OpenID Connect
      "},{"location":"exercises/recap/","title":"Review of Workshop Outcomes","text":"

      So far, we have reached the following milestones, learning to

      • Track work on GitHub
      • Rapidly onboard onto an existing project
      • Work in a collaborative manner, and enable quick incorporation of feedbacks
      • Efficiently secure the software supply chain, catching vulnerabilities and non-compliant dependencies as they are introduced
      • Automate versioning
      • Automate releases
      • Implement continuous deployment
      "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"GitHub DevSecOps Fundamentals | Workshop","text":"

      This self-paced workshop will enable you acquire the capabilities to implement a DevSecOps mindset, leveraging the GitHub platform for a seamless developer experience.

      GitHub Platform"},{"location":"#learning-objectives","title":"Learning Objectives","text":"
      • Collaborate effectively for high-velocity productivity
      • Apply preventive security to every aspect of the development process
      • Implement a secure software supply chain
      • Automate product release and business processes in general
      • Remove complications due to tool-bloat

      Complete the Prerequisites checklist!

      "},{"location":"#resources","title":"\ud83d\udcda Resources","text":"

      Get expert workshop facilitation...

      This publicly available workshop is limited to enable you learn with accompanying research. It does not address concepts at an enterprise-scope.

      Contact \ud83d\udce7 services@github.com to benefit more from a workshop facilitation by GitHub's expert services to support advancement of DevSecOps implementation in your organisation.

      • Project planning for developers
      • Start coding instantly with Codespaces
      • Automate your workflow from idea to production
      • Secure at every step
      • Your packages, at home with their code
      "},{"location":"prerequisites/","title":"Prerequisites","text":"

      Prepare before the workshop

      To ensure a seamless workshop experience, complete the following checklist items in order.

      "},{"location":"prerequisites/#set-up-a-github-account","title":"Set up a GitHub account","text":"

      Login to your GitHub account.

      You may create a new GitHub account, if you do not already have one. (1)

      1. Clicking the button below will open the page on a new tab, for you to create a new GitHub account. Keep your @handle handy after you have logged in.

      Create a new GitHub account

      "},{"location":"prerequisites/#clone-the-workshop-project-to-your-own-account","title":"Clone the workshop project to your own account","text":"
      1. Create workshop project
      2. In the new tab, most of the prompts will automatically fill in for you and the default settings should be fine. Otherwise...

        • For owner, choose your personal account or.
        • We recommend creating a public repository. (1)

          1. Public repositories benefit from

            • Free use of GitHub Actions minutes.
            • Free use of GitHub Advanced Security features.
        • Scroll down and click the Create repository button at the bottom of the form.

          Expand for sample view...

      3. After creation of your new repository has begun, wait about 20 seconds, then refresh the page.

      "},{"location":"prerequisites/#enable-discussions","title":"Enable Discussions","text":"
      1. On GitHub.com, navigate to the main page of your new repository.
      2. Under your repository name, click Settings.
      3. Scroll down to the \"Features\" section and click Set up discussions"},{"location":"prerequisites/#configure-base-security","title":"Configure base security","text":"
        1. Navigate to the Settings tab on your new workshop repository.
        2. Under the \"Security\" section of the menu, select Code security and analysis. Then configure the settings to match as follows (by clicking Enable where the option is/becomes available).

          Further configurations guide...

          • Dependabot version updates

            When enabling, you will be prompted to edit the .github/dependabot.yml configuration file. Simply navigate back on your browser or click on Cancel changes to leave the prompt, and to continue the base security configuration.

          • CodeQL analysis

            1. From the Set up, select the Default option.
            2. Leave the default settings in the prompt that follows, and simply click on Enable CodeQL to continue.
          • Protection rules

            Select the configuration as shown below.

        "},{"location":"prerequisites/#register-a-github-app","title":"Register a GitHub App","text":"
        1. In the upper-right corner of any page on GitHub, click your profile photo.
        2. Navigate to your account Settings.
        3. In the left sidebar, click Developer settings.
        4. In the left sidebar, click GitHub Apps
        5. Click New GitHub App

          Provide the form fields value as follows

          GitHub App Name..........: <YOUR-HANDLE>-bot\n\nHomepage URL.............: https://github.com/<YOUR-HANDLE>/github-devsecops-fundamentals\n\nWebhook\n  Active.................: DESELECT\n\nRepository permissions\n  Actions................: Read and write\n  Administration.........: Read and write\n  Contents...............: Read and write\n  Deployments............: Read and write\n  Discussions............: Read and write\n  Environments...........: Read and write\n  Pages..................: Read and write\n\nWhere can this GitHub App be installed?\n  Any account.................: SELECT\n
        6. Generate a private key for the new GitHub App as documented in here.

        7. Save the GitHub App private key to your new repository's secrets under the name of APP_PRIVATE_KEY_ACTIONS_ASSISTANT.

          \ud83d\udc40 Creating secrets for a repository.

        8. Save the GitHub App's appid to your new repository's variables under the name of APP_ID_ACTIONS_ASSISTANT.

          \ud83d\udc40 Creating configuration variables for a repository

        9. Goto https://github.com/apps/<YOUR-HANDLE>-bot. Install the app in the repository you created earlier.

          Expand for additional guide and sample views...

        What is the use of a GitHub App?

        When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.

        If you do want to trigger a workflow from within a workflow run, you can use a GitHub App installation access token or a personal access token instead of GITHUB_TOKEN to trigger events that require a token.

        If you use a GitHub App, you'll need to create a GitHub App and store the app ID and private key as secrets.

        ~ Triggering a workflow from a workflow

        During the course of the workshop exercises, you will discover how the GitHub App is used to trigger the automatic deployment of release artifacts.

        "},{"location":"prerequisites/#create-a-project-board-for-the-repository","title":"Create a project board for the repository","text":"
        1. Open the recently created workshop repository.

        2. Navigate to the Projects tab.

        3. Open the Link a project dropdown menu . Then select the New Project option.

        4. Click on the New project button to start the project creation wizard.

        5. Select the Team backlog template.
        6. Give a name to the project
        7. Finally click on the Create button.

        "},{"location":"prerequisites/#provision-a-new-cloud-development-environment-for-the-workshop","title":"Provision a new cloud development environment for the workshop","text":"

        GitHub Codespaces enables you to instantly start coding on the workshop project. Personal accounts on GitHub can benefit from a free quota of GitHub Codespaces usage.

        1. Navigate to the Code tab.

        2. Open the Code menu and click on Create codespaces on main.

          Expand for sample view...

        3. Leave the Codespace development environment to initialize and run, we will come back to use it later.

          "},{"location":"exercises/","title":"Introduction","text":"

          Workshop Exercises

          The workshop exercises provide guidance for implementing DevSecOps at the fundamental level with the GitHub platform. On completion, you would have gained the exposure to enable you seamlessly implement DevSecOps capabilities such as

          • Continuous collaboration
          • Continuous planning
          • Continuous integration
          • Continuous delivery
          • Continuous quality
          • Continuous security

          This workshop site also serves as the product we shall target for development. And During the course of the exercises, you will discover how you can rapidly build and test the site locally, and implement standardized tests to enable automated quality checks on the site.

          "},{"location":"exercises/#workshop-scenario","title":"Workshop Scenario","text":"

          You are working in a team that owns this site, and a new business goal has come into the vision of your organisation. In order to grow engagement with the site...

          ...the goal is to create a Tetris Game to delight our site visitors.

          Outcome: Tetris Game

          "},{"location":"exercises/#milestones","title":"Milestones","text":"

          The workshop objectives will be delivered by completion of the following milestones

          • Collaborate

            Facilitate onboarding into the site project and enable project development at high velocity for stakeholders of different experience with the project.

          • Secure the software supply chain

            Seamlessly implement application security and secure the software supply chain.

          • Automate Deployment of Releases

            Reliably deliver value to the end-user at high velocity.

          "},{"location":"exercises/01.collaborate/","title":"Collaborate","text":"

          Continuous Collaboration

          Continuous collaboration enables working together across technical and cultural boundaries as a unified team, reducing frictions and increasing the velocity to accomplish common goals.

          "},{"location":"exercises/01.collaborate/#objectives","title":"Objectives","text":"

          Behaviors that enable addressing the challenge include

          • Facilitate tracking of business goal delivery
          • Enable rapid onboarding to project development
          • Provide a standardized validation of work done
          • Enable collaborative validation of done requirement
          "},{"location":"exercises/01.collaborate/01/","title":"Project Management","text":"

          Facilitate collaborative tracking of business goal delivery

          As part of the prerequisite steps, you had created a project management board. You will now build on that step and keep stakeholders in the loop through the full course of the development process.

          "},{"location":"exercises/01.collaborate/01/#exercise-create-an-issue-to-capture-the-goal","title":"Exercise: Create an issue to capture the goal","text":"

          What is GitHub Issues?

          Use GitHub Issues to track ideas, feedback, tasks, or bugs for 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.

          "},{"location":"exercises/01.collaborate/01/#refer-back-to-the-project-created-in-the-prerequisite-to-the-workshop","title":"Refer back to the project created in the prerequisite to the workshop","text":""},{"location":"exercises/01.collaborate/01/#create-an-issue-to-capture-the-goal","title":"Create an issue to capture the goal","text":"
          1. Identify the Backlog column
          2. Click on + Add item at the bottom of the column
          3. Click on the + button
          4. Select Create new issue from the menu
          5. Choose the repository you created earlier
          6. Choose Feature request (1)

            1. The issue creation was facilitated with an \ud83d\udc40 issue template.

              .github/ISSUE_TEMPLATE/feature_request.md
              ---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n
          7. Fill the form. Feel free to be creative \ud83d\ude42 with your inputs.

            For the title...

            You may for instance enter \"Create a Tetris game to delight our site visitors\".

            After filling the form in, click Create to create the issue. (1)

            1. Things you can do in an issue include but are not limited to
              • Assign the issue to yourself or other stakeholders.
              • Mention other stakeholders (people and teams) to notify them for awareness.
          "},{"location":"exercises/01.collaborate/01/#take-note-of-the-issue-number","title":"Take note of the issue number","text":"

          We will use the issue number to link the the issue to subsequent work later. If you are too curious and cannot wait, see \ud83d\udc40 Linking a pull request to an issue.

          Moreover, having created the issue, we can update the issue with comments to keep collaborating stakeholders in the loop.

          "},{"location":"exercises/01.collaborate/01/#resources","title":"\ud83d\udcda Resources","text":"
          • Project planning for developers
          • Planning and tracking work for your team or project
          • Linking a pull request to an issue
          • Create diagrams to convey information through charts and graphs
          "},{"location":"exercises/01.collaborate/02/","title":"Implement Features","text":"

          Enable rapid onboarding to project development

          Our goal is to create a Tetris Game to delight our site visitors, without losing time to complex project onboarding process nor complications due to tool-bloat.

          Currently, navigating to the Tetris Game page of the workshop site shows that the feature is currently missing. We will address that issue in this exercise.

          "},{"location":"exercises/01.collaborate/02/#exercise-integrate-the-tetris-game","title":"Exercise: Integrate the Tetris Game","text":"

          Refer back to the Codespaces development environment created in the prerequisite to the workshop.(1)

          1. Your Codespace may have stopped due to inactivity. Do not worry, it is quite easy to get back on track...

            • If the browser tab with your Codespace remains open and you can find it, click Restart codespace to resume.
            • Otherwise, you can find it at the new repository you had created.
          "},{"location":"exercises/01.collaborate/02/#explore-your-codespace","title":"Explore your Codespace","text":""},{"location":"exercises/01.collaborate/02/#understand-your-codespace","title":"Understand Your Codespace","text":"

          .devcontainer/devcontainer.json describes the provisioning of your codespace. Some of the configuration entries are explained below, with annotations next to the respective entry. You can learn more about the Development Container Specification at your convenience.

          .devcontainer/devcontainer.json
          {\n  \"hostRequirements\": {//(1)!\n    \"cpus\": 4,\n    \"memory\": \"16gb\",\n    \"storage\": \"32gb\"\n  },\n  \"build\": {\n    \"dockerfile\": \"./Dockerfile\",//(2)!\n    \"context\": \"..\"\n  },\n  \"postAttachCommand\": \"python -m mkdocs serve --clean --dev-addr 127.0.0.1:8080\",//(3)!\n  \"forwardPorts\": [\n    8080\n  ],\n  \"containerEnv\": {\n    \"TETRIS_APP_HOST\": \"127.0.0.1\",\n    \"TETRIS_APP_PORT\": \"8080\",\n    \"TETRIS_APP_PATH\": \"github-devsecops-fundamentals\"\n  },\n  ...\n
          1. You can customize the compute resource to be made available for the Codespace environment, to suit your project.
          2. A Dockerfile can be used to customize the Codespace container image, for instance you may choose to consistently pre-install dependencies required for the development environment.
          3. Tasks may be configured to be executed at the start of each development session e.g. running a development server.

          On the TERMINAL view at the bottom, notice that a local site server is already running. This is as a result of the postAttachCommand configuration entry in .devcontainer/devcontainer.json.

          Looking at the build log in the terminal, you can see a warning like the one in the following example.(1)

          1. \ud83d\udca1 The warning gives a cue to addressing the Tetris Game integration issue. We shall implement the fix in later steps!

          The log INFO entry that reads INFO - [05:36:30] Watching paths for changes: 'docs', 'mkdocs.yml' informs you that thelocal site will rebuild whenever there is a change in the docs folder.

          "},{"location":"exercises/01.collaborate/02/#enable-quick-collaboration-feedback","title":"Enable Quick Collaboration Feedback","text":"

          Switch to the PORTS view on the bottom panel, notice there is a Site (8080) entry in the table.

          1. Focus your mouse pointer on the Site (8080) to reveal additional contexts.
          2. Click the Preview in Editor icon to browse the local build of the site inside of the editor's browser.(1)

              • Only you currently have access to the published site.
            1. You may instead click the icon associated with Site (8080) entry to view the site in your normal browser.

          Open access to other stakeholders for collaboration.

          1. Right click on the Site (8080) entry
          2. In the popup menu, set the mouse pointer on the Port Visibility item and select the Public option.

          Now, other stakeholders you share the site URL with can access the site. Consequently, they can also assess your ongoing work and can collaborate with timely feedbacks.

          "},{"location":"exercises/01.collaborate/02/#implement-automated-checks","title":"Implement Automated Checks","text":"

          GitHub as a platform, is event-driven. Beyond the ordinary, you can generally automate your actual business processes by modelling activities to produce changes on GitHub, thus triggering execution of certain automated tasks depending on the nature of a change. If you already familiar with the concept of GitOps, think of how the idea can be extended beyond the scopes of provisioning infrastructure and implementing continuos deployment.

          At this fundamentals phase of introduction to DevSecOps, we shall focus our leverage of GitHub's powerful event system to drive continuous integration checks and tests with GitHub Workflows.

          "},{"location":"exercises/01.collaborate/02/#learn-github-actions","title":"Learn GitHub Actions","text":"

          What is GitHub Actions?

          GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline. You can create workflows that build and test every pull request to your repository, or deploy merged pull requests to production.

          GitHub Actions goes beyond just DevOps and lets you run workflows when other events happen in your repository. For example, you can run a workflow to automatically add the appropriate labels whenever someone creates a new issue in your repository.

          GitHub provides Linux, Windows, and macOS virtual machines to run your workflows, or you can host your own self-hosted runners in your own data center or cloud infrastructure.

          ~ Understanding GitHub Actions

          Anatomy of a GitHub Workflow
          name: Learn GitHub Actions #(1)!\n\nrun-name: ${{ github.actor }}  is learning GitHub Actions #(2)!\n\non: [push] #(3)!\n\npermissions: #(12)!\n    contents: read\n\nenv: #(13)!\n    LEARNER_NAME: Igwe\n\njobs: #(4)!\n\n    check-bats-version: #(5)!\n\n        runs-on: ubuntu-latest #(6)!\n\n        steps: #(7)!\n\n            - uses: actions/checkout@v4 #(8)!\n\n            - uses: actions/setup-node@v3 #(9)!\n              with:\n                  node-version: '14'\n\n            - run: npm install -g bats #(10)!\n\n            - run: bats -v #(11)!\n\n            - run: echo \"Hey ${LEARNER_NAME}, you're good... You've mastered GitHub Actions\\!\"\n
          1. Optional - The name of the workflow as it will appear in the \"Actions\" tab of the GitHub repository. If this field is omitted, the name of the workflow file will be used instead.
          2. Optional - The name for workflow runs generated from the workflow, which will appear in the list of workflow runs on your repository's \"Actions\" tab. This example uses an expression with the github context to display the username of the actor that triggered the workflow run. For more information, see \"Workflow syntax for GitHub Actions.\"
          3. Specifies the trigger for this workflow. This example uses the push event, so a workflow run is triggered every time someone pushes a change to the repository or merges a pull request. This is triggered by a push to every branch; for examples of syntax that runs only on pushes to specific branches, paths, or tags, see \"Workflow syntax for GitHub Actions\" and \"Events that trigger workflows\" .
          4. Groups together all the jobs that run in the learn-github-actions workflow.
          5. Defines a job named check-bats-version. The child keys will define properties of the job.
          6. Configures the job to run on the latest version of an Ubuntu Linux runner. This means that the job will execute on a fresh virtual machine hosted by GitHub. For syntax examples using other runners, see \"Workflow syntax for GitHub Actions\"
          7. Groups together all the steps that run in the check-bats-version job. Each item nested under this section is a separate action or shell script.
          8. The uses keyword specifies that this step will run v4 of the actions/checkout action. This is an action that checks out your repository onto the runner, allowing you to run scripts or other actions against your code (such as build and test tools). You should use the checkout action any time your workflow will use the repository's code.

            Actions are the building blocks that power your workflow. A workflow can contain actions created by the community, or you can create your own actions directly within your application's repository.

            To learn more, see:

            • Finding and customizing actions
            • About custom actions
          9. This step uses the actions/setup-node@v3 action to install the specified version of the Node.js. (This example uses version 14.) This puts both the node and npm commands in your PATH.

          10. The run keyword tells the job to execute a command on the runner. In this case, you are using npm to install the bats software testing package.
          11. Finally, you'll run the bats command with a parameter that outputs the software version.
          12. At the start of each workflow job, GitHub automatically creates a unique GITHUB_TOKEN secret to use in your workflow. You can use the GITHUB_TOKEN to authenticate in the workflow job.

            When you enable GitHub Actions, GitHub installs a GitHub App on your repository. The GITHUB_TOKEN secret is a GitHub App installation access token. You can use the installation access token to authenticate on behalf of the GitHub App installed on your repository. The token's permissions are limited to the repository that contains your workflow.

            You can modify the permissions for the GITHUB_TOKEN in individual workflow files. If the default permissions for the GITHUB_TOKEN are restrictive, you may have to elevate the permissions to allow some actions and commands to run successfully. If the default permissions are permissive, you can edit the workflow file to remove some permissions from the GITHUB_TOKEN. As a good security practice, you should grant the GITHUB_TOKEN the least required access.

            Learn more about the default Permissions for the GITHUB_TOKEN.

          13. This defines a map of variables that are available to the steps of all jobs in the workflow. You can also set variables that are only available to the steps of a single job or to a single step. Learn more at Defining environment variables for a single workflow.

          "},{"location":"exercises/01.collaborate/02/#implement-automated-pull-request-checks","title":"Implement Automated Pull Request Checks","text":"

          What is a Pull Request (also known as PR)?

          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.

          ~ About pull requests

          To enable quality checks in the project at high velocity, implement a workflow that standardizes automated checks as follows.

          .github/workflows/continuous.integration.yml
          name: Run Checks on PR\n\non:\n  pull_request:\n    branches:\n      - main\n\npermissions:\n  actions: write\n  checks: write\n  contents: read\n  security-events: write\n  pull-requests: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n  TETRIS_APP_HOST: \"127.0.0.1\"\n  TETRIS_APP_PORT: \"8080\"\n  TETRIS_APP_PATH: \"github-devsecops-fundamentals\"\n\njobs:\n  quality-checks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n\n      - name: Install Dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.ci.txt\n          npm ci\n          # Install browsers for running functional tests\n          npx playwright install --with-deps chromium\n\n      - name: Build\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n\n      - name: Functional Test\n        run: npx playwright test\n\n      - name: Upload Functional Test Report\n        uses: actions/upload-artifact@v3\n        if: always()\n        with:\n          name: playwright-report\n          path: playwright-report/\n          retention-days: 30\n
          "},{"location":"exercises/01.collaborate/02/#analysis","title":"Analysis","text":"
          • Lines 3 - 6

            The workflow will be triggered when a pull request is created targeting the main branch. Additional, changes to a pull request will cause the workflow to rerun.

          • Lines 43 - 45

            First check: The site is built with the --strict option, such that the occurrence of any WARNING results in a failed check. As it is, we can expect the automated checks to flag the pull request as non-compliant at this step.

          • Lines 47 - 48

            Second check: Provided the build step had been successful, this next step tests the correctness of the feature implementation in accordance to customer-value expectations. So far, we should not get to this point in the workflow run as the Build should have failed because the Tetris game feature implementation has not been completed.

          DEPRECATED EXERCISE STEP Optionally Implement Merge Queue for GitHub Enterprise

          What is a Merge Queue?

          A merge queue helps increase velocity by automating pull request merges into a busy branch and ensuring the branch is never broken by incompatible changes.

          The merge queue provides the same benefits as the Require branches to be up to date before merging branch protection, but does not require a pull request author to update their pull request branch and wait for status checks to finish before trying to merge.

          Using a merge queue is particularly useful on branches that have a relatively high number of pull requests merging each day from many different users.

          Once a pull request has passed all required branch protection checks, a user with write access to the repository can add the pull request to the queue. The merge queue will ensure the pull request's changes pass all required status checks when applied to the latest version of the target branch and any pull requests already in the queue.

          \ud83d\udcda Learn more...

          • Managing a merge queue
          • Merging a pull request with a merge queue

          The previously implemented pull request checks will be executed in isolation. However, to provide assurance of stability on the target branch as different changes are being introduced to it at a fast pace by multiple collaborators, we want to aggregate isolated changes and re-validate them in batches i.e. the Merge Queue.

          Is this like a Daily Build?

          You probably recognize this concept as similar to the implementation of a daily/nightly build. Except you do not have to wait ~ 24 hours or there about to validate your project's quality status.

          Configure Merge Queue

          A Merge Queue is ideal for rolling out continuous integration at scale, enabling larger projects and teams to be optimally productive -- delivering high quality value without compromising product stability.

          You can reserve execution of expensive checks in a merge queue, to save cost and time.

          To effectively leverage Merge Queue, you must first configure your repository to require it for pull requests as follows.

          1. On GitHub.com, navigate to the main page of the repository you have created.
          2. Under your repository name, click Settings. If you cannot see the \"Settings\" tab, select the dropdown menu, then click Settings.
          3. In the \"Code and automation\" section of the sidebar, click Branches.
          4. Next to \"Branch protection rules\", click Add branch protection rule.
          5. Under \"Branch name pattern\", type the branch name main for the branch you want to protect.
          6. Select Require merge queue.
          7. Click Create to complete Merge Queue configuration

          Finally implement the checks in merge queue as follows.

          .github/workflows/continuous.integration.merge.queue.yml
          name: Run Checks on Merge Queue\n\non:\n  merge_group:\n    types: [checks_requested]\n\npermissions:\n  actions: write\n  checks: write\n  contents: read\n  security-events: write\n  pull-requests: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n  TETRIS_APP_HOST: \"127.0.0.1\"\n  TETRIS_APP_PORT: \"8080\"\n  TETRIS_APP_PATH: \"github-devsecops-fundamentals\"\n\njobs:\n  run-acceptance:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n\n      - name: Install Dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.ci.txt\n          npm ci\n          # Install browsers for running functional tests\n          npx playwright install --with-deps chromium\n\n      - name: Build\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n\n      - name: Functional Test\n        run: npx playwright test\n\n      - name: Upload Functional Test Report\n        uses: actions/upload-artifact@v3\n        if: always()\n        with:\n          name: playwright-report\n          path: playwright-report/\n          retention-days: 30\n
          "},{"location":"exercises/01.collaborate/02/#publish-your-changes","title":"Publish your changes","text":"

          You can link your changes to an issue

          Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

          1. Commit and push the changes.

            git checkout -b feature/tetris-game\ngit add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n- Implement continuous integration\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push -u origin feature/tetris-game\n
          2. Create a pull request by clicking on the GitHub icon in the sidebar menu, and then clicking the Create Pull Request icon.

            Check that the local branch and repository you're merging from, and the remote branch and repository you're merging into, are correct. You may leave the pre-filled pull request title and description as they are.

            Click \"Create\", and if prompted then click \"Always\" or \"Publish Branch\".

          3. The pull request you created will be listed at https://github.com/<YOUR-HANDLE>/github-devsecops-fundamentals/pulls.

            Opening the pull request for exploration you should observe the following

            • Conversation

              Particularly enables and summarizes discussions/reviews on your changes with other collaborators and stakeholders. And additionally summarizes outcome of checks on the pull request. - Commits

              Summarizes all the commits contributing to the pull request.

            • Checks

              Lists the checks run on the pull request and their respective outcomes.

            • Files changed

              Shows a diff of files modified and added due to the pull request.

            Note

            Observe the 3 executed checks.

            • 1 failure due to error in site build.
            • 2 code scanning check passes.
          "},{"location":"exercises/01.collaborate/02/#implement-feature-changes","title":"Implement Feature Changes","text":"

          The Build step in the previously implemented automated checks should identify a failure ultimately pointing to incompletion of the expected Tetris game feature. In the current phase, we will take steps to integrate the Tetris game as follows.

          1. Rename the docs/.tetris.game folder to docs/tetris.game, i.e. simply remove the . prefix from the name.
          2. Find and open the file mkdocs.yml in the File Explorer (it's at the root of the file tree)

          3. Confirm that the Tetris Game relevant entry points to an index file in the tetris.game folder

             nav:\n   - Home: index.md\n   - Prerequisites: prerequisites.md\n   - Exercises:\n       - Introduction: exercises/index.md\n       - Collaborate:\n           - exercises/01.collaborate/index.md\n           - exercises/01.collaborate/01.md\n           - exercises/01.collaborate/02.md\n       - Secure the Software Supply Chain:\n           - exercises/02.secure.the.software.supply.chain/index.md\n           - exercises/02.secure.the.software.supply.chain/01.md\n           - exercises/02.secure.the.software.supply.chain/02.md\n       - Automate Release:\n           - exercises/03.automate.release/index.md\n           - exercises/03.automate.release/01.md\n           - exercises/03.automate.release/02.md\n       - \u2728 Recap:\n           - exercises/recap/index.md\n   - Tetris Game: tetris.game/index.html\n
          "},{"location":"exercises/01.collaborate/02/#manual-test","title":"Manual Test","text":"
          1. Observe the local build in the terminal, there should not be any WARNING in the log.
          2. Manually confirm that the Tetris Game integration was effective.
          "},{"location":"exercises/01.collaborate/02/#automated-test","title":"Automated Test","text":"

          Before publishing our new changes, we will implement and execute a functional test to validate the feature implementation.

          1. Open the terminal and install test dependencies.(1)

            1. \ud83d\udca1 You can create additional terminal session by clicking at the top right side of the TERMINAL panel.
            # Install Node.js\nnvm install --lts #(1)!\n# Install packages required for running the functional UI test\nnpm install\n# Install the browser(s) against which the functional UI test should run\nnpx playwright install --with-deps chromium #(2)!\n
            1. A codespace environment can be customized as needed. In this case, we customized the running session by installing the latest version of Node.js.
            2. This command installs browsers required for the functional test. Please be patient, it may take 1 to 2 minutes to complete the installation.

            Then implement the functional test as follows.

            tests/tetris.spec.js
            import { test, expect } from \"@playwright/test\";\n\ntest(\"Tetris Game\", async ({ page }) => {\n  const { TETRIS_APP_HOST, TETRIS_APP_PORT, TETRIS_APP_PATH } = process.env;\n\n  // should be similar to http://127.0.0.1:8080/github-devsecops-fundamentals/\n  console.log(\n    `http://${TETRIS_APP_HOST}:${TETRIS_APP_PORT}/${TETRIS_APP_PATH}`\n  );\n  await page.goto(\n    `http://${TETRIS_APP_HOST}:${TETRIS_APP_PORT}/${TETRIS_APP_PATH}`\n  );\n\n  await page.getByRole(\"link\", { name: \"Tetris Game\" }).click();\n  await expect(page.getByText(\"score 00000\")).toBeVisible();\n  await expect(page.getByText(\"rows 0\")).toBeVisible();\n  await expect(page.locator(\"#upcoming\")).toBeVisible();\n  await expect(\n    page.getByRole(\"link\", { name: \"Press Space to Play.\" })\n  ).toBeVisible();\n\n  await page.getByRole(\"link\", { name: \"Press Space to Play.\" }).click();\n  await expect(page.getByText(\"score 00000\")).not.toBeVisible({\n    timeout: 0.5 * 60 * 1000,\n  });\n});\n

            Finally execute the automated test.

            npx playwright test\n

            When everything has been done right, the test should pass.

          2. Commit the changes to the current feature/tetris-game branch and publish it for a review.

            You can link your changes to an issue

            Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

            git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Integrate Tetris game implementation\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin\n

            Observe that all checks have passed.

          "},{"location":"exercises/01.collaborate/02/#resources","title":"\ud83d\udcda Resources","text":"
          • Creating a GitHub Pages site
          • Introduction to dev containers
          • Workflow syntax for GitHub Actions
          • Events that trigger workflows
          • Finding and customizing actions
          • Code scanning
          • Security hardening for GitHub Actions
          "},{"location":"exercises/02.secure.the.software.supply.chain/","title":"Secure the Software Supply Chain","text":"

          Continuous Delivery and Secure Supply Chain

          Supply chain security is integral to continuous delivery. With the accelerated use of open source, most projects depend on hundreds of open-source dependencies. This poses a security problem: what if the dependencies you're using are vulnerable? You could be putting your users at risk of a supply chain attack. One of the most important things you can do to protect your supply chain is to patch your vulnerable dependencies and replace any malware.

          Building on the progress from previous exercises, we will apply supply chain security and continuously deliver the product by fulfilling the following objectives.

          "},{"location":"exercises/02.secure.the.software.supply.chain/#objectives","title":"Objectives","text":"
          • Create Integration Checks for the Tetris app using GitHub Actions.
          • Create a Continuous Delivery workflow for the Tetris app using GitHub Actions.
          • Create a new release tag for the Tetris app using GitHub Actions.
          • Create a Compliance using CodeQL, Dependency Review, and Dependabot.
          "},{"location":"exercises/02.secure.the.software.supply.chain/01/","title":"Dependency Review","text":"

          Add Security Checks

          Dependency review helps you understand dependency changes and the security impact of these changes at every pull request. It provides an easily understandable visualization of dependency changes with a rich diff on the \"Files Changed\" tab of a pull request. Dependency review informs you of:

          • Which dependencies were added, removed, or updated, along with the release dates.
          • How many projects use these components.
          • Vulnerability data for these dependencies.

          "},{"location":"exercises/02.secure.the.software.supply.chain/01/#exercise-automate-enforcement-of-dependency-review","title":"Exercise: Automate Enforcement of Dependency Review","text":""},{"location":"exercises/02.secure.the.software.supply.chain/01/#understand-the-dependency-review-configurations","title":"Understand the Dependency Review Configurations","text":".github/dependency-review-config.yml
          fail-on-severity: moderate #(1)!\n\ncomment-summary-in-pr: always #(2)!\n\nallow-licenses: #(3)!\n  - MIT\n  - GPL-3.0\n  - BSD-3-Clause\n\ndeny-licenses: #(4)!\n  - LGPL-2.0\n  - BSD-2-Clause\n\nallow-ghsas: #(5)!\n  - GHSA-abcd-1234-5679\n  - GHSA-efgh-1234-5679\n\nfail-on-scopes: #(6)!\n  - development\n  - runtime\n  - unknown\n
          1. Possible values: \"critical\", \"high\", \"moderate\", \"low\"
          2. Post summary as a comment to respective pull request
          3. Only allow the listed licenses (optional). Possible values: Any spdx_id value(s) from https://docs.github.com/en/rest/licenses
          4. Block the pull request on these licenses (optional). Possible values: Any spdx_id value(s) from https://docs.github.com/en/rest/licenses

            You can only include one of either of these two options: allow-licenses and deny-licenses.

          5. Skip these GitHub Advisory Database IDs during detection (optional). Possible values: Any valid GitHub Advisory Database ID from https://github.com/advisories

          6. Block pull requests that introduce vulnerabilities in the scopes that match this list (optional). Possible values: \"development\", \"runtime\", \"unknown\"
          "},{"location":"exercises/02.secure.the.software.supply.chain/01/#implement-dependency-review-check","title":"Implement Dependency Review Check","text":"

          Open the .github/workflows/continuous.integration.yml file in the editor and add the highlighted content as follows:

          .github/workflows/continuous.integration.yml
          name: Run Checks on PR\n\non:\n  pull_request:\n    branches:\n      - main\n\npermissions:\n  actions: write\n  checks: write\n  contents: read\n  security-events: write\n  pull-requests: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n  TETRIS_APP_HOST: \"127.0.0.1\"\n  TETRIS_APP_PORT: \"8080\"\n  TETRIS_APP_PATH: \"github-devsecops-fundamentals\"\n\njobs:\n  quality-checks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - uses: actions/setup-node@v3\n        with:\n          node-version: 20\n\n      - name: Install Dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.ci.txt\n          npm ci\n          # Install browsers for running functional tests\n          npx playwright install --with-deps chromium\n\n      - name: Build\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n\n      - name: Functional Test\n        run: npx playwright test\n\n      - name: Upload Functional Test Report\n        uses: actions/upload-artifact@v3\n        if: always()\n        with:\n          name: playwright-report\n          path: playwright-report/\n          retention-days: 30\n\n  security-checks:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Dependency Review\n        uses: actions/dependency-review-action@v3\n        with:\n          config-file: >-\n            ./.github/dependency-review-config.yml\n
          "},{"location":"exercises/02.secure.the.software.supply.chain/01/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

          Pushing your changes will apply the check on the existing pull request.

          You can link your changes to an issue

          Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

          git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Add dependency review as a security check\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n

          When you navigate to the repository on GitHub and open the existing pull request, you can confirm that the check was executed. As there are no compliance violations currently in the PR, the check is successful.

          Homework

          Can you attempt to make the dependency review check to fail?

          "},{"location":"exercises/02.secure.the.software.supply.chain/01/#resources","title":"\ud83d\udcda Resources","text":"
          • Understanding your software supply chain
          • GitHub Advanced Security - Dependency Graph
          "},{"location":"exercises/02.secure.the.software.supply.chain/02/","title":"Versioning","text":"

          Motivation for Versions

          A pull request represents a single aggregation of multiple significant changes (i.e. commits). When collaborating at scale in a large team or project, pull requests targeting the default (production) branch can be further buffered through a merge queue for further validation. In either cases, it is imperative to keep track of the aggregated changes introduced into the default branch which serves as the basic source of production releases.

          Some versions may eventually be released whereas others are not. Moreover, a released version may be rolled back to an earlier release as business decisions evolve.

          "},{"location":"exercises/02.secure.the.software.supply.chain/02/#exercise-version-changes-added-to-the-main-branch","title":"Exercise: Version Changes Added to the Main Branch","text":"

          Semantic Versioning, semver is a scheme that conveys meaning about the underlying code and what has been modified from one version to the next.

          semver version 2.0.0 is officially summarized as follows.

          Given a version number MAJOR.MINOR.PATCH, increment the:

          1. MAJOR version when you make incompatible API changes
          2. MINOR version when you add functionality in a backward compatible manner
          3. PATCH version when you make backward compatible bug fixes

          Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

          At this fundamentals phase of DevSecOps implementation, we will apply the semver scheme and automate patch increment. There are conventions that can be adopted to equally automate increment in MAJOR and MINOR versions, but for simplicity our intended implementation assumes the understanding that MAJOR and MINOR version bumps will be manually initiated.

          "},{"location":"exercises/02.secure.the.software.supply.chain/02/#implement-patch-versioning","title":"Implement PATCH Versioning","text":"

          In the file explorer, create a new workflow .github/workflows/continuous.versioning.yml as follows.

          .github/workflows/continuous.versioning.yml
          name: Version Changes to the Main Branch\n\non:\n  push:\n    branches:\n      - main\n  workflow_dispatch: {}\n\njobs:\n  version-main-branch-changes:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/create-github-app-token@v1\n        id: generate-app-token\n        with:\n          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}\n          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}\n\n      - name: Checkout\n        uses: actions/checkout@v3\n        with:\n          fetch-depth: 0\n          token: ${{ steps.generate-app-token.outputs.token }}\n\n      - name: Get last version number\n        id: get_last_version\n        run: |\n          # Retrieve the last git tag, as we will only be processing one delivery line.\n          last_version=$(git describe --tags --abbrev=0 2>/dev/null || echo \"0.0.0\")\n          echo \"Last version is $last_version\"\n          echo \"last_version=$last_version\" >> \"$GITHUB_OUTPUT\"\n\n      - name: Get new version number\n        id: get_new_version\n        run: |\n          major=$(echo $last_version | cut -d. -f1)\n          minor=$(echo $last_version | cut -d. -f2)\n          patch=$(echo $last_version | cut -d. -f3)\n\n          new_patch=$((patch+1))\n\n          new_version=\"$major.$minor.$new_patch\"\n\n          echo \"New version is $new_version\"\n          echo \"new_version=$new_version\" >> \"$GITHUB_OUTPUT\"\n        env:\n          last_version: ${{ steps.get_last_version.outputs.last_version }}\n\n      - name: Create tag for the new version\n        run: |\n          git config --global user.name \"${GITHUB_ACTOR}\"\n          git config --global user.email \"${GITHUB_ACTOR}@users.noreply.github.com\"\n\n          if git tag -a \"$new_version\" -m \"Version $new_version\"; then\n            git push --follow-tags origin \"$new_version\"\n          else\n            echo \"Failed to create tag $new_version, it probably already exists\"\n          fi\n        env:\n          new_version: ${{ steps.get_new_version.outputs.new_version }}-release\n
          "},{"location":"exercises/02.secure.the.software.supply.chain/02/#analysis","title":"Analysis","text":"
          • Lines 4 - 6

            We are introduced to a new event that encapsulates the activity of pushing to particular branches, specifically the main branch alone in this implementation.

          • Lines 13 - 17

            A GitHub App will be used as the actor for the operations we shall be executing. Hence the actions/create-github-app-token@v1 action is used here to generate an authorization token for the app.

            What is a GitHub App?

            GitHub Apps, much like service accounts and bots, are tools that extend GitHub's functionality. You can build a GitHub App to provide flexibility and reduce friction in your processes, without needing to sign in a user or create a service account . GitHub Apps can do things on GitHub like open issues, comment on pull requests, and manage projects. They can also do things outside of GitHub based on events that happen on GitHub. For example, a GitHub App can post on Slack when an issue is opened on GitHub.

            The GitHub App actor will later be used to checkout the repository's source code and to push tags.

          • Lines 25 - 31

            The step Get last version number computes the last version and writes it to the step output named last_version.

          • Lines 33 - 47

            The step Get new version number uses reads the output from the previous step by the expression ${{ steps.get_last_version.outputs.last_version }}, and use it to compute the patch increment.

          • Lines 49 - 60

            The step Create tag for the new version creates a new git tag for release. A tag identifies specific points in a repository\u2019s history as being important. Here, the tag is being used to mark a release point.

            Because a persisted app token exists and will be used in the tag push, we can be confident that the push will effectively trigger other relevant automation. On the other hand, if the default GITHUB_TOKEN was used it would not trigger a workflow as GitHub Actions rightly guard against unintentional recursive triggering of workflows .

          "},{"location":"exercises/02.secure.the.software.supply.chain/02/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

          You can link your changes to an issue

          Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

          git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Implement automatic patch versioning\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n
          "},{"location":"exercises/02.secure.the.software.supply.chain/02/#resources","title":"\ud83d\udcda Resources","text":"
          • Semantic Versioning 2.0.0
          "},{"location":"exercises/03.automate.release/","title":"Automate Deployment of Releases","text":"

          Continuous Deployment

          Continuous deployment (CD) is the practice of using automation to publish and deploy software updates. As part of the typical CD process, the code is automatically built and tested before deployment.

          Continuous deployment is often coupled with continuous integration which we have seen earlier. Building on the progress from previous exercises, we will apply continuous deployment mindset by fulfilling the following objectives.

          "},{"location":"exercises/03.automate.release/#objectives","title":"Objectives","text":"
          • Validate releases
          • Execute production deployments on successful validation of respective releases
          "},{"location":"exercises/03.automate.release/01/","title":"Release Version","text":"

          Release

          As streams of changes make it into the production branch and are versioned in batches, an essential part of continuous delivery/deployment is to produce artifacts from versions which can then be deployed to various targets.

          Releases are deployable software iterations you can package and make available for a wider audience to download and use.

          How do we determine when to create a release? Let's see...

          "},{"location":"exercises/03.automate.release/01/#exercise-create-a-release-of-versions","title":"Exercise: Create a Release of Versions","text":"

          As you can guess already, GitHub provides an event that encapsulates the activity of creating a tag and pushing it to a repository. We will automate addressing such events, so that we can create a release when necessary.

          "},{"location":"exercises/03.automate.release/01/#implement-release-creation","title":"Implement Release Creation","text":"

          In the file explorer, create a new workflow .github/workflows/continuous.delivery.yml as follows.

          .github/workflows/continuous.delivery.yml
          name: Package Delivery Artifacts & Create Release\n\non:\n  push:\n    tags:\n      - \"*-release\"\n\npermissions:\n  contents: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n\njobs:\n  package-delivery:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - uses: actions/setup-python@v4\n        with:\n          python-version: 3.12\n      - name: Install Python dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.txt\n      - name: Build Site\n        run: |\n          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'\n      - name: Archive Site\n        run: |\n          zip -r ${{ env.SITE_DIR }}.zip ${{ env.SITE_DIR }}\n      - run: |\n          echo \"Site directory ${{ env.SITE_DIR }} content:\"\n          ls -al ${{ env.SITE_DIR }}\n\n      - uses: actions/create-github-app-token@v1\n        id: generate-app-token\n        with:\n          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}\n          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}\n\n      - name: Draft release\n        uses: actions/github-script@v6\n        id: draft-release\n        with:\n          github-token: ${{ steps.generate-app-token.outputs.token }}\n          script: |\n\n            const response = await github.request(\n              'POST /repos/{owner}/{repo}/releases',\n              {\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                draft: true,\n                tag_name: '${{ github.ref }}',\n                discussion_category_name: 'announcements',\n                generate_release_notes: true,\n                make_latest: 'legacy',\n                headers: {\n                  'X-GitHub-Api-Version': '2022-11-28'\n                }\n              }\n            );\n\n            console.dir(response);\n\n            return response.data.id;\n\n      - name: Upload release asset\n        run: |\n          curl -L \\\n            -X POST \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"Authorization: Bearer ${{ steps.generate-app-token.outputs.token }}\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            -H \"Content-Type: application/octet-stream\" \\\n            \"https://uploads.github.com/repos/${{ github.repository }}/releases/${{ steps.draft-release.outputs.result }}/assets?name=${{ env.SITE_DIR }}.zip\" \\\n            --data-binary \"@${{ env.SITE_DIR }}.zip\"\n\n      - name: Publish release\n        uses: actions/github-script@v6\n        id: publish-release\n        with:\n          github-token: ${{ steps.generate-app-token.outputs.token }}\n          script: |\n\n            const response = await github.request(\n              'PATCH /repos/{owner}/{repo}/releases/{release_id}',\n              {\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                release_id: ${{ steps.draft-release.outputs.result }},\n                draft: false,\n                discussion_category_name: 'announcements',\n                make_latest: 'true',\n                headers: {\n                  'X-GitHub-Api-Version': '2022-11-28'\n                }\n              }\n            );\n\n            console.dir(response);\n
          "},{"location":"exercises/03.automate.release/01/#analysis","title":"Analysis","text":"
          • Lines 3 - 6

            The release creation workflow will be triggered by tag pushes and when the pushed tag version is suffixed with the -release metadata.

          • Lines 29 - 34

            In the two steps included here, the site is built and archived as a release artifact.

          • Lines 39 - 43

            A GitHub App will be used as the actor for the operations we shall be executing. Hence the actions/create-github-app-token@v1 action is used here to generate an authorization token for the app.

            What is a GitHub App?

            GitHub Apps, much like service accounts and bots, are tools that extend GitHub's functionality. You can build a GitHub App to provide flexibility and reduce friction in your processes, without needing to sign in a user or create a service account . GitHub Apps can do things on GitHub like open issues, comment on pull requests, and manage projects. They can also do things outside of GitHub based on events that happen on GitHub. For example, a GitHub App can post on Slack when an issue is opened on GitHub.

            When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.

            ~ Using the GITHUB_TOKEN in a workflow

            So, we are authorizing operations as a GitHub App to enable the execution of the operation to further trigger other workflow flow runs, possibly.

          • Lines 45 - 70

            A draft release is created by the respective step, allowing for modification of the release before publishing it. The release references the tag that had triggered the workflow.

          • Lines 72 - 81

            This step leverages GitHub's ReST API to adjust the previously created draft release, specifically adding the archive created in the Archive Site step to the release as an asset.

          • Lines 83 - 105

            Having drafted the release and attached deployable assets to it, the Publish release step ultimately publishes the release by flipping the state of it draft attribute to false.

          "},{"location":"exercises/03.automate.release/01/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

          You can link your changes to an issue

          Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

          git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Implement release automation\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n
          "},{"location":"exercises/03.automate.release/01/#resources","title":"\ud83d\udcda Resources","text":"
          • GitHub Apps documentation
          • GitHub REST API documentation
          • GitHub Packages
          "},{"location":"exercises/03.automate.release/02/","title":"Continuous Deployment","text":"

          Deliver high quality value at speed

          Continuous deployment (CD) is the practice of using automation to publish and deploy software updates.

          To ultimately fulfill our goal on complete development of the feature, we altogether apply the practice of continuous deployment to validate and ship the value to our customers at high velocity.

          "},{"location":"exercises/03.automate.release/02/#exercise-automate-deployment-of-releases","title":"Exercise: Automate Deployment of Releases","text":"

          The previous exercise walked us through automating the publication of release. We will continue to build upon that milestone to automate deployment of published releases.

          "},{"location":"exercises/03.automate.release/02/#implement-deployment-workflow","title":"Implement Deployment Workflow","text":"

          In the file explorer, create a new workflow .github/workflows/continuous.deployment.yml as follows.

          .github/workflows/continuous.deployment.yml
          name: Deploy Release\n\non:\n  release:\n    types:\n      - released\n\nconcurrency:\n  group: github-pages\n  cancel-in-progress: false\n\npermissions:\n  contents: write\n  deployments: write\n  pages: write\n  id-token: write\n\nenv:\n  CI: true\n  SITE_DIR: site\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n\n    steps:\n      - uses: actions/create-github-app-token@v1\n        id: generate-app-token\n        with:\n          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}\n          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}\n\n      - name: Setup Pages\n        uses: actions/configure-pages@v3\n        with:\n          enablement: \"true\"\n          token: \"${{ steps.generate-app-token.outputs.token }}\"\n\n      - name: Download release asset\n        id: download-release-asset\n        run: |\n          cat << 'EOF' > event.json\n          ${{ toJson(github.event) }}\n          EOF\n          asset_id=$(cat event.json | jq '.release.assets[] | select(.name == \"${{ env.SITE_DIR }}.zip\") | .id')\n\n          curl --location --output '${{ env.SITE_DIR }}.zip'                          \\\n            -H \"Accept: application/octet-stream\"                                     \\\n            -H \"Authorization: Bearer ${{ steps.generate-app-token.outputs.token }}\"  \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\"                                     \\\n            \"https://api.github.com/repos/${{ github.repository }}/releases/assets/${asset_id}\"\n\n          unzip -o \"${{ env.SITE_DIR }}.zip\" -d .\n\n          echo '##### Debug'\n          ls -al \"${{ env.SITE_DIR }}\"\n\n      - name: Fix site file permissions\n        run: |\n          chmod -c -R +rX \"${{ env.SITE_DIR }}/\" | while read line; do\n            echo \"::warning title=Invalid file permissions automatically fixed::$line\"\n          done\n\n      - name: Upload Pages artifact\n        uses: actions/upload-pages-artifact@v2\n        with:\n          path: \"${{ env.SITE_DIR }}\"\n          retention-days: \"2\"\n\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v2\n        with:\n          token: ${{ steps.generate-app-token.outputs.token }}\n
          "},{"location":"exercises/03.automate.release/02/#analysis","title":"Analysis","text":"
          • Lines 3 - 6

            Deployments will be triggered in the event of a release publication.

          • Lines 8 - 10

            Ensure that only a single job or workflow using the same concurrency group will run at a time.

            When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. Any previously pending job or workflow in the concurrency group will be canceled. If you do not wish to also cancel any currently running job or workflow in the same concurrency group, specify cancel-in-progress: false.

          • Lines 25 - 27

            This will cause the URL of the deployed site to be displayed where the workflow is executed.

          • Lines 36 - 40

            This step enables GitHub Pages and extracts various metadata about a site. It can also be used to configure various static site generators we support as starter workflows.

          • Lines 42 - 65

            Download assets associated with the release publication that triggered this workflow, and where necessary, adjust permissions for the files in the assets.

          • Lines 67 - 71

            Upload the site artifacts to the storage location where it should be ultimately collected by the next step for deployment.

          • Lines 73 - 77

            This step deploys the site.

          "},{"location":"exercises/03.automate.release/02/#commit-and-publish-your-changes","title":"Commit and publish your changes","text":"

          You can link your changes to an issue

          Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

          git add .\ngit commit -m \"$(printf 'Create a tetris game to drive site engagement\\n\\n-Implement continuous deployment\\n\\n- Resolves #<ISSUE-NUMBER>')\"\ngit push origin feature/tetris-game\n
          "},{"location":"exercises/03.automate.release/02/#merge-your-open-pull-request","title":"Merge your open pull request","text":"
          • On the pull request page, open the drop-down from the Merge pull request button to choose the Rebase and merge option.

          • Then press the Rebase and merge button to merge your pull request.

          • Finally, press Confirm rebase and merge.

          When you merge the open pull request, you should make the following observations.

          Collaboration

          • The linked issue in your project board automatically gets closed and moved to the \u2705 Done column of the board.

          Automation

          When you head over to the Actions tab on your repository, and notice...

          • The Version Changes to the Main Branch workflow is executed.
          • The Package Delivery Artifacts & Create Release workflow is executed.

            Consequently the release is announced in Discussions.

          • The Deploy Release workflow is executed.

            And on successful completion of the workflow, the public URL to your site is displayed on the job.

          Stakeholder Enablement

          Stakeholders can easily explore deployments of the project.

          • Deployments summary on repository home.

          • Detailed deployment environments list.

          "},{"location":"exercises/03.automate.release/02/#resources","title":"\ud83d\udcda Resources","text":"
          • Using environments for deployment
          • Creating custom deployment protection rules
          • Security harden deployments with OpenID Connect
          "},{"location":"exercises/recap/","title":"Review of Workshop Outcomes","text":"

          So far, we have reached the following milestones, learning to

          • Track work on GitHub
          • Rapidly onboard onto an existing project
          • Work in a collaborative manner, and enable quick incorporation of feedbacks
          • Efficiently secure the software supply chain, catching vulnerabilities and non-compliant dependencies as they are introduced
          • Automate versioning
          • Automate releases
          • Implement continuous deployment
          "}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index b9564be2800cf66f43ee412a974645201c400cbb..2f84db7249433decfbb58a4775fc43549e433d1d 100644 GIT binary patch delta 15 WcmX@cbc~5jzMF$XFmEH910w(;p##VO delta 15 WcmX@cbc~5jzMF$%Ue-o72SxxT+XPVn