This repository contains the application code for the CMS EASi (Easy Access to System Information).
The server portion of the application is written in Go. More information can be found in the pkg documentation.
There are a number of things you'll need at a minimum to be able to check out, develop, and run this project.
-
Install Homebrew
- Use the following command
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- Use the following command
-
We normally use the latest version of Go unless there's a known conflict (which will be announced by the team) or if we're in the time period just after a new version has been released.
- Install it with Homebrew:
brew install go
- Note:
If you have previously modified your PATH to point to a specific version of go,
make sure to remove that.
This would be either in your
.bash_profile
or.bashrc
, and might look something likePATH=$PATH:/usr/local/opt/[email protected]/bin
.
- Install it with Homebrew:
-
Ensure you are using the latest version of bash for this project:
-
Install it with Homebrew:
brew install bash
-
Update list of shells that users can choose from:
[[ $(cat /etc/shells | grep /usr/local/bin/bash) ]] \ || echo "/usr/local/bin/bash" | sudo tee -a /etc/shells
-
If you are using bash as your shell (and not zsh, fish, etc) and want to use the latest shell as well, then change it (optional):
chsh -s /usr/local/bin/bash
-
Ensure that
/usr/local/bin
comes before/bin
on your$PATH
by runningecho $PATH
. Modify your path by editing~/.bashrc
or~/.bash_profile
and changing thePATH
. Then source your profile withsource ~/.bashrc
or~/.bash_profile
to ensure that your terminal has it.
-
-
Note: If you have previously used yarn or Golang, please make sure none of them are pinned to an old version by running
brew list --pinned
. If they are pinned, please runbrew unpin <formula>
. You can upgrade these formulas instead of installing by runningbrew upgrade <formula
.
Use your work email when making commits to our repositories. The simplest path to correctness is setting global config:
git config --global user.email "[email protected]"
git config --global user.name "Trusty Trussel"
If you drop the --global
flag,
these settings will only apply to the current repo.
If you ever re-clone that repo or clone another repo,
you will need to remember to set the local config again.
You won't.
Use the global config. :-)
For web-based Git operations, GitHub will use your primary email unless you choose "Keep my email address private". If you don't want to set your work address as primary, please turn on the privacy setting.
Note that with 2-factor-authentication enabled, in order to push local code to GitHub through HTTPS, you need to create a personal access token and use that as your password.
All of Go's tooling expects Go code to be checked out in a specific location.
Please read about Go workspaces
for a full explanation.
If you just want to get started,
then decide where you want all your go code to live
and configure the GOPATH environment variable accordingly.
For example,
if you want your go code to live at ~/code/go
,
you should add the following like to your .bash_profile
:
export GOPATH=~/code/go
Golang expects the GOPATH
environment variable to be defined.
If you'd like to use the default location,
then add the following to your .bash_profile
or hard code the default value.
This line will set the GOPATH environment variable
to the value of go env GOPATH
if it is not already set.
export GOPATH=${GOPATH:-$(go env GOPATH)}
Regardless of where your go code is located,
you need to add $GOPATH/bin
to your PATH
so that executables installed with the go tooling can be found.
Add the following to your .bash_profile
:
export PATH=$(go env GOPATH)/bin:$PATH
Finally to have these changes applied to your shell,
you must source
your profile:
source ~/.bash_profile
You can confirm that the values exist with:
env | grep GOPATH
# Verify the GOPATH is correct
env | grep PATH
# Verify the PATH includes your GOPATH bin directory
You can checkout this repository by running
git clone [email protected]:cmsgov/easi-app.git
.
Please check out the code in a directory like
~/Projects/easi-app
and NOT in your $GOPATH
. As an example:
mkdir -p ~/Projects
git clone [email protected]:cmsgov/easi-app.git
cd easi-app
You will then find the code at ~/Projects/easi-app
.
You can check the code out anywhere EXCEPT inside your $GOPATH
.
So this is customization that is up to you.
See also: ADR on how we share secrets
Truss have set up a 1Password vault for EASi engineers to securely share secrets, such as API keys. You will need to be invited to generate login credentials.
If you need access to a secret that is not in the EASi vault, please ask for someone to add it to the vault.
Run brew install direnv
to install.
Add the following line at the very end of your ~/.bashrc
file: eval "$(direnv hook bash)"
, and then restart your shell.
(Here are instructions for other shells.)
To allow direnv in the project directory direnv allow .
.
Once this is setup, you should see direnv
loading/unloading
environment variables as you enter or depart from the
project directory:
$ cd easi-app
direnv: loading ~/Project/easi-app/.envrc
direnv: export +EXAMPLE_ENV +EXAMPLE_ENV_ADDITIONAL +EXAMPLE_ENV_MORE ... ~PATH
$ cd ..
direnv: unloading
$
For additional documentation of this tool, see also:
- The official site
- Truss' Engineering Playbook
Run brew install yarn
to install yarn.
Run yarn install
to install dependencies.
This is temporary for setting up pre-commit package, until we decide how to structure our CLI tools.
Run pre-commit install
to install a pre-commit hook
into ./git/hooks/pre-commit
.
This is different than brew install pre-commit
and must be done
so that the hook will check files
you are about to commit to the repository.
Next install the pre-commit hook libraries
with pre-commit install-hooks
.
If you want to make changes to the CircleCI configuration, you will need to
install the circleci
cli tool so that the changes can be validated by
pre-commit: brew install circleci
To set up docker on your local machine:
brew cask install docker
brew install docker-completion
Now you will need to start the Docker service: run Spotlight and type in 'docker'.
One option for running the app and its dependencies is to use
docker-compose
:
brew install docker-compose
brew install docker-compose-completion # optional
Multiple docker-compose files exist to support different use cases and environments.
File | Description |
---|---|
docker-compose.yml | Base configuration for db , db_migrate , and minio service |
docker-compose.override.yml | Additional configuration for running db and db_migrate locally. Intended to simplify the use case where someone uses docker-compose only to run db and db_migrate |
docker-compose.circleci.yml | Additional configuration for running all services in CircleCI |
docker-compose.local.yml | Additional configuration for running all services locally |
Use the following command if you only intend to run the database and database migration containers locally:
$ docker-compose up --detach
Creating easi-app_db_1 ... done
Creating easi-app_db_migrate_1 ... done
By default, Docker Compose reads two files, a docker-compose.yml and an optional docker-compose.override.yml file. That's why, for the above command, you don't need to specify which compose files to use.
Two options to take it down:
docker-compose kill # stops the running containers
docker-compose down # stops and also removes the containers
You can also force rebuilding the images (e.g. after using kill
) with
docker-compose build
.
To inspect the database from your shell, pgcli
is recommended:
brew install pgcli
Thanks to variables set in the .envrc
, connecting is simple:
$ pgcli
Server: PostgreSQL 11.6 (Debian 11.6-1.pgdg90+1)
Version: 2.2.0
Chat: https://gitter.im/dbcli/pgcli
Home: http://pgcli.com
postgres@localhost:postgres> SHOW server_version;
+-------------------------------+
| server_version |
|-------------------------------|
| 11.6 (Debian 11.6-1.pgdg90+1) |
+-------------------------------+
SHOW
Time: 0.016s
postgres@localhost:postgres>
You may need to access cloud service to develop the application. This allows access to AWS resources (ex. SES Email).
Follow the instructions in the infra repo
here.
You'll need to add the infra account environment variables
to your .envrc.local
.
You can then run the ctkey
command
to get/set AWS environment variables.
https_proxy=localhost:8888 \\
ctkey --username=$CTKEY_USERNAME \\
--password=$CTKEY_PASSWORD \\
--account=$AWS_ACCOUNT_ID \\
--url=$CTKEY_URL \\
--idms=$CT_IDMS \\
--iam-role=$CT_AWS_ROLE setenv
Eventually, we will move this over to wrapper so developers do not need to manually run these commands.
If you want to reload the Go application on changes locally, you can use Air
Install it:
go get -u github.com/cosmtrek/air
Run it:
air
It's not currently set up to run with docker. You can edit the config here
MinIO is an S3 compatible object store. It ships as a Docker container and accepts normal AWS S3 API requests. This allows us to test file uploading functionality in our local development environments without needing to interact with CMS AWS accounts.
The container is configured as part of our docker-compose.yml
and
should be running when you docker-compose up
. You'll need to set
two environment variables locally in your .envrc.local
file:
export MINIO_ACCESS_KEY='minioadmin'
export MINIO_SECRET_KEY='minioadmin'
docker-lambda is used to run lambda functions locally that execute in AWS in a deployed environment.
It should start automatically if you run docker-compose up
.
Regenerate the go types and resolver definitions:
go generate ./...
Regenerate the TypeScript types and validate schema.graphql
:
yarn generate
The EASi server uses Swagger generation to access APIs from CEDAR (the data source). Swagger specs (EASi and LDAP) can be downloaded from webMethods:
Put these files in ️$CEDAR_EASI_DIRECTORY
and $CEDAR_LDAP_DIRECTORY
, respectively,
and name them swagger-<env>.yaml
respectively per environment.
If you haven't run go-swagger before, you'll need to install it. Run:
go build -o bin/swagger github.com/go-swagger/go-swagger/cmd/swagger
Then, to generate the clients run:
swagger generate client -f $CEDAR_EASI_SWAGGER_FILE -c $CEDAR_EASI_DIRECTORY/gen/client -m $CEDAR_EASI_DIRECTORY/gen/models
and
swagger generate client -f $CEDAR_LDAP_SWAGGER_FILE -c $CEDAR_LDAP_DIRECTORY/gen/client -m $CEDAR_LDAP_DIRECTORY/gen/models
To build the cli application in your local filesystem:
go build -a -o bin/easi ./cmd/easi
You can then access the tool with the easi
command.
To add a new migration, add a new file to the migrations
directory
following the standard
V_${last_migration_version + 1}_your_migration_name_here.sql
Once your developer environment is setup,
you can run tests with the easi test
command.
If you run into into various (typecheck)
errors when
running easi test
follow the directions for installing
golangci-lint
to upgrade golangci-lint.
There are multiple ways to run the Cypress tests:
- Run
npx cypress run
to run the tests in the CLI. To have a slightly more interactive experience, you can instead runnpx cypress open
. Note: the database, frontend, and backend must be running prior to starting the Cypress tests. TheAPP_ENV
environment variable should be set totest
. APP_ENV=test ./scripts/run-cypress-test-docker
: Run the Cypress tests, database, migrations, backend, and frontend locally in Docker, similar to how they run in CircleCI. Running the tests in this way takes time, but is useful for troubleshooting integration test failures in CI.
The APIs reside at localhost:8080
when running.
To run a test request,
you can send a GET to the health check endpoint:
curl localhost:8080/api/v1/healthcheck
You can visit http://localhost:8080/graph/playground
to access a GraphQL playground while
the Go backend is running. You will need to enter /graph/query
as the query
path in the UI for this to work.
Setting this APP_ENV
environment variable to "local"
will turn off API authorization.
This allows you to debug quickly without retrieving Okta access tokens.
If you need to test the authorization,
unset that environment variable.
You can then retrieve access tokens
by logging into the development app
and copying okta-token-storage/accessToken
from the browser's local storage.
Place this in the Authorization
header
as Bearer ${accessToken}
.