Skip to content

Commit

Permalink
[EDS-507] Adds Selenium tests which now run after deployment (#129)
Browse files Browse the repository at this point in the history
* [EDS-507] Adds Selenium tests which now run after deployment

- Adds selenium-tests
- Adds docker-compose for selenium tests
- Refactors how app images are built and cached to reduce complexity and maintenance
- [Patch] updates dependencies

* [Bot] Update version to 2.1.6

* [Bot] Update version to 2.1.8

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
Thomas Thorogood and github-actions[bot] authored Mar 23, 2022
1 parent 71c46d5 commit 38cf4a0
Show file tree
Hide file tree
Showing 28 changed files with 1,455 additions and 700 deletions.
6 changes: 1 addition & 5 deletions .github/steps/deploy/canvas.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@
},
{
"stepId": "deploy",
"description": "Deploy version ${{ version }} to ${{ stage }}",
"description": "Deploy version ${{ version }} to ${{ stage }} and validate",
"status": "in progress"
},
{
"stepId": "validate-deployment",
"description": "Test deployed ${{ stage }} instance"
}
]
}
4 changes: 3 additions & 1 deletion .github/steps/pull-request/create-pr-tag.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env bash

set -e
source ./scripts/globals.sh
source ./.build-scripts/sources/github-actions.sh

function print_help {
Expand Down Expand Up @@ -38,7 +40,7 @@ done
pr_number=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH")
test -n "pr_number" || exit 1
tag_name="pull-request-${pr_number}"
dest_image=gcr.io/uwit-mci-iam/husky-directory:${tag_name}
dest_image="${DOCKER_REPOSITORY}.app:${tag_name}"
docker tag "${source_image}" ${dest_image}
docker push "${dest_image}"
set_ci_output image "${dest_image}"
75 changes: 21 additions & 54 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
max-parallel: 1
steps:
- uses: actions/checkout@v2
- uses: abatilo/[email protected]
- run: ./scripts/install-build-scripts.sh
name: Install common-build-scripts
- uses: google-github-actions/[email protected]
Expand Down Expand Up @@ -65,40 +66,33 @@ jobs:
id: configure-env
name: Configure manual deployment

- name: Fetch the promotion version if no version is provided
run: |
./scripts/deploy.sh --configure-only \
-t "${target_cluster}" \
-v "${target_version}" \
-r "${rfc_number}"
id: configure-promotion
if: '! env.target_version'

- name: Update env with promotion version
# This runs as a separate step so that the entrypoint (manual vs. auto)
# doesn't matter.
run: |
source ./scripts/globals.sh
source ./.build-scripts/sources/github-actions.sh
set_env target_version '${{ steps.configure-promotion.outputs.target-version }}'
target_version=$(get_promotion_version ${{ inputs.cluster }})
set_env target_version "${target_version}"
if: '! env.target_version'

- name: Configure slack notification canvas
id: configure-canvas
run: ${STEP_SCRIPTS}/configure-canvas.sh

- uses: uwit-iam/actions/update-slack-workflow[email protected].4
- uses: uwit-iam/actions/set-up-slack-notification[email protected].8
with:
json: ${{ steps.configure-canvas.outputs.slack-canvas }}
command: create-canvas
id: create-canvas
id: slack
name: Create slack notification canvas

- run: |
source ./.build-scripts/sources/github-actions.sh
set_env SLACK_CANVAS_ID "${{ steps.create-canvas.outputs.canvas-id }}"
set_env CURRENT_STEP deploy
set_env NEXT_STEP validate-deployment
name: Set up slack notification env
- uses: uwit-iam/actions/[email protected].4
- uses: uwit-iam/actions/[email protected].8
with:
command: add-artifact
description: ${{ steps.configure-canvas.outputs.context-artifact }}
Expand All @@ -108,51 +102,24 @@ jobs:
id: deploy
name: Deploy version ${{ env.target_version }}

- uses: uwit-iam/actions/[email protected]
with:
command: update-workflow
step-id: ${{ env.CURRENT_STEP }}, ${{ env.NEXT_STEP }}
step-status: succeeded, in progress
name: Update canvas and progress to ${{ env.NEXT_STEP }}
- run: |
source ./.build-scripts/sources/github-actions.sh
set_env CURRENT_STEP $NEXT_STEP
set_env NEXT_STEP ""
name: Update canvas steps in env
- uses: uwit-iam/actions/[email protected]
- uses: uwit-iam/actions/[email protected]
with:
command: update-workflow
step-id: ${{ env.CURRENT_STEP }}
step-status: succeeded
name: Mark step as successful

- if: failure() && steps.create-canvas.outputs.canvas-id
uses: uwit-iam/actions/update-slack-workflow[email protected].4
- if: always() && steps.slack.outputs.canvas-id
uses: uwit-iam/actions/finalize-slack-notification[email protected].8
with:
command: update-workflow
step-id: ${{ env.CURRENT_STEP }}
workflow-status: failed
step-status: failed
name: Mark workflow as failed
workflow-status: ${{ job.status == 'success' && 'succeeded' || 'failed' }}

- if: always() && steps.create-canvas.outputs.canvas-id
uses: uwit-iam/actions/[email protected]
with:
command: remove-step
step-id: '*'
step-status: succeeded
name: Clean up workflow canvas

- if: success()
uses: uwit-iam/actions/[email protected]
with:
command: update-workflow
workflow-status: succeeded
name: Mark workflow as successful
- run: >
test -f webdriver-report/index.html
&& echo "::set-output name=upload-report::true"
id: report
- if: always() && steps.create-canvas.outputs.canvas-id
uses: uwit-iam/actions/[email protected]
- if: always() && steps.report.outputs.upload-report == 'true'
uses: actions/upload-artifact@v2
with:
command: finalize-workflow
name: Finalize workflow
name: web test storyboards for for ${{ github.sha }}
path: ./webdriver-report
5 changes: 3 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
new-version: ${{ steps.update-version.outputs.new-version }}
steps:
- name: Python Poetry Action
uses: abatilo/[email protected].0
uses: abatilo/[email protected].4

- uses: uwit-iam/actions/[email protected]
id: guidance
Expand All @@ -40,14 +40,15 @@ jobs:
APP_VERSION: ${{ needs.update-pr-branch-version.outputs.new-version }}
steps:
- uses: actions/checkout@v2
- uses: abatilo/[email protected]

- run: |
./.github/scripts/gcr-login.sh
./scripts/install-build-scripts.sh
id: configure
- name: Run validation checks and tests
run: ./scripts/pre-push.sh --headless --version $APP_VERSION
run: ./scripts/pre-push.sh --headless --version $APP_VERSION --skip-auto-format -g
id: run-validations

- name: Push tag for pull request
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
webdriver-report
gcloud-credentials.json
.idea
node_modules
Expand Down
2 changes: 1 addition & 1 deletion docker/deployment.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ARG DEPLOYMENT_ID
ENV DEPLOYMENT_ID=${DEPLOYMENT_ID} \
FLASK_ENV=production
RUN echo $DEPLOYMENT_ID >> .deployment
CMD poetry run gunicorn -b 0.0.0.0:${FLASK_PORT} \
CMD gunicorn -b 0.0.0.0:${FLASK_PORT} \
--log-level ${GUNICORN_LOG_LEVEL} \
-c "/app/husky_directory/gunicorn.conf.py" \
"husky_directory.app:create_app()"
28 changes: 0 additions & 28 deletions docker/development-server.dockerfile

This file was deleted.

48 changes: 48 additions & 0 deletions docker/docker-compose.selenium.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# You can use this composition to run tests
# backed by webdriver-recorder. This is helpful if your
# test suite is simple and has no additional dependencies.
# TEST_DIR=/path/to/your/tests docker-compose up --build.
version: '3.1'
services:
selenium:
image: selenium/standalone-chrome:4.1
environment:
SE_NODE_MAX_SESSIONS: 2 # Allows up to two concurrent browser instances to use
# the node.
SE_START_XFVB: "false" # Prevents some expensive overhead we don't need
ports:
- "4444:4444" # This is the port where you can access the selenium
# dashboard
- "7900:7900"
logging:
driver: "none"
volumes:
# We want for test files to available on the selenium
# container because tests may have files the test browser
# needs to serve.
- ../selenium-tests:/selenium-tests

test-runner:
build:
dockerfile: ./docker/husky-directory.dockerfile
target: selenium-runner
context: ../
environment:
TZ: America/Los_Angeles
pytest_args: ${pytest_args}
pytest_log_level: ${pytest_log_level}
uw_directory_url: ${uw_directory_url}
USE_TEST_IDP: True
volumes:
- ../webdriver-report:/webdriver-report
- ../selenium-tests:/selenium-tests
depends_on:
- selenium
entrypoint: /selenium-tests/entrypoint.sh
command: >
pytest
--report-dir /webdriver-report
--selenium-server selenium:4444
--uw-directory-url ${uw_directory_url:-prod}
-o log_cli=true -o log_cli_level=${pytest_log_level:-error}
${pytest_args}
9 changes: 0 additions & 9 deletions docker/husky-directory-base.dockerfile

This file was deleted.

51 changes: 51 additions & 0 deletions docker/husky-directory.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
ARG uw_saml_poetry_version=latest
FROM ghcr.io/uwit-iam/uw-saml-poetry:${uw_saml_poetry_version} as base
WORKDIR /app

# gcc is required to install the Levenshtein library.
RUN apt-get update && apt-get -y install gcc curl jq

COPY poetry.lock pyproject.toml ./

ENV PATH="$POETRY_HOME/bin:$PATH"

RUN poetry install --no-dev --no-interaction \
&& apt-get -y remove gcc \
&& apt-get -y autoremove

FROM base as app
ARG HUSKY_DIRECTORY_VERSION
COPY ./husky_directory ./husky_directory/
ENV PYTHONPATH="/app:${PYTHONPATH}" \
DOTENV_FILE="/app/husky_directory/settings/base.dotenv" \
PROMETHEUS_MULTIPROC_DIR="/tmp/prometheus" \
FLASK_PORT=8000 \
HUSKY_DIRECTORY_VERSION=${HUSKY_DIRECTORY_VERSION} \
GUNICORN_LOG_LEVEL=DEBUG

RUN mkdir -pv $PROMETHEUS_MULTIPROC_DIR && mkdir "/tmp/flask_session"

FROM app AS test-runner
WORKDIR /scripts
COPY ./scripts/validate-development-image.sh ./scripts/run-image-tests.sh ./
COPY ./tests /tests
COPY ./selenium-tests /selenium-tests
# Re-running install without the `--no-dev` arg to get the extra dependencies;
# the others won't need updating, so won't add extra time to the secondary run.
WORKDIR /app
RUN poetry install --no-interaction
# Make sure that unit tests are available at the root directory of the test-runner
WORKDIR /tests

# Make sure that selenium tests are
# available at the root directory of the selenium-runner
FROM test-runner AS selenium-runner
WORKDIR /selenium-tests

FROM app AS development-server
ENV FLASK_ENV=development
EXPOSE 8000
# 0.0.0.0 binding is necessary for the endpoint to be available externally.
CMD poetry run gunicorn -b 0.0.0.0:${FLASK_PORT} \
-c "/app/husky_directory/gunicorn.conf.py" \
"husky_directory.app:create_app()"
5 changes: 5 additions & 0 deletions husky_directory/blueprints/saml.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ def process_saml_request(self, request: Request, session: LocalProxy, **kwargs):
return redirect(dest_url)

def login(self, request: Request, session: LocalProxy):
session_permanent = session.get("permanent")
# A recent update clears the 'permanent' setting when the
# session is cleared; this override preserves the original
# value.
session.clear()
session["permanent"] = session_permanent
acs_hostname = urllib.parse.urlparse(request.host_url).hostname
acs_host = f"https://{acs_hostname}"
acs_url = urllib.parse.urljoin(acs_host, self.auth_settings.saml_acs_path)
Expand Down
2 changes: 2 additions & 0 deletions husky_directory/settings/base.dotenv
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ SAML_ENTITY_ID=https://${HOST}/saml
SAML_ACS_PATH=/saml/login
PROMETHEUS_METRIC_PREFIX=uw_directory
SHOW_EXPERIMENTAL_FEATURES=False
SESSION_FILE_DIR=/tmp/flask_session
USE_TEST_IDP=True

This comment has been minimized.

Copy link
@jprosser

jprosser Oct 11, 2022

In hind sight, this should probably have been default false and overridden where needed.

Loading

0 comments on commit 38cf4a0

Please sign in to comment.