Adding the docker image for Cypress + Nginx container.

Also modifying the Gitlab CI to use local Nginx for proxying to API backend while running Cypress tests.
This commit is contained in:
Arpit Mohan 2020-05-12 19:59:36 +00:00
parent 8ca4683de7
commit aefcf68c80
14 changed files with 134 additions and 107 deletions

View File

@ -8,6 +8,7 @@
- |
if [ "$CI_COMMIT_BRANCH" == "master" ]; then
REACT_APP_ENVIRONMENT="PRODUCTION"
REACT_APP_BASE_URL="https://api.appsmith.com"
elif [ "$CI_COMMIT_BRANCH" == "release" ]; then
REACT_APP_ENVIRONMENT="STAGING"
REACT_APP_BASE_URL="https://release-api.appsmith.com"
@ -15,7 +16,9 @@
REACT_APP_ENVIRONMENT="DEVELOPMENT"
REACT_APP_BASE_URL="https://release-api.appsmith.com"
fi
image: cypress/base:10.16.3
# This image contains Nginx & Cypress binaries
image: appsmith/cypress-nginx
variables:
npm_config_cache: "$CI_PROJECT_DIR/.npm"
@ -55,15 +58,30 @@ react-build-release:
- release
- merge_requests
cypress-test-release:
unit_test:
stage: test
script:
- *set_env_variables
- yarn run test:unit
only:
- release
- merge_requests
# all jobs that actually run tests can use the same definition
.test_job_template:
image: appsmith/cypress-nginx
stage: test
script:
- *set_env_variables
- yarn global add serve
- serve -s build -p 3000 &
# This is required in order to ensure that all the test cases pass
- echo "127.0.0.1 dev.appsmith.com" >> /etc/hosts
- yarn test
- serve -s build -p 3000 &
- mkdir -p /var/www/appsmith /etc/certificate
- cp ./docker/nginx-linux.conf /etc/nginx/conf.d/app.conf
- cp $APPSMITH_SSL_CERTIFICATE /etc/certificate/dev.appsmith.com.pem
- cp $APPSMITH_SSL_KEY /etc/certificate/dev.appsmith.com-key.pem
- nginx
- yarn test:ci
artifacts:
when: always
expire_in: 1 week
@ -75,35 +93,29 @@ cypress-test-release:
- release
- merge_requests
# cypress-test-fix:
# stage: build
# script:
# - *set_env_variables
# - yarn install
# # show where the Cypress test runner binaries are cached
# - $(npm bin)/cypress cache path
# # show all installed versions of Cypress binary
# - $(npm bin)/cypress cache list
# - $(npm bin)/cypress verify
# - curl https://s3.ap-south-1.amazonaws.com/dev.public.appsmith/react-build/build1.tar.gz --output build.tar.gz
# - tar xvf build.tar.gz
# - yarn global add serve
# - serve -s build -p 3000 &
# # This is required in order to ensure that all the test cases pass
# - echo "127.0.0.1 dev.appsmith.com" >> /etc/hosts
# - yarn test
# artifacts:
# when: always
# expire_in: 1 week
# paths:
# - cypress/screenshots
# - cypress/videos
# only:
# # We don't test on master right now because of changing environment variables for REACT_APP_BASE_URL. Need to figure out a way to configure that.
# - fix/test-revert
cypress-test-release-1:
extends: .test_job_template
cypress-test-release-2:
extends: .test_job_template
cypress-test-release-3:
extends: .test_job_template
cypress-test-release-4:
extends: .test_job_template
cypress-test-release-5:
extends: .test_job_template
cypress-test-release-6:
extends: .test_job_template
docker-package-release:
image: docker:dind
# This ensures that it runs on the dedicated runner
tags:
- appsmith
services:
- docker:dind
stage: package
@ -137,7 +149,9 @@ docker-package-prod:
script:
- *set_env_variables
- docker build -t appsmith/appsmith-editor:latest .
- docker build -t appsmith/appsmith-editor:$CI_COMMIT_SHORT_SHA .
- docker login -u $DOCKER_HUB_USERNAME -p $DOCKER_HUB_ACCESS_TOKEN
- docker push appsmith/appsmith-editor:latest
# If we don't add the tag to the `docker push` command, all the tags for this image will be pushed
- docker push appsmith/appsmith-editor
only:
- master

View File

@ -0,0 +1,3 @@
FROM cypress/browsers:node10.16.3-chrome80-ff73
RUN apt-get update -y && apt-get install -y nginx && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && yarn global add serve

View File

@ -10,6 +10,9 @@
- `yarn start` Deploy locally
> For more details on how to run this locally, please visit: [Notion Doc](https://www.notion.so/appsmith/How-to-run-the-code-e031545454874419b9f72cd51feb90ff)
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts

View File

@ -1,5 +1,5 @@
{
"baseUrl":"http://dev.appsmith.com:3000/",
"baseUrl": "https://dev.appsmith.com/",
"defaultCommandTimeout": 20000,
"requestTimeout": 21000,
"pageLoadTimeout": 20000,

View File

@ -18,4 +18,12 @@
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on("before:browser:launch", (browser = {}, launchOptions) => {
if (browser.name === "chrome") {
launchOptions.args.push("--disable-dev-shm-usage");
return launchOptions;
}
return launchOptions;
});
};

View File

@ -397,35 +397,30 @@ Cypress.Commands.add("addDsl", dsl => {
//Fetch the layout id
cy.server();
cy.request(
"GET",
"https://release-api.appsmith.com/api/v1/pages/" + pageid,
).then(response => {
const len = JSON.stringify(response.body);
cy.log(len);
layoutId = JSON.parse(len).data.layouts[0].id;
cy.request("GET", "https://dev.appsmith.com/api/v1/pages/" + pageid).then(
response => {
const len = JSON.stringify(response.body);
cy.log(len);
layoutId = JSON.parse(len).data.layouts[0].id;
// Dumpimg the DSL to the created page
// Dumpimg the DSL to the created page
cy.request(
"PUT",
"https://release-api.appsmith.com/api/v1/layouts/" +
layoutId +
"/pages/" +
pageid,
dsl,
).then(response => {
expect(response.status).equal(200);
cy.reload();
});
});
cy.request(
"PUT",
"https://dev.appsmith.com/api/v1/layouts/" +
layoutId +
"/pages/" +
pageid,
dsl,
).then(response => {
expect(response.status).equal(200);
cy.reload();
});
},
);
});
});
Cypress.Commands.add("NavigateToDatasourceEditor", () => {
cy.get(datasourceEditor.datasourceEditorIcon).click({ force: true });
});
Cypress.Commands.add("getPluginFormsAndCreateDatasource", () => {
cy.wait("@getPluginForm").should(
"have.nested.property",
@ -578,18 +573,6 @@ Cypress.Commands.add("runSaveDeleteQuery", () => {
);
});
Cypress.Commands.add("getPluginFormsAndCreateDatasource", () => {
cy.wait("@getPluginForm").should(
"have.nested.property",
"response.body.responseMeta.status",
200,
);
cy.wait("@createDatasource").should(
"have.nested.property",
"response.body.responseMeta.status",
201,
);
});
Cypress.Commands.add("openPropertyPane", widgetType => {
const selector = `.t--draggable-${widgetType}`;
cy.get(selector)

View File

@ -21,6 +21,8 @@ let appId;
// Import commands.js using ES2015 syntax:
import "./commands";
before(function() {
console.log("**** Got Cypress base URL as: ", process.env.CYPRESS_BASE_URL);
cy.server();
cy.route("GET", "/api/v1/applications").as("applications");
cy.route("GET", "/api/v1/users/profile").as("getUser");
@ -90,7 +92,7 @@ before(function() {
});
beforeEach(function() {
Cypress.Cookies.preserveOnce("session_id", "remember_token");
Cypress.Cookies.preserveOnce("SESSION");
});
after(function() {

View File

@ -1 +1,32 @@
$(npm bin)/cypress run CYPRESS_BASE_URL='http://dev.appsmith.com:3000/' --spec "cypress/integration/Smoke_TestSuite/*/*"
#!/bin/bash
# By default we assume that the target for the CI is local
target=local
while :; do
case $1 in
-e|--env)
if [ "$2" ]; then
target=$2
shift
else
die 'ERROR: "--env" requires a non-empty option argument. Allowed values local/ci'
fi
;;
--env=?*)
target=${1#*=} # Delete everything up to "=" and assign the remainder.
;;
*) # Default case: No more options, so break out of the loop.
break
esac
shift
done
echo "Got the target: $target"
if [ "$target" == "ci" ]; then
# On the CI server run the tests in parallel
# This requires the projectId and the record_key to be configured in your environment variables. By default this is defined on the CI server
$(npm bin)/cypress run --headless --browser chrome --record --parallel --group "Electrons on Gitlab CI" --spec "cypress/integration/Smoke_TestSuite/*/*"
else
$(npm bin)/cypress run --headless --browser chrome --spec "cypress/integration/Smoke_TestSuite/*/*"
fi

View File

@ -6,22 +6,17 @@ server {
gzip on;
gzip_proxied any;
proxy_ssl_server_name on;
# sub_filter_once off;
location / {
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
# sub_filter ___BASE_URL___ http://$host;
proxy_pass http://localhost:3000;
}
location /api {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}
location /oauth2 {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}
@ -40,22 +35,17 @@ server {
gzip on;
proxy_ssl_server_name on;
# sub_filter_once off;
location / {
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
# sub_filter ___BASE_URL___ http://$host;
proxy_pass http://localhost:3000;
}
location /api {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}
location /oauth2 {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}

View File

@ -6,22 +6,16 @@ server {
gzip on;
gzip_proxied any;
proxy_ssl_server_name on;
# sub_filter_once off;
location / {
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
# sub_filter ___BASE_URL___ http://$host;
proxy_pass http://host.docker.internal:3000;
}
location /api {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}
location /oauth2 {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}
@ -40,22 +34,16 @@ server {
gzip on;
proxy_ssl_server_name on;
# sub_filter_once off;
location / {
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
# sub_filter ___BASE_URL___ http://$host;
proxy_pass http://host.docker.internal:3000;
}
location /api {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}
location /oauth2 {
# proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass https://release-api.appsmith.com;
}

View File

@ -27,3 +27,16 @@
[context.b.environment]
REACT_APP_ENVIRONMENT = "STAGING"
REACT_APP_BASE_URL = "https://release-api.appsmith.com"
[[redirects]]
from = "/api/*"
to = "API_PLACEHOLDER/api/:splat"
status = 200
force = true
[[redirects]]
from = "/oauth2/*"
to = "API_PLACEHOLDER/oauth2/:splat"
status = 200
force = true

View File

@ -107,13 +107,14 @@
"build": "./build.sh",
"build-local": "craco --max-old-space-size=4096 build --config craco.build.config.js",
"build-staging": "REACT_APP_BASE_URL=https://release-api.appsmith.com REACT_APP_ENVIRONMENT=STAGING craco --max-old-space-size=4096 build --config craco.build.config.js",
"test": "npm run test-jest && cypress/test.sh",
"test": "CYPRESS_BASE_URL=https://dev.appsmith.com cypress/test.sh",
"test:ci": "CYPRESS_BASE_URL=https://dev.appsmith.com cypress/test.sh --env=ci",
"eject": "react-scripts eject",
"start-prod": "REACT_APP_BASE_URL=https://api.appsmith.com REACT_APP_ENVIRONMENT=PRODUCTION craco start",
"storybook": "start-storybook",
"cytest": "REACT_APP_TESTING=TESTING REACT_APP_ENVIRONMENT=DEVELOPMENT craco start & ./node_modules/.bin/cypress open",
"build-storybook": "build-storybook -c .storybook -o .storybook-out",
"test-jest": "./node_modules/jest/bin/jest.js -b --colors"
"test:unit": "$(npm bin)/jest -b --colors"
},
"resolution": {
"jest": "24.8.0"

View File

@ -22,7 +22,6 @@
<div id="loader" style="width: 30vw;"></div>
<div id="root"></div>
<script type="text/javascript">
window.BASE_URL = "___BASE_URL___";
window.addEventListener("DOMContentLoaded", (event) => {
document.getElementById("loader").style.width = "50vw";
});

View File

@ -10,15 +10,7 @@ declare global {
// TODO(Abhinav): See if this is called so many times, that we may need memoization.
export const getAppsmithConfigs = (): AppsmithUIConfigs => {
const WINDOW_BASE_URL: string = window.BASE_URL;
const REACT_APP_BASE_URL: string | undefined = process.env.REACT_APP_BASE_URL;
const BASE_URL =
WINDOW_BASE_URL === "___BASE_URL___" ? REACT_APP_BASE_URL : WINDOW_BASE_URL;
if (!BASE_URL) {
throw Error("NO API Endpont defined - aborting");
}
const BASE_URL = "";
switch (process.env.REACT_APP_ENVIRONMENT) {
case "PRODUCTION":
return prodConfig(BASE_URL);