Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smoke test workflow #7

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
name: E2E Tests

on:
workflow_dispatch # disabled pending db seeding
# push:
# branches: [ main ]
# pull_request:
# branches: [ main ]
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: build containers and run cypress e2e tests
# TODO: seed the database with a sparse(r) dump so there are pages to test..
run: make e2e

- name: deploy services in e2e mode
run: make deploy-e2e

- name: run e2e tests
uses: cypress-io/github-action@v6
with:
working-directory: e2e
wait-on: "http://localhost:8000"
wait-on-timeout: 300

- name: display service logs
if: failure()
run: docker compose -f docker-compose.yml -f e2e.yml logs

- name: upload cypress videos
if: failure()
uses: actions/upload-artifact@v4
with:
name: cypress-videos
path: e2e/cypress/videos
29 changes: 21 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ ENV_TEMPLATE=${DEPLOY_CONF_DIR}/.env.template
BORG_REPO_URL := https://example.com/repo.tar.xz
BORG_REPO_PATH=${BUILD_DIR}/repo.tar.xz
REPO_BACKUPS_PATH=${DOCKER_SHARED_DIR}/backups
E2E_REPO_BACKUPS_PATH=${DOCKER_SHARED_DIR}/e2e/backups

include config.mk
include .env
Expand Down Expand Up @@ -84,7 +85,7 @@ release-version: .env
.PHONY: docker-compose.yml
docker-compose.yml: base.yml dev.yml staging.yml prod.yml config.mk $(PGPASS_PATH) release-version
case "$(DEPLOY_ENVIRONMENT)" in \
dev|staging|e2e) docker compose -f base.yml -f $(DEPLOY_ENVIRONMENT).yml config > docker-compose.yml;; \
dev|staging) docker compose -f base.yml -f $(DEPLOY_ENVIRONMENT).yml config > docker-compose.yml;; \
prod) docker compose -f base.yml -f staging.yml -f $(DEPLOY_ENVIRONMENT).yml config > docker-compose.yml;; \
*) echo "invalid environment. must be either dev, staging or prod" 1>&2; exit 1;; \
esac
Expand Down Expand Up @@ -139,10 +140,22 @@ clean_deploy: clean
.PHONY: test
test: build
docker compose run --rm server /code/deploy/test.sh

.PHONY: e2e
e2e: DEPLOY_ENVIRONMENT=e2e
e2e: build
docker compose run server inv collectstatic
docker compose run --rm e2e npm run test
docker compose down

$(E2E_REPO_BACKUPS_PATH):
@echo "$(E2E_REPO_BACKUPS_PATH) did not exist, creating now"
mkdir -p $(E2E_REPO_BACKUPS_PATH)

.PHONY: build-e2e
build-e2e: docker-compose.yml secrets $(DOCKER_SHARED_DIR)
docker compose -f docker-compose.yml -f e2e.yml build

.PHONY: deploy-e2e
deploy-e2e: build-e2e $(BORG_REPO_PATH) | $(E2E_REPO_BACKUPS_PATH)
sudo chown -R ${USER}: $(E2E_REPO_BACKUPS_PATH)
# create repo directory if it doesn't exist
mkdir -p $(E2E_REPO_BACKUPS_PATH)/repo
tar -Jxf $(BORG_REPO_PATH) -C $(E2E_REPO_BACKUPS_PATH)
docker compose -f docker-compose.yml -f e2e.yml up -d
docker compose -f docker-compose.yml -f e2e.yml exec server inv borg.restore --force
docker compose -f docker-compose.yml -f e2e.yml exec server ./manage.py migrate
docker compose -f docker-compose.yml -f e2e.yml exec server inv prepare
24 changes: 22 additions & 2 deletions django/core/settings/e2e.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
from .dev import *
from .test import *

DEPLOY_ENVIRONMENT = Environment.TEST
DEBUG = True

DJANGO_VITE_DEV_MODE = False

SHARE_DIR = path.realpath("/shared/e2e")
LIBRARY_ROOT = path.join(SHARE_DIR, "library")
LIBRARY_PREVIOUS_ROOT = path.join(SHARE_DIR, ".latest")
REPOSITORY_ROOT = path.join(BASE_DIR, "repository")
BACKUP_ROOT = path.join(SHARE_DIR, "backups")
BORG_ROOT = path.join(BACKUP_ROOT, "repo")
EXTRACT_ROOT = path.join(SHARE_DIR, "extract")
MEDIA_ROOT = path.join(SHARE_DIR, "media")

DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("DB_NAME"),
"USER": os.getenv("DB_USER"),
"PASSWORD": read_secret("db_password", os.getenv("DB_PASSWORD")),
"HOST": "e2edb",
"PORT": os.getenv("DB_PORT"),
}
}
13 changes: 9 additions & 4 deletions django/curator/invoke_tasks/borg.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,19 @@ def restore_database(

@task()
def restore(
ctx, repo=settings.BORG_ROOT, archive=None, target_database=db._DEFAULT_DATABASE
ctx,
repo=settings.BORG_ROOT,
archive=None,
target_database=db._DEFAULT_DATABASE,
force=False,
):
"""Restore the library files, media files and database to the state given in the borg repo at path REPO
using archive ARCHIVE. The target_database argument is for testing so a different database can be used to
make sure the database is getting restored properly"""
confirm(
"Are you sure you want to restore the database and all file content (y/n)? "
)
if not force:
confirm(
"Are you sure you want to restore the database and all file content (y/n)? "
)
with tempfile.TemporaryDirectory(dir=settings.SHARE_DIR) as working_directory:
_restore(
ctx,
Expand Down
4 changes: 2 additions & 2 deletions django/curator/invoke_tasks/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def create_pgpass_file(ctx, db_key=_DEFAULT_DATABASE, force=False):
if os.path.isfile(pgpass_path) and not force:
return
with open(pgpass_path, "w+") as pgpass:
pgpass.write("db:*:*:{db_user}:{db_password}\n".format(**db_config))
pgpass.write("{db_host}:*:*:{db_user}:{db_password}\n".format(**db_config))
ctx.run("chmod 0600 ~/.pgpass")


Expand Down Expand Up @@ -132,7 +132,7 @@ def restore_from_dump(
cat_cmd = "zcat"
drop(ctx, database=target_database, create=True)
ctx.run(
"{cat_cmd} {dumpfile} | psql -w -q -o restore-from-dump-log.txt -h db {db_name} {db_user}".format(
"{cat_cmd} {dumpfile} | psql -w -q -o restore-from-dump-log.txt -h {db_host} {db_name} {db_user}".format(
cat_cmd=cat_cmd, dumpfile=dumpfile, **db_config
),
echo=True,
Expand Down
52 changes: 34 additions & 18 deletions e2e.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,43 @@
services:
e2e:
image: comses/cypress
build: e2e
environment:
- CYPRESS_baseUrl=http://server:8000
db:
image: alpine # disable the normal db container
command: tail -f /dev/null
healthcheck: null
e2edb:
image: postgis/postgis:15-3.4
secrets:
- db_password # re-using the same db password
volumes:
- ./e2e/cypress:/code/cypress
- ./e2e/cypress.config.js:/code/cypress.config.js
- ./django/deploy/wait-for-it.sh:/code/wait-for-it.sh
depends_on:
- server
- ./build/secrets/db_password:/run/secrets/db_password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
interval: 30s
timeout: 5s
retries: 5
environment:
POSTGRES_USER: "${DB_USER}"
POSTGRES_DB: "${DB_NAME}"
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
vite:
volumes:
- ./frontend:/code
command: ["npm", "run", "build"]
environment:
NODE_ENV: "e2e"
server:
image: comses/server:dev
volumes:
- ./django:/code
- ./docs:/docs
depends_on:
db:
condition: service_started
e2edb:
condition: service_healthy
elasticsearch:
condition: service_started
redis:
condition: service_started
vite:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000"]
interval: 30s
timeout: 10s
retries: 5
environment:
DJANGO_SETTINGS_MODULE: "core.settings.e2e"
ports:
- "127.0.0.1:8000:8000"
14 changes: 0 additions & 14 deletions e2e/Dockerfile

This file was deleted.

4 changes: 2 additions & 2 deletions e2e/cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
baseUrl: "http://localhost:8000",
specPattern: ["cypress/e2e/**/*.spec.ts"],
specPattern: ["cypress/tests/**/*.spec.ts"],
supportFile: false,
screenshotOnRunFailure: false,
video: false,
video: true,
}
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//test narative documentation
1 change: 1 addition & 0 deletions e2e/cypress/fixtures/codebase/testSimulationOutput.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//testSimulationOutput
2 changes: 2 additions & 0 deletions e2e/cypress/fixtures/codebase/testSourceCode.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//test source code

1 change: 1 addition & 0 deletions e2e/cypress/fixtures/codebase/testUploadData.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//test upload data
19 changes: 19 additions & 0 deletions e2e/cypress/tests/beforeLoginTests.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//test ability to browse/download codebases
describe("Browse Codebases", () => {
it("should browse the model library and be able to enter a search query", () => {
cy.visit("/"); // visit homepage
cy.visit("/codebases");
assert(cy.get("h1").contains("Computational Model Library"));
});
});

//download codebase
describe("Download Codebases", () => {
it("should download a codebase", () => {
// Navigate to the first 'search-result', find the 'a' tag within the 'title' div, and click it
cy.get(".search-result", { timeout: 10000 })
.first()
.find(".title a")
.click();
});
});
Loading
Loading