Due Tuesday Sep 5th at midnight (Late submission are allowed, but there will be a penality of -10 points.)
This assignment is the first step towards building a functional backend for the final project - building a receipt storage and indexing service. The goal of this assignment is to familiarize you with REST architecture, the CircleCI Continuous Integration tool, and the mechanism by which one can deploy software to the cloud.
We will not worry about session management and access control---an user can read / write any receipt. We will not worry about setting up an external database - we will use H2 (which supports the MySQL SQL Dialect).
To complete the assignment you must complete the following:
- Configure CircleCI to run on the
master
branch in your repo - Add a CircleCI build-status badge to README.md
- Build a RESTful API that supports operations on
receipts
andtags
- Deploy the API to AWS
- Submit
CircleCI is a cloud-based tool for building software. CircleCI seamlessly integrates with
GitHub to detect when a change is made, at which point CircleCI will execute a series of build-steps that are
defined in the file .circleci/config.yml
which must be added to your GitHub repository.
When you initially log into CircleCI you should see a Dashboard showing recent builds.
A Projects menu-option on the left-hand side will help you configure your repo. Choose
Add Project, select the repository you want to setup by clicking Setup Project next to your repository name, and
finally select the OS (linux), Platform (2.0) and Language (Gradle/Java).
Circle will reward your efforts here by preparing a sample config.yml
along with detailed instructions you should
follow carefully to get your CI system setup. The sample config.yml
will work without modification, however you
should not be afraid to dive into the excellent CircleCI Docs to add custom
build steps such as building a docker-image.
Once CircleCI is setup, every time you push changes to GitHub CircleCI will detect the change and will follow the steps
defined in config.yml
. By should always include checking out the new code and running the tests. build.gradle
in the skeleton
repo is already setup to run any tests that are annotated with @Test
. You can check this yourself
by running the test
target e.g. ./gradlew test
.
Important - adding your build status badge to README.md
in the class GitHub is the only way to get credit for
setting up CircleCI. You can get the code for your badge by copying it from the Status Badges section of the
Settings page for your project in CircleCI.
To get credit for the assignment you must add the badge as a suffix to your line in the Students section
of the README.md
, you must write at least one non-trivial test, and CircleCI must run the test + pass.
A working test is available in the skeleton
project at src/test/java/api/CreateReceiptRequestTest.java
The API we are building is relatively simple, and only supports operations on two
resources: receipts
and tags
. The basic idea is that one should be able to create new
receipts, categorize them by using user-defined tags, and retrieve receipts by-tag.
Endpoints required to support this functionality with inputs and outputs are summarized below. All endpoints must
return 200/OK
if the operation completed successfully.
Effect: Create a new receipt. Every receipt should have an UNSIGNED INT
primary key which
is returned by this endpoint. No duplicate detection or uniqueness constraints are required. New
receipts are un-tagged.
Request Body:
{
"merchant": "foo", /* required! */
"amount": 22.45 /* optional, must be valid decimal if provided */
}
Response:
33 /* <-- this is the id of the newly-created un-tagged receipt */
Effect: Return a list of all receipts in the system.
Request Body: None
Response:
[
{
"id": 5,
"merchant": "Gerry's Ice Cream",
"amount": 22.50
},
{
"id": 3,
"merchant": "Starbux"
}
]
Effect: Categorize a receipt by tagging it. Tags are simple short character strings that are user-defined, (not pre-defined). To associate a receipt with two tags, this endpoint would need to be executed twice - once for each tag. If a receipt is already tagged with a specific tag (say "t1"), the effect of hitting this endpoint (for "t1") will be to un-tag the receipt for the specific tag, but no other tags will be affected.
Request Body
35 /* <-- this is the id of the receipt to tag / untag */
Response
None / no response is required from the server beyond a 200/OK HTTP Response code. To do this using
the JAX-RS
framework, simply declare your endpoint function to return void
. e.g.
@PUT
@Path("/tags/{tag}")
public void toggleTag(@PathParam("tag") String tagName) {
// <your code here
}
Effect: Returns a list of all receipts associated with a tag, an empty list if there are none.
Request Body: None
Response:
[
{
"id": 39,
"merchant": "Coin-Op Laundromat",
"amount": 2.50
}
]
Effect: Returns your netid as a string for grading purposes.
Request Body: None
Response:
af494
You need to build a Docker image containing your compiled application code plus any dependencies. The beauty of Docker is that you can run this image locally to verify it is functioning correctly, and when you deploy it to the cloud it should work in exactly the same way. Beauty is not without pain however:
- To build an image you must have docker installed and you need to
construct a working
Dockerfile
. A working example will be made available in theskeleton
repo shortly. - Once the image is built you must upload the image to a Docker Repository so that AWS can find and pull the image.
Essentially you only need to create an account at hub.docker.com and execute a
docker push <tagged_image_name
- You must setup an AWS ECS Cluster
- You need to create a Task Definition and a Service with the name of your Docker image in the Docker Repository
- Test your API. Autograder to follow shortly
Although Amazon has an ECS Tutorial available, I think this fantastic tutorial which walks through all the steps and concepts is much better. You can safely ignore the ELB/ALB load balancing steps.
Create a PR for README.md
, modifying your row in the Students section by replacing the URL from the first assignment with the url of your shiny new API.
Auto-grader for the REST API is up. This is a Python script, and hopefully it will work consistently accross all platforms. How to run?
$ python grade_a2.py <your-url>
Here, <your-url>
should be your server url (without the angle brackets), e.g.,
python grade_a2.py http://localhost:8080
.
You might need to install a Python library called requests
used for making http requests very easily.
Installing library in python is simple. You can use pip
, a Python package manager, do install request
library.
pip install requests
. You can install pip
from https://pip.pypa.io/en/stable/installing/.
UPDATE
Added support to check CircleCI badge directly from the Github. Once your PR is approved, you can
run python grade_a2.py -github <your-netid>
. It will fetch the submitted URL, and the circle CI
badge and perform the tests that we will check during grading.