Practical: Deploying a Next Application

Initial Due Date: 2024-10-15 11:59PM Final Due Date: 2024-10-25 4:00PM

Github Classroom Gradescope
Today you will add a feature to the color picker to enable the user to enter the color component by number. As part of that process we will practice testing, CI and automated deployment. Check out a deployed version of the final result.
Learning Goals:
  • Practice integration via GitHub pull request (PR)
  • Use a CI server (Github Actions) to test a PR before integration
  • Deploy an application to a PaaS (csci312.dev)
Submission: Successfully submitting your assignment is an ordered two-step process:
  1. Commit and push your changes to GitHub
  2. Submit your repository to the Gradescope assignment

Prerequisites

  1. Create the git repository for your practical by accepting the assignment from GitHub Classroom. This will create a new repository for you with a skeleton application already setup for you.
  2. Clone the repository to you computer with 💻 git clone (get the name of the repository from GitHub).
  3. Open up the package.json file and add your name as the author of the package.
  4. Install the module dependencies by executing 💻 npm install in the terminal.

Add CI with Github Actions

Before you make any changes, create a feature branch named “editable-number” to isolate your modifications from the main branch:

💻 git checkout -b editable-number

This should be the new default action that you take when working on your code to get you in the habit. When you start a feature, create a corresponding feature branch. Work until it is stable and only then merge it into the main branch.

Create the CI config file

GitHub actions allow us to execute a wide variety of actions in response to git events. If you are looking at the repository on Github, you will see there is an Actions tab, which will allow you to add a number of different actions designed by GitHub and the community. However, all these do is create a special configuration file in your repository, so we will do that directly.

At the top level of your package directory, you should have a .github directory with a workflows directory inside (if not, you should create them). Inside of workflows, create a new file called node.js.yml, i.e., .github/workflows/node.js.yml (the important part of the file name is the .yml on the end, but use the full name) with the contents shown below.

YAML (pronounced like “camel”) is a popular file format for text-based configuration files. It won’t be important to understand all of its ins and outs, for now the key thing to know is that like Python, indentation matters.

name: Node.js CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Use Node.js 20.x
      uses: actions/setup-node@v3
      with:
        node-version: 20.x
        cache: 'npm'
    - run: npm ci
    - run: npm test
    - run: npm run build

There are two main sections here: on and jobs. The on section tells GitHub Actions when to execute this action (when we push to main or make a PR to main). The jobs section describes the steps to carry out. In this case, it

  1. Checks out our code into a linux virtual machine
  2. Installs node version 20.x
  3. Runs npm ci, which uses the package-lock.json file to install all of the dependencies
  4. Runs npm test
  5. Runs npm run build to ensure a production version of your application will build

If any of the commands fail, e.g., there are testing errors, GitHub actions will report the errors so we know we need to fix the pull request.

Add a status badge to your README.md

As you browse different repositories on GitHub, you may have seen flashy status badges in the README files that indicate that the tests are passing (or not). You can add one to your project as well.

As described in the documentation, the URL of the image is:

https://github.com/<OWNER>/<REPOSITORY>/actions/workflows/<WORKFLOW_FILE>/badge.svg

We need to put this into Markdown syntax to add an image. So for example, I might add the following line to the README.md to render the image. Do so in your README.md, but change the URL to point to your repository.

![workflow status](https://github.com/csci312-s24/practical06-devops-lbiester/actions/workflows/node.js.yml/badge.svg)

Create a PR

Let’s commit this change and push it to GitHub:

💻 git add .
💻 git commit -m "Add actions config file"
💻 git push -u origin editable-number

The last command tells git to find the local branch named editable-number and push its contents to a branch named editable-number in the remote origin repository. Recall that origin is the name automatically given to the repository we cloned from (on GitHub in this case).

Visit the repository on GitHub (reloading the page, if needed). There should be a yellow banner across the top notifying you of a change to a branch and asking if you would like to “Compare & pull request”. Do so. If you don’t see the banner, you can always create a new PR from the ‘Pull requests’ tab.

On the new page that comes up you will see a form for starting the PR. Type in a message and click the button to create the PR.

You will see a message that it is OK to merge with main. This is unsurprising since no one has done anything to main since you made a branch, so the merge just involved adding the changes in this branch on top of main. If you wait a moment (you may also need to reload), however, you will see a new message appear as GitHub Actions kicks off. Give it a moment to run, and then it should come back and tell you that the checks have failed. This is also unsurprising since you haven’t changed the code yet. If you click on Details you can see the run log and the output from running the tests.

Enhancing the color picker with controllable number

Now let’s make our change the the ColorPicker. Start the development server (💻 npm run dev) so you can see the effects of your changes. You should see the familiar ColorPicker appear in the web view. You can also run the tests with 💻 npm test, and they should fail.

You are now ready to make the changes to the LabeledSlider in src/pages/index.js. Remove the current span which reports the value (<span>{value}</span>) and replace it with a number input element. The numerical input will be very similar to its slider counterpart. Its value should be controlled by the React state (so that all the elements that depend on or modify that value remain in sync), it should update the color component as specified, and have appropriate min and max values. The differences are it will be of type “number” and it will have an appropriate data-testid, e.g.,

data-testid={`${label}_number`}

You should now see your new inputs at the end of the sliders, and the tests should all pass.

Revisit the PR

Now that you have working code, add, commit and push it on the same feature branch you have been working on, e.g., 💻 git push origin editable-number

Return to the PR page on GitHub. You should see your new commit added to the PR and after a moment you should see the action kick off again. This time you should get a message that “All checks have passed”. If not, make sure that the tests were passing locally and that the new code has actually been pushed to the branch.

Click the “Merge pull request” button. it should give you a chance to add a message to the merge and then you can click “Confirm merge”. After the merge is complete, it will give you a “Delete branch” button. Click it to remove the feature branch from GitHub.

Clean up your local repository after the merge

Return to your terminal and switch back to the “main” branch (💻 git checkout main). You now want to pull the changes from GitHub, pruning to delete remote tracking references (💻 git pull --prune) and then delete your local branch (💻 git branch -d editable-number).

To avoid mistakes when deleting branches, you can add the --dry-run option to the pull --prune command , e.g. 💻 git pull --prune --dry-run to double check before actually pruning anything (note you will still need to run the actual command when you are sure it correct).

The full command sequence is:

💻 git checkout main
💻 git pull --prune
💻 git branch -d editable-number

Deploy to csci312.dev

To support deployment without requiring you to enter a credit card or running into limits on team sizes, etc. we have our own simple cloud deployment platform csci312.dev. Similar to Heroku or fly.io, you will push your code to a deployment repository at csci312.dev, which will then build and deploy your application at https://<project name>.csci312.dev.

Before you deploy, I encourage you to test the production version of your application locally. You can do so with:

💻 npm run build
💻 npm run start

This will build the production version of your application and start it the same way the server will (e.g., setting the production environment). If this doesn’t work locally, it is unlikely to work remotely!

  1. As a prerequisite, you should have added an SSH key to GitHub as described in the getting started instructions. Doing so is necessary to obtain deploy permissions. If you have not created a key yet, or if you attempt the below and get permission-related errors, contact the instructor to make sure your key has been added to the deployment server.
  2. Add the deployment repository as a remote in your repository with the name deploy: 💻 git remote add deploy git@csci312.dev:<midd username>-practical06 replace <midd username> with your Middlebury username, e.g., 💻 git remote add deploy git@csci312.dev:lbiester-practical06. Note that the name matters, it must be your Middlebury username followed by “-practical06”.
  3. Push the main branch to the deploy repository: 💻 git push deploy main. This should automatically build and deploy your application at https://<midd username>-practical06.csci312.dev. Note that the push will not complete until the application deploys, so it will take a minute or so. Any errors should (hopefully) be reported in the terminal as the push proceeds.
  4. To view the most recent logs from your application execute 💻 ssh git@csci312.dev logs <midd username>-practical06. You can optionally add a --lines argument, e.g., --line 50 to look at more lines.
  5. If you need to make a change or want to update your application, merge new commits into the main branch and push them to the deploy remote as you did above. That will re-deploy your application automatically.

When the deployment completes successfully, open https://<midd username>-practical06.csci312.dev in the browser, e.g., https://lbiester-practical06.csci312.dev, to see your application live! Note that these sites are visible to anyone (i.e., you can send your awesome color picker to friends, family or anyone you want impress😀).

csci312.dev caveats

There are some more features of this platform that we will use when we deploy our projects. For that process, we will follow these similar, but more detailed, instructions.

⚠️ This platform is home-rolled, and while adequate for the needs of 5 concurrent projects, I am not sure it will hold up to 30 simultaneous deployments. We will see how it goes…

Finishing up

Commit any additional changes you may have made and then push your changes to GitHub. You should then submit your repository to Gradescope.

Grading

Required functionality:

  • Numeric input for ColorPicker
  • GitHub actions
  • Feature branch workflow
  • Pass all tests
  • Pass all ESLint checks
  • Deployed to csci312.dev

Unlike other practicals, this practical requires some manual checking to verify your deployment and github actions setup. We will complete these manual checks if you have earned 2/2 on the automated tests on gradescope.

Recall that the Practical exercises are evaluated as “Satisfactory/Not yet satisfactory”. Your submission will need to implement all of the required functionality to be Satisfactory.


© Laura Biester, Michael Linderman, and Christopher Andrews 2019-2024.