merge: 1.9.45 front-end
This commit is contained in:
commit
0eacfa2267
|
|
@ -0,0 +1,13 @@
|
|||
# https://EditorConfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[{*.java,pom.xml,*.py}]
|
||||
indent_size = 4
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -11,12 +11,12 @@
|
|||
> Add a TL;DR when description is extra long (helps content team)
|
||||
|
||||
Fixes # (issue)
|
||||
|
||||
> if no issue exists, please create an issue and ask the maintainers about this first
|
||||
|
||||
|
||||
Media
|
||||
> A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video
|
||||
|
||||
> A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video
|
||||
|
||||
## Type of change
|
||||
|
||||
|
|
@ -27,26 +27,35 @@ Media
|
|||
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||
- Chore (housekeeping or task changes that don't impact user perception)
|
||||
- This change requires a documentation update
|
||||
>
|
||||
|
||||
## Testing
|
||||
|
||||
## How Has This Been Tested?
|
||||
> Please describe the tests that you ran to verify your changes. Provide instructions, so we can reproduce.
|
||||
> Please also list any relevant details for your test configuration.
|
||||
> Delete anything that is not important
|
||||
>
|
||||
|
||||
- Manual
|
||||
- Jest
|
||||
- Cypress
|
||||
#### How Has This Been Tested?
|
||||
|
||||
> Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration.
|
||||
> Delete anything that is not relevant
|
||||
|
||||
- [ ] Manual
|
||||
- [ ] JUnit
|
||||
- [ ] Jest
|
||||
- [ ] Cypress
|
||||
>
|
||||
|
||||
#### Test Plan
|
||||
|
||||
### Test Plan
|
||||
> Add Testsmith test cases links that relate to this PR
|
||||
|
||||
### Issues raised during DP testing
|
||||
|
||||
> Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR)
|
||||
|
||||
|
||||
## Checklist:
|
||||
|
||||
### Dev activity
|
||||
|
||||
- [ ] My code follows the style guidelines of this project
|
||||
- [ ] I have performed a self-review of my own code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
|
|
@ -56,8 +65,8 @@ Media
|
|||
- [ ] New and existing unit tests pass locally with my changes
|
||||
- [ ] PR is being merged under a feature flag
|
||||
|
||||
|
||||
#### QA activity:
|
||||
|
||||
- [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered
|
||||
- [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-)
|
||||
- [ ] Test plan has been peer reviewed by project stakeholders and other QA members
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
"status": "IN_PROGRESS",
|
||||
"githubWorkflowId": "${{ github.run_id }}"
|
||||
}'
|
||||
|
||||
|
||||
server-build:
|
||||
name: server-build
|
||||
uses: ./.github/workflows/server-build.yml
|
||||
|
|
@ -104,6 +104,12 @@ jobs:
|
|||
echo "Cleaning up the tar files"
|
||||
rm app/client/packages/rts/dist/rts-dist.tar
|
||||
|
||||
- name: Generate info.json
|
||||
run: |
|
||||
if [[ -f scripts/generate_info_json.sh ]]; then
|
||||
scripts/generate_info_json.sh
|
||||
fi
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
|
|
@ -121,6 +127,7 @@ jobs:
|
|||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-dp:${{ github.event.inputs.sub-domain-name }}
|
||||
build-args: |
|
||||
APPSMITH_CLOUD_SERVICES_BASE_URL=https://release-cs.appsmith.com
|
||||
BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:release
|
||||
|
||||
outputs:
|
||||
imageHash: ${{ github.event.inputs.sub-domain-name }}
|
||||
|
|
@ -190,4 +197,4 @@ jobs:
|
|||
"status": "FAILED"
|
||||
}'
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ on:
|
|||
pull_request:
|
||||
branches: [release, master]
|
||||
paths:
|
||||
- "deploy/docker/utils/**"
|
||||
- "deploy/docker/fs/opt/appsmith/utils/**"
|
||||
|
||||
# Change the working directory for all the jobs in this workflow
|
||||
defaults:
|
||||
run:
|
||||
working-directory: deploy/docker/utils/
|
||||
working-directory: deploy/docker/fs/opt/appsmith/utils/
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -97,7 +97,7 @@ jobs:
|
|||
echo "appsmithctl_run_result=failed" >> $GITHUB_OUTPUT > ~/appsmithctl_run_result
|
||||
exit 1;
|
||||
|
||||
|
||||
|
||||
# Set status = success
|
||||
- name: Save the status of the run
|
||||
run: echo "appsmithctl_run_result=success" >> $GITHUB_OUTPUT > ~/appsmithctl_run_result
|
||||
|
|
|
|||
|
|
@ -186,45 +186,63 @@ jobs:
|
|||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
# Deleting the existing dir's if any
|
||||
- name: Delete existing directories
|
||||
- name: Setup node
|
||||
if: needs.ci-test-limited.result != 'success'
|
||||
run: |
|
||||
rm -f ~/failed_spec_ci
|
||||
rm -f ~/combined_failed_spec_ci
|
||||
|
||||
# Force store previous cypress dashboard url from cache
|
||||
- name: Store the previous cypress dashboard url
|
||||
if: success()
|
||||
uses: actions/cache@v3
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
path: |
|
||||
~/cypress_url
|
||||
key: ${{ github.run_id }}-dashboard-url-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-dashboard-url
|
||||
node-version: 18
|
||||
|
||||
- name: Print cypress dashboard url
|
||||
id: dashboard_url
|
||||
run: |
|
||||
cypress_url=$(cat ~/cypress_url)
|
||||
echo "dashboard_url=$cypress_url" >> $GITHUB_OUTPUT
|
||||
|
||||
# Download failed_spec list for all jobs
|
||||
- uses: actions/download-artifact@v3
|
||||
- name: install pg
|
||||
if: needs.ci-test-limited.result != 'success'
|
||||
id: download_ci
|
||||
run: npm install pg
|
||||
|
||||
- name: Fetch the failed specs
|
||||
if: needs.ci-test-limited.result != 'success'
|
||||
id: failed_specs
|
||||
env:
|
||||
DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci
|
||||
script: |
|
||||
const { Pool } = require("pg");
|
||||
const { DB_HOST, DB_NAME, DB_USER, DB_PWD, RUN_ID, ATTEMPT_NUMBER } = process.env
|
||||
|
||||
const client = await new Pool({
|
||||
user: DB_USER,
|
||||
host: DB_HOST,
|
||||
database: DB_NAME,
|
||||
password: DB_PWD,
|
||||
port: 5432,
|
||||
connectionTimeoutMillis: 60000,
|
||||
}).connect();
|
||||
|
||||
const result = await client.query(
|
||||
`SELECT DISTINCT name FROM public."specs"
|
||||
WHERE "matrixId" IN
|
||||
(SELECT id FROM public."matrix"
|
||||
WHERE "attemptId" = (
|
||||
SELECT id FROM public."attempt" WHERE "workflowId" = $1 and "attempt" = $2
|
||||
)
|
||||
) AND status = 'fail'`,
|
||||
[RUN_ID, ATTEMPT_NUMBER],
|
||||
);
|
||||
client.release();
|
||||
return result.rows.map((spec) => spec.name);
|
||||
|
||||
# In case for any ci job failure, create combined failed spec
|
||||
- name: "combine all specs for CI"
|
||||
- name: combine all specs for CI
|
||||
id: combine_ci
|
||||
if: needs.ci-test-limited.result != 'success'
|
||||
run: |
|
||||
echo "Debugging: failed specs in ~/failed_spec_ci/failed_spec_ci*"
|
||||
cat ~/failed_spec_ci/failed_spec_ci*
|
||||
cat ~/failed_spec_ci/failed_spec_ci* | sort -u >> ~/combined_failed_spec_ci
|
||||
failed_specs=$(echo ${{steps.failed_specs.outputs.result}} | sed 's/\[\|\]//g' | tr -d ' ' | tr ',' '\n')
|
||||
while read -r line; do
|
||||
echo "$line" >> ~/combined_failed_spec_ci
|
||||
done <<< "$failed_specs"
|
||||
|
||||
# Upload combined failed CI spec list to a file
|
||||
# This is done for debugging.
|
||||
|
|
@ -258,9 +276,9 @@ jobs:
|
|||
issue-number: ${{fromJson(needs.file-check.outputs.pr)}}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Cypress dashboard: <a href="${{ steps.dashboard_url.outputs.dashboard_url }}" target="_blank"> Click here!</a>
|
||||
Cypress dashboard: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank"> Click here!</a>
|
||||
The following are new failures, please fix them before merging the PR: ${{env.new_failed_spec_env}}
|
||||
To know the list of identified flaky tests - <a href="https://app.appsmith.com/applications/613868bedd7786286ddd4a6a/pages/63ec710e8e503f763651791a" target="_blank">Refer here</a>
|
||||
To know the list of identified flaky tests - <a href="https://internal.appsmith.com/app/cypressdashboard/identified-flaky-tests-6541e22b0c243558fe2288ca?branch=master" target="_blank">Refer here</a>
|
||||
|
||||
- name: Add a comment on the PR when ci-test-limited is success
|
||||
if: needs.ci-test-limited.result == 'success' && needs.file-check.outputs.pr != '0'
|
||||
|
|
@ -269,7 +287,7 @@ jobs:
|
|||
issue-number: ${{fromJson(needs.file-check.outputs.pr)}}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Cypress dashboard url: <a href="${{ steps.dashboard_url.outputs.dashboard_url }}" target="_blank">Click here!</a>
|
||||
Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}" target="_blank">Click here!</a>
|
||||
All cypress tests have passed 🎉🎉🎉
|
||||
|
||||
- name: Check ci-test-limited set status
|
||||
|
|
@ -285,45 +303,63 @@ jobs:
|
|||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
# Deleting the existing dir's if any
|
||||
- name: Delete existing directories
|
||||
- name: Setup node
|
||||
if: needs.ci-test-limited-existing-docker-image.result != 'success'
|
||||
run: |
|
||||
rm -f ~/failed_spec_ci
|
||||
rm -f ~/combined_failed_spec_ci
|
||||
|
||||
# Force store previous cypress dashboard url from cache
|
||||
- name: Store the previous cypress dashboard url
|
||||
if: success()
|
||||
uses: actions/cache@v3
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
path: |
|
||||
~/cypress_url
|
||||
key: ${{ github.run_id }}-dashboard-url-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-dashboard-url
|
||||
node-version: 18
|
||||
|
||||
- name: Print cypress dashboard url
|
||||
id: dashboard_url
|
||||
run: |
|
||||
cypress_url=$(cat ~/cypress_url)
|
||||
echo "dashboard_url=$cypress_url" >> $GITHUB_OUTPUT
|
||||
|
||||
# Download failed_spec list for all jobs
|
||||
- uses: actions/download-artifact@v3
|
||||
- name: install pg
|
||||
if: needs.ci-test-limited-existing-docker-image.result != 'success'
|
||||
id: download_ci
|
||||
run: npm install pg
|
||||
|
||||
- name: Fetch the failed specs
|
||||
if: needs.ci-test-limited-existing-docker-image.result != 'success'
|
||||
id: failed_specs
|
||||
env:
|
||||
DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci
|
||||
script: |
|
||||
const { Pool } = require("pg");
|
||||
const { DB_HOST, DB_NAME, DB_USER, DB_PWD, RUN_ID, ATTEMPT_NUMBER } = process.env
|
||||
|
||||
const client = await new Pool({
|
||||
user: DB_USER,
|
||||
host: DB_HOST,
|
||||
database: DB_NAME,
|
||||
password: DB_PWD,
|
||||
port: 5432,
|
||||
connectionTimeoutMillis: 60000,
|
||||
}).connect();
|
||||
|
||||
const result = await client.query(
|
||||
`SELECT DISTINCT name FROM public."specs"
|
||||
WHERE "matrixId" IN
|
||||
(SELECT id FROM public."matrix"
|
||||
WHERE "attemptId" = (
|
||||
SELECT id FROM public."attempt" WHERE "workflowId" = $1 and "attempt" = $2
|
||||
)
|
||||
) AND status = 'fail'`,
|
||||
[RUN_ID, ATTEMPT_NUMBER],
|
||||
);
|
||||
client.release();
|
||||
return result.rows.map((spec) => spec.name);
|
||||
|
||||
# In case for any ci job failure, create combined failed spec
|
||||
- name: "combine all specs for CI"
|
||||
- name: combine all specs for CI
|
||||
id: combine_ci
|
||||
if: needs.ci-test-limited-existing-docker-image.result != 'success'
|
||||
run: |
|
||||
echo "Debugging: failed specs in ~/failed_spec_ci/failed_spec_ci*"
|
||||
cat ~/failed_spec_ci/failed_spec_ci*
|
||||
cat ~/failed_spec_ci/failed_spec_ci* | sort -u >> ~/combined_failed_spec_ci
|
||||
failed_specs=$(echo ${{steps.failed_specs.outputs.result}} | sed 's/\[\|\]//g' | tr -d ' ' | tr ',' '\n')
|
||||
while read -r line; do
|
||||
echo "$line" >> ~/combined_failed_spec_ci
|
||||
done <<< "$failed_specs"
|
||||
|
||||
# Upload combined failed CI spec list to a file
|
||||
# This is done for debugging.
|
||||
|
|
@ -357,9 +393,9 @@ jobs:
|
|||
issue-number: ${{fromJson(needs.file-check.outputs.pr)}}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Cypress dashboard: <a href="${{ steps.dashboard_url.outputs.dashboard_url }}" target="_blank"> Click here!</a>
|
||||
Cypress dashboard: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank"> Click here!</a>
|
||||
The following are new failures, please fix them before merging the PR: ${{env.new_failed_spec_env}}
|
||||
To know the list of identified flaky tests - <a href="https://app.appsmith.com/applications/613868bedd7786286ddd4a6a/pages/63ec710e8e503f763651791a" target="_blank">Refer here</a>
|
||||
To know the list of identified flaky tests - <a href="https://internal.appsmith.com/app/cypressdashboard/identified-flaky-tests-6541e22b0c243558fe2288ca?branch=master" target="_blank">Refer here</a>
|
||||
|
||||
- name: Add a comment on the PR when ci-test-limited-existing-docker-image is success
|
||||
if: needs.ci-test-limited-existing-docker-image.result == 'success' && needs.file-check.outputs.pr != '0'
|
||||
|
|
@ -368,7 +404,7 @@ jobs:
|
|||
issue-number: ${{fromJson(needs.file-check.outputs.pr)}}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Cypress dashboard url: <a href="${{ steps.dashboard_url.outputs.dashboard_url }}" target="_blank">Click here!</a>
|
||||
Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}" target="_blank">Click here!</a>
|
||||
All cypress tests have passed 🎉🎉🎉
|
||||
|
||||
- name: Check ci-test-limited-existing-docker-image set status
|
||||
|
|
|
|||
|
|
@ -79,19 +79,27 @@ jobs:
|
|||
echo "Cleaning up the tar files"
|
||||
rm app/client/packages/rts/dist/rts-dist.tar
|
||||
|
||||
- name: Generate info.json
|
||||
run: |
|
||||
if [[ -f scripts/generate_info_json.sh ]]; then
|
||||
scripts/generate_info_json.sh
|
||||
fi
|
||||
|
||||
# We don't use Depot Docker builds because it's faster for local Docker images to be built locally.
|
||||
# It's slower and more expensive to build these Docker images on Depot and download it back to the CI node.
|
||||
- name: Build docker image
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: "."
|
||||
run: |
|
||||
set -o xtrace
|
||||
declare -a args
|
||||
if [[ "${{ inputs.pr }}" != 0 ]]; then
|
||||
args+=(--cache-from "${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-${{ vars.EDITION }}:release")
|
||||
fi
|
||||
if [[ "${{ inputs.pr }}" != 0 || "${{ github.ref_name }}" != master ]]; then
|
||||
args+=(--build-arg "APPSMITH_CLOUD_SERVICES_BASE_URL=https://release-cs.appsmith.com")
|
||||
base_tag=release
|
||||
else
|
||||
base_tag=nightly
|
||||
fi
|
||||
args+=(--build-arg "BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:$base_tag")
|
||||
docker build -t cicontainer "${args[@]}" .
|
||||
|
||||
# Saving the docker image to tar file
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
key: ${{ github.run_id }}-failed_spec_ci_sanity-${{ github.job }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-failed_spec_ci_sanity-${{ github.job }}
|
||||
|
||||
|
||||
# failed_spec_env will contain list of all failed specs
|
||||
# We are using environment variable instead of regular to support multiline
|
||||
- name: Get failed_spec
|
||||
|
|
@ -151,15 +151,15 @@ jobs:
|
|||
cicontainer
|
||||
|
||||
- name: Setup MSSQL & Arango docker containers
|
||||
working-directory : app/client/cypress
|
||||
run : |
|
||||
working-directory: app/client/cypress
|
||||
run: |
|
||||
docker run --name=mssqldb -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Root@123" -p 1433:1433 -d mcr.microsoft.com/azure-sql-edge
|
||||
docker run --name arangodb -e ARANGO_USERNAME=root -e ARANGO_ROOT_PASSWORD=Arango -p 8529:8529 -d arangodb
|
||||
# docker exec -i mssqldb /bin/bash -c "echo -e '[mysqld]\ntcpport=1433\ntcpnodelay=1' >> /var/opt/mssql/mssql.conf"
|
||||
# docker restart mssqldb
|
||||
# sudo ufw allow 1433/tcp
|
||||
# docker cp init-mssql-dump-for-test.sql mssqldb:var/init-mssql-dump-for-test.sql
|
||||
# docker exec -i mssqldb /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P Root@123 -i /var/init-mssql-dump-for-test.sql
|
||||
# docker exec -i mssqldb /bin/bash -c "echo -e '[mysqld]\ntcpport=1433\ntcpnodelay=1' >> /var/opt/mssql/mssql.conf"
|
||||
# docker restart mssqldb
|
||||
# sudo ufw allow 1433/tcp
|
||||
# docker cp init-mssql-dump-for-test.sql mssqldb:var/init-mssql-dump-for-test.sql
|
||||
# docker exec -i mssqldb /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P Root@123 -i /var/init-mssql-dump-for-test.sql
|
||||
|
||||
- name: Use Node.js
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
|
|
@ -179,48 +179,6 @@ jobs:
|
|||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_URL: ${{ secrets.CYPRESS_URL }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
|
|
@ -253,6 +211,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
|
|
@ -272,6 +234,8 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
|
|
@ -313,6 +277,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
|
|
@ -332,6 +300,8 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
key: ${{ github.run_id }}-failed_spec_ci_smoke-${{ github.job }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-failed_spec_ci_smoke-${{ github.job }}
|
||||
|
||||
|
||||
# failed_spec_env will contain list of all failed specs
|
||||
# We are using environment variable instead of regular to support multiline
|
||||
- name: Get failed_spec
|
||||
|
|
@ -151,15 +151,15 @@ jobs:
|
|||
cicontainer
|
||||
|
||||
- name: Setup MSSQL & Arango docker containers
|
||||
working-directory : app/client/cypress
|
||||
run : |
|
||||
working-directory: app/client/cypress
|
||||
run: |
|
||||
docker run --name=mssqldb -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=Root@123" -p 1433:1433 -d mcr.microsoft.com/azure-sql-edge
|
||||
docker run --name arangodb -e ARANGO_USERNAME=root -e ARANGO_ROOT_PASSWORD=Arango -p 8529:8529 -d arangodb
|
||||
# docker exec -i mssqldb /bin/bash -c "echo -e '[mysqld]\ntcpport=1433\ntcpnodelay=1' >> /var/opt/mssql/mssql.conf"
|
||||
# docker restart mssqldb
|
||||
# sudo ufw allow 1433/tcp
|
||||
# docker cp init-mssql-dump-for-test.sql mssqldb:var/init-mssql-dump-for-test.sql
|
||||
# docker exec -i mssqldb /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P Root@123 -i /var/init-mssql-dump-for-test.sql
|
||||
# docker exec -i mssqldb /bin/bash -c "echo -e '[mysqld]\ntcpport=1433\ntcpnodelay=1' >> /var/opt/mssql/mssql.conf"
|
||||
# docker restart mssqldb
|
||||
# sudo ufw allow 1433/tcp
|
||||
# docker cp init-mssql-dump-for-test.sql mssqldb:var/init-mssql-dump-for-test.sql
|
||||
# docker exec -i mssqldb /opt/mssql-tools/bin/sqlcmd -S localhost -U SA -P Root@123 -i /var/init-mssql-dump-for-test.sql
|
||||
|
||||
- name: Use Node.js
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
|
|
@ -179,48 +179,6 @@ jobs:
|
|||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_URL: ${{ secrets.CYPRESS_URL }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
|
|
@ -253,6 +211,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
|
|
@ -272,6 +234,8 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
|
|
@ -313,6 +277,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
|
|
@ -332,6 +300,8 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
|
|
|
|||
|
|
@ -24,7 +24,69 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
|
||||
job:
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
51,
|
||||
52,
|
||||
53,
|
||||
54,
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
59,
|
||||
]
|
||||
|
||||
# Service containers to run with this job. Required for running tests
|
||||
services:
|
||||
|
|
@ -44,6 +106,12 @@ jobs:
|
|||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
# Check out merge commit
|
||||
- name: Fork based /ok-to-test checkout
|
||||
if: inputs.pr != 0
|
||||
|
|
@ -80,39 +148,17 @@ jobs:
|
|||
run: |
|
||||
run_result_env=$(cat ~/run_result)
|
||||
echo "run_result=$run_result_env" >> $GITHUB_OUTPUT
|
||||
if [[ "$run_result_env" == "failedtest" ]]; then
|
||||
echo "rerun=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "rerun=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Dump steps context
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: echo "$STEPS_CONTEXT"
|
||||
|
||||
# In case this is second attempt try restoring failed tests
|
||||
- if : steps.run_result.outputs.run_result == 'failedtest'
|
||||
run: echo "failed_spec_artifact=failed-spec-ci-$((${{github.run_attempt}}-1))" >> $GITHUB_ENV
|
||||
- name: Restore the previous failed combine result
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.failed_spec_artifact }}
|
||||
path: ~/failed_spec_ci
|
||||
|
||||
# failed_spec_env will contain list of all failed specs
|
||||
# We are using environment variable instead of regular to support multiline
|
||||
- name: Get failed_spec
|
||||
id: failed_spec
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
working-directory: app/client
|
||||
run: |
|
||||
failed_spec_env=""
|
||||
while IFS= read -r line
|
||||
do
|
||||
spec_name=$(echo $line | awk -F'/' '{print $NF}')
|
||||
failed_spec=$(find . -name $spec_name | sed 's|./||')
|
||||
failed_spec_env="$failed_spec_env,$failed_spec"
|
||||
done < ~/failed_spec_ci/failed_spec_ci-${{ matrix.job }}
|
||||
failed_spec_env=${failed_spec_env#,}
|
||||
echo "failed_spec_env=$failed_spec_env" >> $GITHUB_ENV
|
||||
|
||||
- if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
run: echo "Starting full run" && exit 0
|
||||
|
||||
|
|
@ -148,12 +194,43 @@ jobs:
|
|||
docker run --name test-event-driver -d -p 22:22 -p 5001:5001 -p 3306:3306 \
|
||||
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3001:3000 -p 6001:6001 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
|
||||
-v ~/git-server/repos:/git-server/repos appsmith/test-event-driver:latest
|
||||
docker run --name cloud-services -d -p 8000:80 -p 8090:8090 \
|
||||
--privileged --pid=host --ipc=host --add-host=host.docker.internal:host-gateway\
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_URI=mongodb://host.docker.internal:27017 \
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_DATABASE=cs \
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_AUTH_DATABASE=admin \
|
||||
-e APPSMITH_REDIS_URL=redis://host.docker.internal:6379/ \
|
||||
-e APPSMITH_APPS_API_KEY=dummy-api-key \
|
||||
-e APPSMITH_REMOTE_API_KEY=dummy-api-key \
|
||||
-e APPSMITH_GITHUB_API_KEY=dummy-appsmith-gh-api-key \
|
||||
-e APPSMITH_JWT_SECRET=appsmith-cloud-services-jwt-secret-dummy-key \
|
||||
-e APPSMITH_ENCRYPTION_SALT=encryption-salt \
|
||||
-e APPSMITH_ENCRYPTION_PASSWORD=encryption-password \
|
||||
-e APPSMITH_CLOUD_SERVICES_URL=https://cs-dev.appsmith.com \
|
||||
-e APPSMITH_CUSTOMER_PORTAL_URL=https://dev.appsmith.com \
|
||||
-e APPSMITH_CLOUD_SERVICES_BASE_URL=https://cs-dev.appsmith.com \
|
||||
-e APPSMITH_CLOUD_SERVER_BASE_URL=https://release.app.appsmith.com \
|
||||
-e AUTH0_ISSUER_URL=https://login.release-customer.appsmith.com/ \
|
||||
-e AUTH0_CLIENT_ID=dummy-client-id \
|
||||
-e AUTH0_CLIENT_SECRET=dummy-secret-id \
|
||||
-e AUTH0_AUDIENCE_URL=https://login.local-customer.appsmith.com/ \
|
||||
-e CLOUDSERVICES_URL=cs-dev.appsmith.com \
|
||||
-e CUSTOMER_URL=dev.appsmith.com \
|
||||
-e ENTERPRISE_USER_NAME=ent-user@appsmith.com \
|
||||
-e ENTERPRISE_USER_PASSWORD=ent_user_password \
|
||||
-e ENTERPRISE_ADMIN_NAME=ent-admin@appsmith.com \
|
||||
-e ENTERPRISE_ADMIN_PASSWORD=ent_admin_password \
|
||||
-e FLAGSMITH_URL=http://host.docker.internal:5001/flagsmith \
|
||||
-e FLAGSMITH_SERVER_KEY=dummykey \
|
||||
-e FLAGSMITH_SERVER_KEY_BUSINESS_FEATURES=dummykeybusinessfeatures \
|
||||
appsmith/cloud-services:release
|
||||
cd cicontainerlocal
|
||||
docker run -d --name appsmith -p 80:80 -p 9001:9001 \
|
||||
-v "$PWD/stacks:/appsmith-stacks" \
|
||||
-e APPSMITH_DISABLE_TELEMETRY=true \
|
||||
-e APPSMITH_INTERCOM_APP_ID=DUMMY_VALUE \
|
||||
-e APPSMITH_CLOUD_SERVICES_BASE_URL=http://host.docker.internal:5001 \
|
||||
-e APPSMITH_CLOUD_SERVICES_SIGNATURE_BASE_URL=http://host.docker.internal:8090 \
|
||||
--add-host=host.docker.internal:host-gateway --add-host=api.segment.io:host-gateway --add-host=t.appsmith.com:host-gateway \
|
||||
cicontainer
|
||||
|
||||
|
|
@ -185,49 +262,6 @@ jobs:
|
|||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
|
|
@ -239,69 +273,50 @@ jobs:
|
|||
- run: |
|
||||
echo "BROWSER_PATH=$(which chrome)" >> $GITHUB_ENV
|
||||
|
||||
- name: Run the cypress test
|
||||
if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
id: cypress_test
|
||||
uses: cypress-io/github-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
TOTAL_RUNNERS: ${{ strategy.job-total }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
CYPRESS_SPEC_PATTERN: "cypress/e2e/**/**/*"
|
||||
CYPRESS_ENV: "NODE_ENV=development"
|
||||
CYPRESS_CONFIG_FILE: cypress_ci_custom.config.ts
|
||||
CYPRESS_HEADLESS: "true"
|
||||
CYPRESS_BROWSER: ${{ env.BROWSER_PATH }}
|
||||
with:
|
||||
install: false
|
||||
working-directory: app/client
|
||||
command: yarn ts-node --require esm cypress/cypress-split.ts
|
||||
- name: Save Git values
|
||||
# pass env variables from this step to other steps
|
||||
# using GitHub Actions environment file
|
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#environment-files
|
||||
run: |
|
||||
PR_NUMBER=${{ inputs.pr }}
|
||||
echo COMMIT_INFO_BRANCH=$(git rev-parse --abbrev-ref HEAD) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_MESSAGE=OkToTest run on PR# ${{ inputs.pr }} >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_EMAIL=$(git show -s --pretty=%ae) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_AUTHOR=$(git show -s --pretty=%an) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_SHA=$(git show -s --pretty=%H) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_TIMESTAMP=$(git show -s --pretty=%ct) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_REMOTE=$(git config --get remote.origin.url) >> $GITHUB_ENV
|
||||
# delete the .git folder afterwords to use the environment values
|
||||
rm -rf .git
|
||||
|
||||
# In case of second attempt only run failed specs
|
||||
- name: Run the cypress test with failed tests
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
id: cypress_test_failedtest
|
||||
uses: cypress-io/github-action@v5
|
||||
- name: Show Git values
|
||||
run: |
|
||||
echo Branch $COMMIT_INFO_BRANCH
|
||||
echo Message $COMMIT_INFO_MESSAGE
|
||||
echo Email $COMMIT_INFO_EMAIL
|
||||
echo Author $COMMIT_INFO_AUTHOR
|
||||
echo SHA $COMMIT_INFO_SHA
|
||||
echo Timestamp $COMMIT_INFO_TIMESTAMP
|
||||
echo Remote $COMMIT_INFO_REMOTE
|
||||
|
||||
- name: Set Commit Message
|
||||
env:
|
||||
EVENT_COMMITS: ${{ toJson(github.event.commits[0].message) }}
|
||||
run: |
|
||||
eventCommit=$(echo ${{env.EVENT_COMMITS}} | sed "s/'//g")
|
||||
if [[ ${{ inputs.pr }} -ne 0 ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=${{ env.COMMIT_INFO_MESSAGE }}" >> $GITHUB_ENV
|
||||
else
|
||||
if [[ '$eventCommit' == 'null' ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo ${{ github.event_name }} | perl -pe 's/(^|_)./uc($&)/ge;s/_//g')" >> $GITHUB_ENV
|
||||
echo "COMMIT_INFO_MESSAGE=${{ env.COMMIT_INFO_MESSAGE}} by ${{ env.COMMIT_INFO_AUTHOR }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo "$eventCommit" | awk -F '\\\\n' '{print $1}' | sed 's/^"//;s/"$//')" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Run the cypress test
|
||||
uses: cypress-io/github-action@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
|
|
@ -318,6 +333,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
|
|
@ -338,19 +357,47 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_ENV: "NODE_ENV=development"
|
||||
CYPRESS_CONFIG_FILE: cypress_ci.config.ts
|
||||
CYPRESS_HEADLESS: "true"
|
||||
CYPRESS_BROWSER: ${{ env.BROWSER_PATH }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
CYPRESS_RERUN: ${{steps.run_result.outputs.rerun}}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
install: false
|
||||
config-file: cypress_ci_custom.config.ts
|
||||
working-directory: app/client
|
||||
command: yarn cypress run --browser ${{ env.BROWSER_PATH }} --config-file cypress_ci_custom.config.ts --spec ${{ env.failed_spec_env }}
|
||||
env: "NODE_ENV=development"
|
||||
|
||||
- name: Trim number of cypress log files
|
||||
if: failure()
|
||||
run: |
|
||||
find ${{ github.workspace }}/app/client/cypress/cypress-logs -name '*.json' -type f | tail -n +11 | xargs -I {} rm -- {}
|
||||
|
||||
- name: Upload failed test cypress logs artifact
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cypress-console-logs
|
||||
path: ${{ github.workspace }}/app/client/cypress/cypress-logs
|
||||
|
||||
- name: Collect CI container logs
|
||||
if: failure()
|
||||
|
|
@ -368,13 +415,13 @@ jobs:
|
|||
path: ~/dockerlogs
|
||||
|
||||
- name: Rename reports
|
||||
if: always()
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p ~/results
|
||||
mv ${{ github.workspace }}/app/client/results ~/results/${{ matrix.job }}
|
||||
|
||||
- name: Upload cypress report
|
||||
if: always()
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: results-${{github.run_attempt}}
|
||||
|
|
@ -387,28 +434,6 @@ jobs:
|
|||
echo "run_result=failedtest" >> $GITHUB_OUTPUT
|
||||
echo "failedtest" > ~/run_result
|
||||
|
||||
# Create a directory ~/failed_spec_ci and add a dummy file
|
||||
# This will ensure upload and download steps are successful
|
||||
- name: Create directory for failed tests
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p ~/failed_spec_ci-${{github.run_attempt}}
|
||||
|
||||
# add list failed tests to a file
|
||||
- name: In case of test failures copy them to a file
|
||||
if: failure()
|
||||
run: |
|
||||
cd ${{ github.workspace }}/app/client/cypress/
|
||||
find screenshots -type f \( -iname "*\(attempt 2\).png" -o -iname "*before all hook*" -o -iname "*after all hook*" \) | sed 's/screenshots/cypress\/e2e/g'| sed 's:/[^/]*$::' | sort -u > ~/failed_spec_ci-${{github.run_attempt}}/failed_spec_ci-${{ matrix.job }}
|
||||
|
||||
# Upload failed test list using common path for all matrix job
|
||||
- name: Upload failed test list artifact
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci-${{github.run_attempt}}
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: failure()
|
||||
|
|
@ -418,16 +443,6 @@ jobs:
|
|||
~/run_result
|
||||
key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }}
|
||||
|
||||
- name: get cypress url dashboard url
|
||||
id: dashboard_url
|
||||
if: always()
|
||||
run: |
|
||||
if [[ "${{steps.run_result.outputs.run_result }}" != "success" && "${{steps.run_result.outputs.run_result }}" != "failedtest" ]]; then
|
||||
echo "" >> ~/cypress_url
|
||||
elif [[ "${{steps.run_result.outputs.run_result }}" == "failedtest" ]]; then
|
||||
echo "" >> ~/cypress_url
|
||||
fi
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: success()
|
||||
|
|
|
|||
|
|
@ -86,36 +86,17 @@ jobs:
|
|||
run: |
|
||||
run_result_env=$(cat ~/run_result)
|
||||
echo "run_result=$run_result_env" >> $GITHUB_OUTPUT
|
||||
if [[ "$run_result_env" == "failedtest" ]]; then
|
||||
echo "rerun=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "rerun=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Dump steps context
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: echo "$STEPS_CONTEXT"
|
||||
|
||||
# In case this is second attempt try restoring failed tests
|
||||
- name: Restore the previous failed combine result
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: failed_spec_ci
|
||||
path: ~/failed_spec_ci
|
||||
|
||||
# failed_spec_env will contain list of all failed specs
|
||||
# We are using environment variable instead of regular to support multiline
|
||||
- name: Get failed_spec
|
||||
id: failed_spec
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
working-directory: app/client
|
||||
run: |
|
||||
echo "failed_spec_env<<EOF" >> $GITHUB_ENV
|
||||
while IFS= read -r line
|
||||
do
|
||||
spec_name=$(echo $line | awk -F'/' '{print $NF}')
|
||||
failed_spec_env=$(find . -name $spec_name | sed 's|./||')
|
||||
echo "$failed_spec_env" >> $GITHUB_ENV
|
||||
done < ~/failed_spec_ci/failed_spec_ci
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
- if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
run: echo "Starting full run" && exit 0
|
||||
|
||||
|
|
@ -153,50 +134,6 @@ jobs:
|
|||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_URL: ${{ secrets.CYPRESS_URL }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
|
|
@ -208,12 +145,6 @@ jobs:
|
|||
- run: |
|
||||
echo "BROWSER_PATH=$(which chrome)" >> $GITHUB_ENV
|
||||
|
||||
# - name: Set Pull Request Title
|
||||
# env:
|
||||
# EVENT_COMMITS: ${{ toJson(github.event.commits[0].message) }}
|
||||
# run: |
|
||||
# echo "${{ env.EVENT_COMMITS }}" | awk -F '\\\\n' '{print $1}'
|
||||
|
||||
- name: Save Git values
|
||||
# pass env variables from this step to other steps
|
||||
# using GitHub Actions environment file
|
||||
|
|
@ -245,19 +176,15 @@ jobs:
|
|||
EVENT_COMMITS: ${{ toJson(github.event.commits[0].message) }}
|
||||
run: |
|
||||
if [[ ${{ github.event_name }} == 'schedule' ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=Scheduled workflow run for gsheet tests" >> $GITHUB_ENV
|
||||
echo "COMMIT_INFO_MESSAGE=Scheduled run for Hosted tests" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=Manual workflow run for gsheet tests" >> $GITHUB_ENV
|
||||
echo "COMMIT_INFO_MESSAGE=Manual workflow run for Hosted tests" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Run the cypress test
|
||||
if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
id: cypress_test
|
||||
uses: cypress-io/github-action@v5
|
||||
uses: cypress-io/github-action@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
|
|
@ -272,6 +199,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
|
|
@ -292,87 +223,54 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
TOTAL_RUNNERS: ${{ strategy.job-total }}
|
||||
CYPRESS_RERUN: ${{steps.run_result.outputs.rerun}}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
record: true
|
||||
install: false
|
||||
parallel: true
|
||||
config-file: cypress_ci_hosted.config.ts
|
||||
group: "Chrome-Fat Container tests"
|
||||
spec: |
|
||||
cypress/e2e/Sanity/Datasources/Airtable_Basic_Spec.ts
|
||||
cypress/e2e/GSheet/**/**/*
|
||||
working-directory: app/client
|
||||
# tag will be either "push" or "pull_request"
|
||||
tag: ${{ github.event_name }}
|
||||
env: "NODE_ENV=development"
|
||||
|
||||
# In case of second attempt only run failed specs
|
||||
- name: Run the cypress test with failed tests
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
id: cypress_test_failedtest
|
||||
uses: cypress-io/github-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
- name: Rename reports
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p ~/results
|
||||
mv ${{ github.workspace }}/app/client/results ~/results/${{ matrix.job }}
|
||||
|
||||
- name: Upload cypress report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
record: true
|
||||
install: false
|
||||
parallel: true
|
||||
config-file: cypress_ci_hosted.config.ts
|
||||
group: "Chrome-Fat Container tests"
|
||||
spec: ${{ env.failed_spec_env }}
|
||||
working-directory: app/client
|
||||
# tag will be either "push" or "pull_request"
|
||||
tag: ${{ github.event_name }}
|
||||
env: "NODE_ENV=development"
|
||||
name: results-${{github.run_attempt}}
|
||||
path: ~/results
|
||||
|
||||
- name: Upload cypress snapshots
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: snapshots
|
||||
path: ${{ github.workspace }}/app/client/cypress/snapshots
|
||||
|
||||
# Set status = failedtest
|
||||
- name: Set fail if there are test failures
|
||||
|
|
@ -382,27 +280,6 @@ jobs:
|
|||
echo "run_result=failedtest" >> $GITHUB_OUTPUT
|
||||
echo "failedtest" > ~/run_result
|
||||
|
||||
# add list failed tests to a file
|
||||
- name: In case of test failures copy them to a file
|
||||
if: failure()
|
||||
run: |
|
||||
cd ${{ github.workspace }}/app/client/cypress/
|
||||
find screenshots -type f \( -iname "*\(attempt 2\).png" -o -iname "*before all hook*" -o -iname "*after all hook*" \) | sed 's/screenshots/cypress\/e2e/g'| sed 's:/[^/]*$::' | sort -u > ~/failed_spec_ci
|
||||
|
||||
# reset the failed_spec_ci file in case of success
|
||||
- name: In case of test success reset the failed_spec_ci file
|
||||
if: success()
|
||||
run: |
|
||||
touch ~/failed_spec_ci
|
||||
|
||||
# Upload failed test list using common path for all matrix job
|
||||
- name: Upload failed test list artifact
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed_spec_ci
|
||||
path: ~/failed_spec_ci
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: failure()
|
||||
|
|
@ -411,16 +288,6 @@ jobs:
|
|||
path: |
|
||||
~/run_result
|
||||
key: ${{ github.run_id }}-${{ github.job }}
|
||||
|
||||
- name: get cypress url dashboard url
|
||||
id: dashboard_url
|
||||
if: always()
|
||||
run: |
|
||||
if [[ "${{steps.run_result.outputs.run_result }}" != "success" && "${{steps.run_result.outputs.run_result }}" != "failedtest" ]]; then
|
||||
echo "url=${{ steps.cypress_test.outputs.resultsUrl }}" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{steps.run_result.outputs.run_result }}" == "failedtest" ]]; then
|
||||
echo "url=${{ steps.cypress_test_failedtest.outputs.resultsUrl }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Generate slack message
|
||||
continue-on-error: true
|
||||
|
|
@ -428,11 +295,13 @@ jobs:
|
|||
id: slack_notification
|
||||
run: |
|
||||
if [[ "${{ steps.test_status.outputs.run_result }}" == "failedtest" ]]; then
|
||||
echo "slack_message=There are test failures in the run. Please check the <${{ steps.dashboard_url.outputs.url }}|Cypress dashboard> for more details." >> $GITHUB_OUTPUT
|
||||
echo "slack_message=There are test failures in the run. Cypress Dashboard: <https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}&selectiontype=test&testsstatus=failed&specsstatus=fail|Click here!>" >> $GITHUB_OUTPUT
|
||||
echo "slack_color=#FF0000" >> $GITHUB_OUTPUT
|
||||
echo "slack_icon=:parachute:" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "slack_message=All tests passed successfully :tada: . Cypress Dashboard: <${{ steps.dashboard_url.outputs.url }}|Click here!>" >> $GITHUB_OUTPUT
|
||||
echo "slack_message=All tests passed successfully :tada: . Cypress Dashboard: <https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}|Click here!>" >> $GITHUB_OUTPUT
|
||||
echo "slack_color=#00FF00" >> $GITHUB_OUTPUT
|
||||
echo "slack_icon=:eight_spoked_asterisk:" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Slack Notification
|
||||
|
|
@ -442,21 +311,13 @@ jobs:
|
|||
env:
|
||||
SLACK_CHANNEL: cypresspushworkflow
|
||||
SLACK_COLOR: ${{steps.slack_notification.outputs.slack_color}}
|
||||
SLACK_ICON_EMOJI: ':bell:'
|
||||
SLACK_ICON_EMOJI: ${{steps.slack_notification.outputs.slack_icon}}
|
||||
SLACK_MESSAGE: ${{steps.slack_notification.outputs.slack_message}}
|
||||
SLACK_TITLE: 'Result:'
|
||||
SLACK_USERNAME: Cloud-Hosted Tests
|
||||
SLACK_TITLE: "Result:"
|
||||
SLACK_USERNAME: Cloud Hosted Run
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_HOSTED }}
|
||||
MSG_MINIMAL: Ref,Event,Commit
|
||||
SLACK_FOOTER: 'Appsmith CI runs'
|
||||
|
||||
# Upload the log artifact so that it can be used by the test & deploy job in the workflow
|
||||
- name: Upload server logs bundle on failure
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: server-logs-${{ matrix.job }}
|
||||
path: app/server/server-logs.log
|
||||
SLACK_FOOTER: "Hosted run"
|
||||
|
||||
# Set status = success
|
||||
- name: Save the status of the run
|
||||
|
|
|
|||
|
|
@ -3,6 +3,22 @@ name: Appsmith CI run limited Tests Workflow
|
|||
on:
|
||||
# This line enables manual triggering of this workflow.
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr:
|
||||
description: "PR number"
|
||||
required: false
|
||||
type: number
|
||||
default: 0
|
||||
previous-workflow-run-id:
|
||||
description: "Workflow ID (To Download cicontainer)"
|
||||
required: false
|
||||
type: number
|
||||
default: 0
|
||||
matrix:
|
||||
description: "Matrix jobs"
|
||||
required: false
|
||||
type: string
|
||||
default: "[0, 1, 2]"
|
||||
workflow_call:
|
||||
inputs:
|
||||
pr:
|
||||
|
|
@ -55,6 +71,12 @@ jobs:
|
|||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
# Check out merge commit
|
||||
- name: Fork based /ok-to-test checkout
|
||||
if: inputs.pr != 0
|
||||
|
|
@ -89,46 +111,28 @@ jobs:
|
|||
id: run_result
|
||||
run: |
|
||||
run_result_env=$(cat ~/run_result)
|
||||
echo "::set-output name=run_result::$run_result_env"
|
||||
|
||||
# In case this is second attempt try restoring failed tests
|
||||
- name: Restore the previous failed combine result
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: combined_failed_spec_ci
|
||||
path: ~/combined_failed_spec_ci
|
||||
|
||||
# failed_spec_env will contain list of all failed specs
|
||||
# We are using environment variable instead of regular to support multiline
|
||||
- name: Get failed_spec
|
||||
id: failed_spec
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
working-directory: app/client
|
||||
run: |
|
||||
echo "failed_spec_env<<EOF" >> $GITHUB_ENV
|
||||
while IFS= read -r line
|
||||
do
|
||||
spec_name=$(echo $line | awk -F'/' '{print $NF}')
|
||||
failed_spec_env=$(find . -name $spec_name | sed 's|./||')
|
||||
echo "$failed_spec_env" >> $GITHUB_ENV
|
||||
done < ~/combined_failed_spec_ci/combined_failed_spec_ci
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
echo "run_result=$run_result_env" >> $GITHUB_OUTPUT
|
||||
if [[ "$run_result_env" == "failedtest" ]]; then
|
||||
echo "rerun=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "rerun=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Get specs to run
|
||||
- name: Get specs to run
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
run: |
|
||||
echo "specs_to_run<<EOF" >> $GITHUB_ENV
|
||||
specs_to_run=""
|
||||
while IFS= read -r line
|
||||
do
|
||||
if [[ $line =~ ^#|^\/\/ ]]; then
|
||||
continue
|
||||
else
|
||||
echo "$line" >> $GITHUB_ENV
|
||||
specs_to_run="$specs_to_run,$line"
|
||||
fi
|
||||
done < app/client/cypress/limited-tests.txt
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
specs_to_run=${specs_to_run#,}
|
||||
echo "specs_to_run=$specs_to_run" >> $GITHUB_ENV
|
||||
|
||||
# In case of run-id provided download the artifact from the previous run
|
||||
- name: Download Docker image artifact
|
||||
|
|
@ -166,6 +170,36 @@ jobs:
|
|||
docker run --name test-event-driver -d -p 22:22 -p 5001:5001 -p 3306:3306 \
|
||||
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3001:3000 -p 6001:6001 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
|
||||
-v ~/git-server/repos:/git-server/repos appsmith/test-event-driver:latest
|
||||
docker run --name cloud-services -d -p 8000:80 -p 8090:8090 \
|
||||
--privileged --pid=host --ipc=host --add-host=host.docker.internal:host-gateway\
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_URI=mongodb://host.docker.internal:27017 \
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_DATABASE=cs \
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_AUTH_DATABASE=admin \
|
||||
-e APPSMITH_REDIS_URL=redis://host.docker.internal:6379/ \
|
||||
-e APPSMITH_APPS_API_KEY=dummy-api-key \
|
||||
-e APPSMITH_REMOTE_API_KEY=dummy-api-key \
|
||||
-e APPSMITH_GITHUB_API_KEY=dummy-appsmith-gh-api-key \
|
||||
-e APPSMITH_JWT_SECRET=appsmith-cloud-services-jwt-secret-dummy-key \
|
||||
-e APPSMITH_ENCRYPTION_SALT=encryption-salt \
|
||||
-e APPSMITH_ENCRYPTION_PASSWORD=encryption-password \
|
||||
-e APPSMITH_CLOUD_SERVICES_URL=https://cs-dev.appsmith.com \
|
||||
-e APPSMITH_CUSTOMER_PORTAL_URL=https://dev.appsmith.com \
|
||||
-e APPSMITH_CLOUD_SERVICES_BASE_URL=https://cs-dev.appsmith.com \
|
||||
-e APPSMITH_CLOUD_SERVER_BASE_URL=https://release.app.appsmith.com \
|
||||
-e AUTH0_ISSUER_URL=https://login.release-customer.appsmith.com/ \
|
||||
-e AUTH0_CLIENT_ID=dummy-client-id \
|
||||
-e AUTH0_CLIENT_SECRET=dummy-secret-id \
|
||||
-e AUTH0_AUDIENCE_URL=https://login.local-customer.appsmith.com/ \
|
||||
-e CLOUDSERVICES_URL=cs-dev.appsmith.com \
|
||||
-e CUSTOMER_URL=dev.appsmith.com \
|
||||
-e ENTERPRISE_USER_NAME=ent-user@appsmith.com \
|
||||
-e ENTERPRISE_USER_PASSWORD=ent_user_password \
|
||||
-e ENTERPRISE_ADMIN_NAME=ent-admin@appsmith.com \
|
||||
-e ENTERPRISE_ADMIN_PASSWORD=ent_admin_password \
|
||||
-e FLAGSMITH_URL=http://host.docker.internal:5001/flagsmith \
|
||||
-e FLAGSMITH_SERVER_KEY=dummykey \
|
||||
-e FLAGSMITH_SERVER_KEY_BUSINESS_FEATURES=dummykeybusinessfeatures \
|
||||
appsmith/cloud-services:release
|
||||
cd cicontainerlocal
|
||||
docker run -d --name appsmith -p 80:80 -p 9001:9001 \
|
||||
-v "$PWD/stacks:/appsmith-stacks" \
|
||||
|
|
@ -201,50 +235,6 @@ jobs:
|
|||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_URL: ${{ secrets.CYPRESS_URL }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
|
|
@ -256,12 +246,6 @@ jobs:
|
|||
- run: |
|
||||
echo "BROWSER_PATH=$(which chrome)" >> $GITHUB_ENV
|
||||
|
||||
# - name: Set Pull Request Title
|
||||
# env:
|
||||
# EVENT_COMMITS: ${{ toJson(github.event.commits[0].message) }}
|
||||
# run: |
|
||||
# echo "test: Cypress (#24586)\n\n## Description\r\n- This PR adds the No Error toast to NavigateBacktoEditor() which\r\nsometimes results in Edit page not being load in CI runs" | awk -F '\\\\n' '{sub(/.*#/, "#", $1); sub(/).*/, "", $1); print $1}'
|
||||
|
||||
- name: Save Git values
|
||||
# pass env variables from this step to other steps
|
||||
# using GitHub Actions environment file
|
||||
|
|
@ -296,17 +280,17 @@ jobs:
|
|||
elif [[ ${{ inputs.pr }} -ne 0 && ${{github.event_name}} == 'workflow_dispatch' ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=Workflow run on PR# ${{ inputs.pr }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo \"${{ env.EVENT_COMMITS }}\" | awk -F '\\\\n' '{print $1}' | sed 's/^\"//')" >> $GITHUB_ENV
|
||||
if [[ '${{env.EVENT_COMMITS}}' == 'null' ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=${{ github.event_name }} by ${{ env.COMMIT_INFO_AUTHOR }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo \"${{ env.EVENT_COMMITS }}\" | awk -F '\\\\n' '{print $1}' | sed 's/^\"//')" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Run the cypress test
|
||||
id: cypress_test
|
||||
if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
uses: cypress-io/github-action@v5
|
||||
uses: cypress-io/github-action@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
|
|
@ -321,6 +305,10 @@ jobs:
|
|||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
|
|
@ -341,86 +329,56 @@ jobs:
|
|||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
CYPRESS_SPECS: ${{ env.specs_to_run }}
|
||||
CYPRESS_RERUN: ${{steps.run_result.outputs.rerun}}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
record: true
|
||||
install: false
|
||||
parallel: true
|
||||
config-file: cypress_ci.config.ts
|
||||
group: "Chrome-Fat Container tests"
|
||||
config-file: cypress_ci_custom.config.ts
|
||||
spec: ${{ env.specs_to_run }}
|
||||
working-directory: app/client
|
||||
# tag will be either "push" or "pull_request"
|
||||
tag: ${{ github.event_name }}
|
||||
env: "NODE_ENV=development"
|
||||
|
||||
# In case of second attempt only run failed specs
|
||||
- name: Run the cypress test with failed tests
|
||||
id: cypress_test_failedtest
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
uses: cypress-io/github-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
CYPRESS_PROJECT_ID: ${{ secrets.CYPRESS_PROJECT_ID }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
- name: Trim number of cypress log files
|
||||
if: failure()
|
||||
run: |
|
||||
find ${{ github.workspace }}/app/client/cypress/cypress-logs -name '*.json' -type f | tail -n +11 | xargs -I {} rm -- {}
|
||||
|
||||
- name: Upload failed test cypress logs artifact
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
record: true
|
||||
install: false
|
||||
parallel: true
|
||||
config-file: cypress_ci.config.ts
|
||||
group: "Chrome-Fat Container tests"
|
||||
spec: ${{ env.failed_spec_env }}
|
||||
working-directory: app/client
|
||||
# tag will be either "push" or "pull_request"
|
||||
tag: ${{ github.event_name }}
|
||||
env: "NODE_ENV=development"
|
||||
name: cypress-console-logs
|
||||
path: ${{ github.workspace }}/app/client/cypress/cypress-logs
|
||||
|
||||
- name: Upload cypress snapshots
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: snapshots
|
||||
path: ${{ github.workspace }}/app/client/cypress/snapshots
|
||||
|
||||
- name: Collect CI container logs
|
||||
if: failure()
|
||||
|
|
@ -437,35 +395,25 @@ jobs:
|
|||
name: dockerlogs
|
||||
path: ~/dockerlogs
|
||||
|
||||
- name: Rename reports
|
||||
if: failure()
|
||||
run: |
|
||||
mkdir -p ~/results
|
||||
mv ${{ github.workspace }}/app/client/results ~/results/${{ matrix.job }}
|
||||
|
||||
- name: Upload cypress report
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: results-${{github.run_attempt}}
|
||||
path: ~/results
|
||||
|
||||
# Set status = failedtest
|
||||
- name: Set fail if there are test failures
|
||||
if: failure()
|
||||
run: |
|
||||
echo "::set-output name=run_result::failedtest"
|
||||
echo "failedtest" > ~/run_result
|
||||
|
||||
# Create a directory ~/failed_spec_ci and add a dummy file
|
||||
# This will ensure upload and download steps are successful
|
||||
- name: Create directory for failed tests
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p ~/failed_spec_ci-${{github.run_attempt}}
|
||||
|
||||
# add list failed tests to a file
|
||||
- name: In case of test failures copy them to a file
|
||||
if: failure()
|
||||
run: |
|
||||
cd ${{ github.workspace }}/app/client/cypress/
|
||||
find screenshots -type f \( -iname "*\(attempt 2\).png" -o -iname "*before all hook*" -o -iname "*after all hook*" \) | sed 's/screenshots/cypress\/e2e/g'| sed 's:/[^/]*$::' | sort -u > ~/failed_spec_ci-${{github.run_attempt}}/failed_spec_ci-${{ matrix.job }}
|
||||
|
||||
# Upload failed test list using common path for all matrix job
|
||||
- name: Upload failed test list artifact
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci-${{github.run_attempt}}
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: failure()
|
||||
|
|
@ -485,25 +433,6 @@ jobs:
|
|||
name: server-logs-${{ matrix.job }}
|
||||
path: app/server/server-logs.log
|
||||
|
||||
- name: get cypress url dashboard url
|
||||
id: dashboard_url
|
||||
if: always()
|
||||
run: |
|
||||
if [[ "${{steps.run_result.outputs.run_result }}" != "success" && "${{steps.run_result.outputs.run_result }}" != "failedtest" ]]; then
|
||||
echo ${{ steps.cypress_test.outputs.resultsUrl }} >> ~/cypress_url
|
||||
elif [[ "${{steps.run_result.outputs.run_result }}" == "failedtest" ]]; then
|
||||
echo ${{ steps.cypress_test_failedtest.outputs.resultsUrl }} >> ~/cypress_url
|
||||
fi
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: success()
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: |
|
||||
~/cypress_url
|
||||
key: ${{ github.run_id }}-dashboard-url-${{ github.run_attempt }}
|
||||
|
||||
# Set status = success
|
||||
- name: Save the status of the run
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,627 @@
|
|||
name: Appsmith CI Test (with DocumentDB) Workflow
|
||||
|
||||
on:
|
||||
# This line enables manual triggering of this workflow.
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
pr:
|
||||
description: "This is the PR number in case the workflow is being called in a pull request"
|
||||
required: false
|
||||
type: number
|
||||
|
||||
jobs:
|
||||
ci-test:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
github.event_name == 'repository_dispatch'
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
[
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
31,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36,
|
||||
37,
|
||||
38,
|
||||
39,
|
||||
40,
|
||||
41,
|
||||
42,
|
||||
43,
|
||||
44,
|
||||
45,
|
||||
46,
|
||||
47,
|
||||
48,
|
||||
49,
|
||||
50,
|
||||
51,
|
||||
52,
|
||||
53,
|
||||
54,
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
58,
|
||||
59,
|
||||
]
|
||||
|
||||
# Service containers to run with this job. Required for running tests
|
||||
services:
|
||||
# Label used to access the service container
|
||||
redis:
|
||||
# Docker Hub image for Redis
|
||||
image: redis
|
||||
ports:
|
||||
# Opens tcp port 6379 on the host and service container
|
||||
- 6379:6379
|
||||
mongo:
|
||||
image: mongo
|
||||
ports:
|
||||
- 27017:27017
|
||||
|
||||
steps:
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
# Check out merge commit
|
||||
- name: Fork based /ok-to-test checkout
|
||||
if: inputs.pr != 0
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: "refs/pull/${{ inputs.pr }}/merge"
|
||||
|
||||
# Checkout the code in the current branch in case the workflow is called because of a branch push event
|
||||
- name: Checkout the head commit of the branch
|
||||
if: inputs.pr == 0
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Timestamp will be used to create cache key
|
||||
- id: timestamp
|
||||
run: echo "::set-output name=timestamp::$(date +'%Y-%m-%dT%H:%M:%S')"
|
||||
|
||||
# In case this is second attempt try restoring status of the prior attempt from cache
|
||||
- name: Restore the previous run result
|
||||
id: cache-appsmith
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/run_result
|
||||
key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-${{ github.job }}-${{ matrix.job }}
|
||||
|
||||
- name: Get the previous run result
|
||||
if: steps.cache-appsmith.outputs.cache-hit == 'true'
|
||||
id: run_result
|
||||
run: |
|
||||
run_result_env=$(cat ~/run_result)
|
||||
echo "run_result=$run_result_env" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Dump steps context
|
||||
env:
|
||||
STEPS_CONTEXT: ${{ toJson(steps) }}
|
||||
run: echo "$STEPS_CONTEXT"
|
||||
|
||||
# In case this is second attempt try restoring failed tests
|
||||
- if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
run: echo "failed_spec_artifact=failed-spec-ci-$((${{github.run_attempt}}-1))" >> $GITHUB_ENV
|
||||
- name: Restore the previous failed combine result
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.failed_spec_artifact }}
|
||||
path: ~/failed_spec_ci
|
||||
|
||||
# failed_spec_env will contain list of all failed specs
|
||||
# We are using environment variable instead of regular to support multiline
|
||||
- name: Get failed_spec
|
||||
id: failed_spec
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
working-directory: app/client
|
||||
run: |
|
||||
failed_spec_env=""
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
file_path=$(echo "$line" | awk -F'/' '{print $(NF-1)"/"$NF}')
|
||||
spec_name=$(echo "$file_path" | awk -F'/' '{print $NF}')
|
||||
failed_spec=$(find . -name "$spec_name" | sed 's|./||')
|
||||
if [ "$(echo "$failed_spec" | wc -l)" -eq 1 ]; then
|
||||
failed_spec_env="$failed_spec_env,$failed_spec"
|
||||
else
|
||||
for file in $failed_spec; do
|
||||
new_file_path=$(echo "$file" | awk -F'/' '{print $(NF-1)"/"$NF}')
|
||||
if [ "$new_file_path" == "$file_path" ]; then
|
||||
failed_spec_env="$failed_spec_env,$file"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done < ~/failed_spec_ci/failed_spec_ci-${{ matrix.job }}
|
||||
failed_spec_env=${failed_spec_env#,}
|
||||
echo "failed_spec_env=$failed_spec_env" >> $GITHUB_ENV
|
||||
|
||||
- if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
run: echo "Starting full run" && exit 0
|
||||
|
||||
- if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
run: echo "Rerunning failed tests" && exit 0
|
||||
|
||||
- name: cat run_result
|
||||
run: echo ${{ steps.run_result.outputs.run_result }}
|
||||
|
||||
- name: Setup mongodb-tools
|
||||
run: |
|
||||
wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-ubuntu2204-x86_64-100.6.1.deb
|
||||
sudo apt install ./mongodb-database-tools-*-100.6.1.deb
|
||||
|
||||
- name: Download mongodb archive
|
||||
run: |
|
||||
curl -o data.gz https://appsmithctl-backup-restore-test.s3.ap-south-1.amazonaws.com/docdb-data.gz
|
||||
|
||||
- name: Download Docker image artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: cicontainer
|
||||
|
||||
- name: Load Docker image from tar file
|
||||
run: |
|
||||
gunzip cicontainer.tar.gz
|
||||
docker load -i cicontainer.tar
|
||||
|
||||
- name: Create folder
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: "."
|
||||
run: |
|
||||
mkdir -p cicontainerlocal/stacks/configuration/
|
||||
|
||||
- name: Set up SSH key for tunnel
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.APPSMITH_CI_TUNNEL_PRIVATE_KEY }}
|
||||
run: |
|
||||
echo "$SSH_PRIVATE_KEY" > ssh_key.pem
|
||||
chmod 400 ssh_key.pem
|
||||
|
||||
- name: Setup SSH tunnel to AWS DocumentDB instance
|
||||
run: |
|
||||
chmod 400 ssh_key.pem
|
||||
ssh -4 -o StrictHostKeyChecking=no -o ServerAliveInterval=180 -o ServerAliveCountMax=5 -i "ssh_key.pem" -L 0.0.0.0:27010:docdb-ansible-test-cluster.cluster-cz8diybf9wdj.ap-south-1.docdb.amazonaws.com:27017 ubuntu@65.1.106.35 -N -f
|
||||
|
||||
- name: Run Appsmith, CS & TED docker image
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: "."
|
||||
env:
|
||||
APPSMITH_MONGODB_URI: ${{ secrets.INTERNAL_CI_DOC_DB_URI }}
|
||||
|
||||
run: |
|
||||
timestamp=$(date +%Y%m%d%H%M%S)
|
||||
hash=$(hostname)
|
||||
random=$(shuf -i 1000-9999 -n 1)
|
||||
DB_NAME="${timestamp}-${hash}-${random}"
|
||||
echo "DB_NAME: ${DB_NAME}"
|
||||
MONGO_CREDS=$(echo $APPSMITH_MONGODB_URI | sed 's/@.*//')
|
||||
URI="${MONGO_CREDS}@localhost:27010/${DB_NAME}?retryWrites=false&replicaSet=rs0&directConnection=true"
|
||||
mongorestore --uri="${URI}" --archive=data.gz --gzip --drop --nsInclude "doc-db-base.*" --nsFrom "doc-db-base.*" --nsTo "${DB_NAME}.*"
|
||||
sudo /etc/init.d/ssh stop ;
|
||||
mkdir -p ~/git-server/keys
|
||||
mkdir -p ~/git-server/repos
|
||||
docker run --name test-event-driver -d -p 22:22 -p 5001:5001 -p 3306:3306 \
|
||||
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3001:3000 -p 6001:6001 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
|
||||
-v ~/git-server/repos:/git-server/repos appsmith/test-event-driver:latest
|
||||
docker run --name cloud-services -d -p 8000:80 -p 8090:8090 \
|
||||
--privileged --pid=host --ipc=host --add-host=host.docker.internal:host-gateway\
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_URI=mongodb://host.docker.internal:27017 \
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_DATABASE=cs \
|
||||
-e APPSMITH_CLOUD_SERVICES_MONGODB_AUTH_DATABASE=admin \
|
||||
-e APPSMITH_REDIS_URL=redis://host.docker.internal:6379/ \
|
||||
-e APPSMITH_APPS_API_KEY=dummy-api-key \
|
||||
-e APPSMITH_REMOTE_API_KEY=dummy-api-key \
|
||||
-e APPSMITH_GITHUB_API_KEY=dummy-appsmith-gh-api-key \
|
||||
-e APPSMITH_JWT_SECRET=appsmith-cloud-services-jwt-secret-dummy-key \
|
||||
-e APPSMITH_ENCRYPTION_SALT=encryption-salt \
|
||||
-e APPSMITH_ENCRYPTION_PASSWORD=encryption-password \
|
||||
-e APPSMITH_CLOUD_SERVICES_URL=https://cs-dev.appsmith.com \
|
||||
-e APPSMITH_CUSTOMER_PORTAL_URL=https://dev.appsmith.com \
|
||||
-e APPSMITH_CLOUD_SERVICES_BASE_URL=https://cs-dev.appsmith.com \
|
||||
-e APPSMITH_CLOUD_SERVER_BASE_URL=https://release.app.appsmith.com \
|
||||
-e AUTH0_ISSUER_URL=https://login.release-customer.appsmith.com/ \
|
||||
-e AUTH0_CLIENT_ID=dummy-client-id \
|
||||
-e AUTH0_CLIENT_SECRET=dummy-secret-id \
|
||||
-e AUTH0_AUDIENCE_URL=https://login.local-customer.appsmith.com/ \
|
||||
-e CLOUDSERVICES_URL=cs-dev.appsmith.com \
|
||||
-e CUSTOMER_URL=dev.appsmith.com \
|
||||
-e ENTERPRISE_USER_NAME=ent-user@appsmith.com \
|
||||
-e ENTERPRISE_USER_PASSWORD=ent_user_password \
|
||||
-e ENTERPRISE_ADMIN_NAME=ent-admin@appsmith.com \
|
||||
-e ENTERPRISE_ADMIN_PASSWORD=ent_admin_password \
|
||||
appsmith/cloud-services:release
|
||||
cd cicontainerlocal
|
||||
docker run -d --name appsmith -p 80:80 -p 9001:9001 \
|
||||
-v "$PWD/stacks:/appsmith-stacks" \
|
||||
-e APPSMITH_DISABLE_TELEMETRY=true \
|
||||
-e APPSMITH_INTERCOM_APP_ID=DUMMY_VALUE \
|
||||
-e APPSMITH_CLOUD_SERVICES_BASE_URL=http://host.docker.internal:5001 \
|
||||
-e APPSMITH_MONGODB_URI="${APPSMITH_MONGODB_URI}${DB_NAME}?retryWrites=false&replicaSet=rs0&directConnection=true" \
|
||||
--add-host=host.docker.internal:host-gateway --add-host=api.segment.io:host-gateway --add-host=t.appsmith.com:host-gateway \
|
||||
cicontainer
|
||||
|
||||
- name: Use Node.js
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: app/client/package.json
|
||||
|
||||
# actions/setup-node@v3 doesn’t work properly with Yarn 3
|
||||
# when the project lives in a subdirectory: https://github.com/actions/setup-node/issues/488
|
||||
# Restoring the cache manually instead
|
||||
- name: Restore Yarn cache
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: app/client/.yarn/cache
|
||||
key: v1-yarn3-${{ hashFiles('app/client/yarn.lock') }}
|
||||
restore-keys: |
|
||||
v1-yarn3-
|
||||
|
||||
# Install all the dependencies
|
||||
- name: Install dependencies
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: app/client
|
||||
run: |
|
||||
yarn install --immutable
|
||||
|
||||
- name: Wait until appsmith server is healthy
|
||||
run: |
|
||||
bash scripts/health_check.sh
|
||||
|
||||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
./cypress/setup-test-ci.sh
|
||||
|
||||
- uses: browser-actions/setup-chrome@latest
|
||||
with:
|
||||
chrome-version: stable
|
||||
- run: |
|
||||
echo "BROWSER_PATH=$(which chrome)" >> $GITHUB_ENV
|
||||
|
||||
- name: Save Git values
|
||||
# pass env variables from this step to other steps
|
||||
# using GitHub Actions environment file
|
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#environment-files
|
||||
run: |
|
||||
PR_NUMBER=${{ inputs.pr }}
|
||||
echo COMMIT_INFO_BRANCH=$(git rev-parse --abbrev-ref HEAD) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_MESSAGE=OkToTest run on PR# ${{ inputs.pr }} >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_EMAIL=$(git show -s --pretty=%ae) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_AUTHOR=$(git show -s --pretty=%an) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_SHA=$(git show -s --pretty=%H) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_TIMESTAMP=$(git show -s --pretty=%ct) >> $GITHUB_ENV
|
||||
echo COMMIT_INFO_REMOTE=$(git config --get remote.origin.url) >> $GITHUB_ENV
|
||||
# delete the .git folder afterwords to use the environment values
|
||||
rm -rf .git
|
||||
|
||||
- name: Show Git values
|
||||
run: |
|
||||
echo Branch $COMMIT_INFO_BRANCH
|
||||
echo Message $COMMIT_INFO_MESSAGE
|
||||
echo Email $COMMIT_INFO_EMAIL
|
||||
echo Author $COMMIT_INFO_AUTHOR
|
||||
echo SHA $COMMIT_INFO_SHA
|
||||
echo Timestamp $COMMIT_INFO_TIMESTAMP
|
||||
echo Remote $COMMIT_INFO_REMOTE
|
||||
|
||||
- name: Set Commit Message
|
||||
env:
|
||||
EVENT_COMMITS: ${{ toJson(github.event.commits[0].message) }}
|
||||
run: |
|
||||
if [[ ${{ inputs.pr }} -ne 0 ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=${{ env.COMMIT_INFO_MESSAGE }}" >> $GITHUB_ENV
|
||||
else
|
||||
if [[ '${{env.EVENT_COMMITS}}' == 'null' ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=${{ github.event_name }} by ${{ env.COMMIT_INFO_AUTHOR }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo \"${{ env.EVENT_COMMITS }}\" | awk -F '\\\\n' '{print $1}' | sed 's/^\"//')" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Run the cypress test
|
||||
if: steps.run_result.outputs.run_result != 'success' && steps.run_result.outputs.run_result != 'failedtest'
|
||||
id: cypress_test
|
||||
uses: cypress-io/github-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
TOTAL_RUNNERS: ${{ strategy.job-total }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
CYPRESS_SPEC_PATTERN: "cypress/e2e/**/**/*"
|
||||
CYPRESS_ENV: "NODE_ENV=development"
|
||||
CYPRESS_CONFIG_FILE: cypress_ci_custom.config.ts
|
||||
CYPRESS_HEADLESS: "true"
|
||||
CYPRESS_BROWSER: ${{ env.BROWSER_PATH }}
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
install: false
|
||||
working-directory: app/client
|
||||
command: yarn ts-node --require esm cypress/cypress-split.ts
|
||||
|
||||
# In case of second attempt only run failed specs
|
||||
- name: Run the cypress test with failed tests
|
||||
if: steps.run_result.outputs.run_result == 'failedtest'
|
||||
id: cypress_test_failedtest
|
||||
uses: cypress-io/github-action@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_ORACLE_HOST: ${{ secrets.ORACLE_HOST }}
|
||||
CYPRESS_ORACLE_SERVICE: ${{ secrets.ORACLE_SERVICE }}
|
||||
CYPRESS_ORACLE_USERNAME: ${{ secrets.ORACLE_USERNAME }}
|
||||
CYPRESS_ORACLE_PASSWORD: ${{ secrets.ORACLE_PASSWORD }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_OKTA_PASSWORD }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_DIRECT_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_ENV: "NODE_ENV=development"
|
||||
CYPRESS_CONFIG_FILE: cypress_ci.config.ts
|
||||
CYPRESS_HEADLESS: "true"
|
||||
CYPRESS_BROWSER: ${{ env.BROWSER_PATH }}
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
install: false
|
||||
working-directory: app/client
|
||||
command: yarn cypress run --browser ${{ env.BROWSER_PATH }} --config-file cypress_ci_custom.config.ts --spec ${{ env.failed_spec_env }}
|
||||
|
||||
- name: Collect CI container logs
|
||||
if: failure()
|
||||
working-directory: "."
|
||||
run: |
|
||||
mkdir -p ~/dockerlogs
|
||||
docker logs appsmith 2>&1 > ~/dockerlogs/dockerlogs-${{ matrix.job }}.txt
|
||||
|
||||
# Upload docker logs
|
||||
- name: Upload failed test list artifact
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dockerlogs
|
||||
path: ~/dockerlogs
|
||||
|
||||
- name: Rename reports
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p ~/results
|
||||
mv ${{ github.workspace }}/app/client/results ~/results/${{ matrix.job }}
|
||||
|
||||
- name: Upload cypress report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: results-${{github.run_attempt}}
|
||||
path: ~/results
|
||||
|
||||
# Set status = failedtest
|
||||
- name: Set fail if there are test failures
|
||||
if: failure()
|
||||
run: |
|
||||
echo "run_result=failedtest" >> $GITHUB_OUTPUT
|
||||
echo "failedtest" > ~/run_result
|
||||
|
||||
# Create a directory ~/failed_spec_ci and add a dummy file
|
||||
# This will ensure upload and download steps are successful
|
||||
- name: Create directory for failed tests
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p ~/failed_spec_ci-${{github.run_attempt}}
|
||||
|
||||
# add list failed tests to a file
|
||||
- name: In case of test failures copy them to a file
|
||||
if: failure()
|
||||
run: |
|
||||
cd ${{ github.workspace }}/app/client/cypress/
|
||||
find screenshots -type f \( -iname "*\(attempt 2\).png" -o -iname "*before all hook*" -o -iname "*after all hook*" \) | sed 's/screenshots/cypress\/e2e/g'| sed 's:/[^/]*$::' | sort -u > ~/failed_spec_ci-${{github.run_attempt}}/failed_spec_ci-${{ matrix.job }}
|
||||
|
||||
# Upload failed test list using common path for all matrix job
|
||||
- name: Upload failed test list artifact
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci-${{github.run_attempt}}
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: failure()
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: |
|
||||
~/run_result
|
||||
key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }}
|
||||
|
||||
# - name: get cypress url dashboard url
|
||||
# id: dashboard_url
|
||||
# if: always()
|
||||
# run: |
|
||||
# if [[ "${{steps.run_result.outputs.run_result }}" != "success" && "${{steps.run_result.outputs.run_result }}" != "failedtest" ]]; then
|
||||
# echo "" >> ~/cypress_url
|
||||
# elif [[ "${{steps.run_result.outputs.run_result }}" == "failedtest" ]]; then
|
||||
# echo "" >> ~/cypress_url
|
||||
# fi
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
if: success()
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: |
|
||||
~/cypress_url
|
||||
key: ${{ github.run_id }}-dashboard-url-${{ github.run_number }}
|
||||
|
||||
# Upload the log artifact so that it can be used by the test & deploy job in the workflow
|
||||
- name: Upload server logs bundle on failure
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: server-logs-${{ matrix.job }}
|
||||
path: app/server/server-logs.log
|
||||
|
||||
# Set status = success
|
||||
- name: Save the status of the run
|
||||
run: |
|
||||
echo "run_result=success" >> $GITHUB_OUTPUT
|
||||
echo "success" > ~/run_result
|
||||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
|
||||
job: [0]
|
||||
|
||||
# Service containers to run with this job. Required for running tests
|
||||
services:
|
||||
|
|
@ -178,6 +178,9 @@ jobs:
|
|||
-e ENTERPRISE_USER_PASSWORD=ent_user_password \
|
||||
-e ENTERPRISE_ADMIN_NAME=ent-admin@appsmith.com \
|
||||
-e ENTERPRISE_ADMIN_PASSWORD=ent_admin_password \
|
||||
-e FLAGSMITH_URL=http://host.docker.internal:5001/flagsmith \
|
||||
-e FLAGSMITH_SERVER_KEY=dummykey \
|
||||
-e FLAGSMITH_SERVER_KEY_BUSINESS_FEATURES=dummykeybusinessfeatures \
|
||||
appsmith/cloud-services:release
|
||||
cd cicontainerlocal
|
||||
docker run -d --name appsmith -p 80:80 -p 9001:9001 \
|
||||
|
|
@ -217,50 +220,6 @@ jobs:
|
|||
- name: Setting up the cypress tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_URL: ${{ secrets.CYPRESS_URL }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
CYPRESS_AIRTABLE_BEARER: ${{ secrets.AIRTABLE_BEARER }}
|
||||
CYPRESS_FIRESTORE_PRIVATE_KEY: ${{ secrets.FIRESTORE_PRIVATE_KEY }}
|
||||
CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.CYPRESS_GITHUB_PERSONAL_ACCESS_TOKEN }}
|
||||
CYPRESS_TEST_GITHUB_USER_NAME: ${{ secrets.CYPRESS_TEST_GITHUB_USER_NAME }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
CYPRESS_OAUTH_SAML_EMAIL: ${{ secrets.CYPRESS_OAUTH_SAML_EMAIL }}
|
||||
CYPRESS_OAUTH_SAML_ENTITY_ID: ${{ secrets.CYPRESS_OAUTH_SAML_ENTITY_ID }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_URL: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_URL }}
|
||||
CYPRESS_OAUTH_SAML_METADATA_XML: ${{ secrets.CYPRESS_OAUTH_SAML_METADATA_XML }}
|
||||
CYPRESS_OAUTH_SAML_PUB_CERT: ${{ secrets.CYPRESS_OAUTH_SAML_PUB_CERT }}
|
||||
CYPRESS_OAUTH_SAML_SSO_URL: ${{ secrets.CYPRESS_OAUTH_SAML_SSO_URL }}
|
||||
CYPRESS_OAUTH_SAML_REDIRECT_URL: ${{ secrets.CYPRESS_OAUTH_SAML_REDIRECT_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_AUTH_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_TOKEN_URL }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_USER_INFO }}
|
||||
CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_OIDC_JWKS_URL }}
|
||||
CYPRESS_EXCLUDE_TAGS: "airgap"
|
||||
CYPRESS_AIRGAPPED: false
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
run: |
|
||||
cd app/client
|
||||
chmod a+x ./cypress/setup-test-ci.sh
|
||||
|
|
@ -311,7 +270,11 @@ jobs:
|
|||
if [[ ${{ inputs.pr }} -ne 0 ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=${{ env.COMMIT_INFO_MESSAGE }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo \"${{ env.EVENT_COMMITS }}\" | awk -F '\\\\n' '{print $1}' | sed 's/^\"//')" >> $GITHUB_ENV
|
||||
if [[ '${{env.EVENT_COMMITS}}' == 'null' ]]; then
|
||||
echo "COMMIT_INFO_MESSAGE=${{ github.event_name }} by ${{ env.COMMIT_INFO_AUTHOR }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "COMMIT_INFO_MESSAGE=$(echo \"${{ env.EVENT_COMMITS }}\" | awk -F '\\\\n' '{print $1}' | sed 's/^\"//')" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Run the cypress test
|
||||
|
|
@ -362,6 +325,19 @@ jobs:
|
|||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
CYPRESS_VERIFY_TIMEOUT: 100000
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
record: true
|
||||
|
|
@ -441,6 +417,19 @@ jobs:
|
|||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
COMMIT_INFO_MESSAGE: ${{ env.COMMIT_INFO_MESSAGE }}
|
||||
RUNID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
COMMITTER: ${{ env.COMMIT_INFO_AUTHOR }}
|
||||
TAG: ${{ github.event_name }}
|
||||
BRANCH: ${{ env.COMMIT_INFO_BRANCH }}
|
||||
THIS_RUNNER: ${{ strategy.job-index }}
|
||||
CYPRESS_DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
CYPRESS_DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
CYPRESS_DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
CYPRESS_DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
CYPRESS_S3_ACCESS: ${{ secrets.CYPRESS_S3_ACCESS }}
|
||||
CYPRESS_S3_SECRET: ${{ secrets.CYPRESS_S3_SECRET }}
|
||||
with:
|
||||
browser: ${{ env.BROWSER_PATH }}
|
||||
record: true
|
||||
|
|
@ -507,15 +496,15 @@ jobs:
|
|||
~/run_result
|
||||
key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }}
|
||||
|
||||
- name: get cypress url dashboard url
|
||||
id: dashboard_url
|
||||
if: always()
|
||||
run: |
|
||||
if [[ "${{steps.run_result.outputs.run_result }}" != "success" && "${{steps.run_result.outputs.run_result }}" != "failedtest" ]]; then
|
||||
echo ${{ steps.cypress_test.outputs.resultsUrl }} >> ~/cypress_url
|
||||
elif [[ "${{steps.run_result.outputs.run_result }}" == "failedtest" ]]; then
|
||||
echo ${{ steps.cypress_test_failedtest.outputs.resultsUrl }} >> ~/cypress_url
|
||||
fi
|
||||
# - name: get cypress url dashboard url
|
||||
# id: dashboard_url
|
||||
# if: always()
|
||||
# run: |
|
||||
# if [[ "${{steps.run_result.outputs.run_result }}" != "success" && "${{steps.run_result.outputs.run_result }}" != "failedtest" ]]; then
|
||||
# echo ${{ steps.cypress_test.outputs.resultsUrl }} >> ~/cypress_url
|
||||
# elif [[ "${{steps.run_result.outputs.run_result }}" == "failedtest" ]]; then
|
||||
# echo ${{ steps.cypress_test_failedtest.outputs.resultsUrl }} >> ~/cypress_url
|
||||
# fi
|
||||
|
||||
# Force store previous run result to cache
|
||||
- name: Store the previous run result
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
name: Cleanup Deploy Previews
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: 0 0 * * *
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,11 @@ on:
|
|||
description: "This is the branch to be used for the build."
|
||||
required: false
|
||||
type: string
|
||||
|
||||
ads-compliant-check:
|
||||
description: "This is a boolean value in case the workflow is being called in build deploy-preview"
|
||||
required: false
|
||||
type: string
|
||||
default: "true"
|
||||
|
||||
# Change the working directory for all the jobs in this workflow
|
||||
defaults:
|
||||
|
|
@ -76,7 +80,7 @@ jobs:
|
|||
uses: umani/changed-files@v4.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.APPSMITH_CI_TEST_PAT }}
|
||||
pattern: 'app/client/cypress/e2e/.*'
|
||||
pattern: "app/client/cypress/e2e/.*"
|
||||
pr-number: ${{ inputs.pr }}
|
||||
|
||||
# Check all the newly added files are in ts
|
||||
|
|
@ -107,6 +111,46 @@ jobs:
|
|||
- if: steps.check_files.outputs.non_ts_files_count != 0 && inputs.check-test-files == 'true' && inputs.pr != 0
|
||||
run: exit 1
|
||||
|
||||
- name: Get all the added or changed files in client/src folder
|
||||
if: inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release'
|
||||
id: client_files
|
||||
uses: umani/changed-files@v4.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.APPSMITH_CI_TEST_PAT }}
|
||||
pattern: "app/client/src/.*"
|
||||
pr-number: ${{ inputs.pr }}
|
||||
|
||||
# Check all the newly added files are in ts
|
||||
- name: ADS compliant check
|
||||
if: inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release'
|
||||
id: ads_check
|
||||
run: |
|
||||
comment_files=""
|
||||
files=(${{steps.client_files.outputs.files_created}}${{steps.client_files.outputs.files_updated}})
|
||||
for file in "${files[@]}"; do
|
||||
while IFS= read -r line; do
|
||||
if echo "$line" | grep -q -E '(color|Color).*#|border.*#|(color|Color).*"'; then
|
||||
comment_files+=("$file")
|
||||
break
|
||||
fi
|
||||
done < ${file#app/client/}
|
||||
done
|
||||
unique_files=$(echo "${comment_files[@]}" | sort -u | sed '/^[[:space:]]*$/d' | sed 's/ / <li>/g')
|
||||
echo "ads_non_compliant_files=$unique_files" >> $GITHUB_OUTPUT
|
||||
echo "ads_non_compliant_count=${#unique_files[@]}" >> $GITHUB_OUTPUT
|
||||
|
||||
# Comment in PR if test files are not written in ts and fail the workflow
|
||||
- name: Comment in PR if test files are not written in ts
|
||||
if: steps.ads_check.outputs.ads_non_compliant_count != 0 && inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release'
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ inputs.pr }}
|
||||
body: |
|
||||
<b> 🔴 Below files are not compliant with ADS. Please fix and re-trigger ok-to-test </b>
|
||||
<ol>${{steps.ads_check.outputs.ads_non_compliant_files}}</ol>
|
||||
- if: steps.ads_check.outputs.ads_non_compliant_count != 0 && inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release'
|
||||
run: exit 1
|
||||
|
||||
# Create a run record exactly at the time of merge to release to
|
||||
# ensure we compare run details with code at this point
|
||||
- name: Create Perf Meta
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
name: Docker Base Image
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 5 * * MON"
|
||||
push:
|
||||
branches:
|
||||
- release
|
||||
- master
|
||||
paths:
|
||||
- "deploy/docker/base.dockerfile"
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- name: Checkout the head commit of the branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Get tag
|
||||
id: tag
|
||||
run: |
|
||||
tag="${GITHUB_REF_NAME//\//-}"
|
||||
if [[ "$tag" == master ]]; then
|
||||
tag=nightly
|
||||
fi
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build and push base image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: deploy/docker/base.dockerfile
|
||||
push: true
|
||||
platforms: linux/arm64,linux/amd64
|
||||
tags: |
|
||||
${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:${{ steps.tag.outputs.tag }}
|
||||
|
|
@ -269,6 +269,12 @@ jobs:
|
|||
echo "Cleaning up the tar files"
|
||||
rm app/client/packages/rts/dist/rts-dist.tar
|
||||
|
||||
- name: Generate info.json
|
||||
run: |
|
||||
if [[ -f scripts/generate_info_json.sh ]]; then
|
||||
scripts/generate_info_json.sh
|
||||
fi
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
|
|
@ -283,6 +289,7 @@ jobs:
|
|||
platforms: linux/arm64,linux/amd64
|
||||
build-args: |
|
||||
APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY }}
|
||||
BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:nightly
|
||||
tags: |
|
||||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-${{ vars.EDITION }}:${{needs.prelude.outputs.tag}}
|
||||
|
||||
|
|
@ -296,5 +303,6 @@ jobs:
|
|||
platforms: linux/arm64,linux/amd64
|
||||
build-args: |
|
||||
APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY }}
|
||||
BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:nightly
|
||||
tags: |
|
||||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-${{ vars.EDITION }}:latest
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ name: Appsmith External Integration Test Workflow
|
|||
on:
|
||||
# This workflow is only triggered by the ok to test command dispatch
|
||||
repository_dispatch:
|
||||
types: [ ok-to-test-command ]
|
||||
types: [ok-to-test-command]
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
|
|
@ -19,8 +19,7 @@ jobs:
|
|||
Workflow: `${{ github.workflow }}`.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
PR: ${{ github.event.client_payload.pull_request.number }}.
|
||||
Perf tests will be available at <https://app.appsmith.com/app/performance-infra-dashboard/pr-details-638dd7cd2913ba43778b915e?pr=${{ github.event.client_payload.pull_request.number }}&runId=${{ github.run_id }}_${{github.run_attempt}}>
|
||||
|
||||
|
||||
server-build:
|
||||
name: server-build
|
||||
uses: ./.github/workflows/server-build.yml
|
||||
|
|
@ -52,7 +51,7 @@ jobs:
|
|||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
build-docker-image:
|
||||
needs: [ client-build, server-build, rts-build ]
|
||||
needs: [client-build, server-build, rts-build]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: build-docker-image
|
||||
|
|
@ -62,27 +61,17 @@ jobs:
|
|||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
ci-test:
|
||||
needs: [ build-docker-image ]
|
||||
needs: [build-docker-image]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: ci-test
|
||||
uses: ./.github/workflows/ci-test.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
perf-test:
|
||||
needs: [ build-docker-image ]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: perf-test
|
||||
uses: ./.github/workflows/perf-test.yml
|
||||
uses: ./.github/workflows/ci-test-custom-script.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
ci-test-result:
|
||||
needs: [ci-test, perf-test ]
|
||||
needs: [ci-test]
|
||||
# Only run if the ci-test with matrices step is successful
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -95,54 +84,69 @@ jobs:
|
|||
PAYLOAD_CONTEXT: ${{ toJson(github.event.client_payload) }}
|
||||
run: echo "$PAYLOAD_CONTEXT"
|
||||
|
||||
# Deleting the existing dir's if any
|
||||
- name: Delete existing directories
|
||||
- name: Setup node
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: |
|
||||
rm -f ~/failed_spec_ci
|
||||
rm -f ~/combined_failed_spec_ci
|
||||
|
||||
# Force store previous cypress dashboard url from cache
|
||||
- name: Store the previous cypress dashboard url
|
||||
continue-on-error: true
|
||||
if: success()
|
||||
uses: actions/cache@v3
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
path: |
|
||||
~/cypress_url
|
||||
key: ${{ github.run_id }}-dashboard-url-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-dashboard-url
|
||||
node-version: 18
|
||||
|
||||
- name: Print cypress dashboard url
|
||||
continue-on-error: true
|
||||
id: dashboard_url
|
||||
run: |
|
||||
cypress_url=$(cat ~/cypress_url)
|
||||
echo "dashboard_url=$cypress_url" >> $GITHUB_OUTPUT
|
||||
|
||||
# Download failed_spec list for all jobs
|
||||
- uses: actions/download-artifact@v3
|
||||
- name: install pg
|
||||
if: needs.ci-test.result != 'success'
|
||||
id: download_ci
|
||||
run: npm install pg
|
||||
|
||||
- name: Fetch the failed specs
|
||||
if: needs.ci-test.result != 'success'
|
||||
id: failed_specs
|
||||
env:
|
||||
DB_HOST: ${{ secrets.CYPRESS_DB_HOST }}
|
||||
DB_NAME: ${{ secrets.CYPRESS_DB_NAME }}
|
||||
DB_USER: ${{ secrets.CYPRESS_DB_USER }}
|
||||
DB_PWD: ${{ secrets.CYPRESS_DB_PWD }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
ATTEMPT_NUMBER: ${{ github.run_attempt }}
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci
|
||||
|
||||
script: |
|
||||
const { Pool } = require("pg");
|
||||
const { DB_HOST, DB_NAME, DB_USER, DB_PWD, RUN_ID, ATTEMPT_NUMBER } = process.env
|
||||
|
||||
const client = await new Pool({
|
||||
user: DB_USER,
|
||||
host: DB_HOST,
|
||||
database: DB_NAME,
|
||||
password: DB_PWD,
|
||||
port: 5432,
|
||||
connectionTimeoutMillis: 60000,
|
||||
}).connect();
|
||||
|
||||
const result = await client.query(
|
||||
`SELECT DISTINCT name FROM public."specs"
|
||||
WHERE "matrixId" IN
|
||||
(SELECT id FROM public."matrix"
|
||||
WHERE "attemptId" = (
|
||||
SELECT id FROM public."attempt" WHERE "workflowId" = $1 and "attempt" = $2
|
||||
)
|
||||
) AND status = 'fail'`,
|
||||
[RUN_ID, ATTEMPT_NUMBER],
|
||||
);
|
||||
client.release();
|
||||
return result.rows.map((spec) => spec.name);
|
||||
|
||||
# In case for any ci job failure, create combined failed spec
|
||||
- name: combine all specs for CI
|
||||
id: combine_ci
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: |
|
||||
echo "Debugging: failed specs in ~/failed_spec_ci/failed_spec_ci*"
|
||||
cat ~/failed_spec_ci/failed_spec_ci*
|
||||
cat ~/failed_spec_ci/failed_spec_ci* | sort -u >> ~/combined_failed_spec_ci
|
||||
failed_specs=$(echo ${{steps.failed_specs.outputs.result}} | sed 's/\[\|\]//g' | tr -d ' ' | tr ',' '\n')
|
||||
while read -r line; do
|
||||
echo "$line" >> ~/combined_failed_spec_ci
|
||||
done <<< "$failed_specs"
|
||||
if [[ -z $(grep '[^[:space:]]' ~/combined_failed_spec_ci) ]] ; then
|
||||
echo "specs_failed=0" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "specs_failed=1" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
|
||||
# Upload combined failed CI spec list to a file
|
||||
# This is done for debugging.
|
||||
- name: upload combined failed spec
|
||||
|
|
@ -157,7 +161,7 @@ jobs:
|
|||
run: |
|
||||
curl --request POST --url https://yatin-s-workspace-jk8ru5.us-east-1.xata.sh/db/CypressKnownFailures:main/tables/CypressKnownFailuires/query --header 'Authorization: Bearer ${{ secrets.XATA_TOKEN }}' --header 'Content-Type: application/json'|jq -r |grep Spec|cut -d ':' -f 2 2> /dev/null|sed 's/"//g'|sed 's/,//g' > ~/knownfailures
|
||||
|
||||
# Verify CI test failures against known failures
|
||||
# Verify CI test failures against known failures
|
||||
- name: Verify CI test failures against known failures
|
||||
if: needs.ci-test.result != 'success'
|
||||
shell: bash
|
||||
|
|
@ -176,19 +180,30 @@ jobs:
|
|||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
Cypress dashboard: <a href="${{ steps.dashboard_url.outputs.dashboard_url }}" target="_blank"> Click here!</a>
|
||||
Cypress dashboard: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank"> Click here!</a>
|
||||
The following are new failures, please fix them before merging the PR: ${{env.new_failed_spec_env}}
|
||||
To know the list of identified flaky tests - <a href="https://app.appsmith.com/applications/613868bedd7786286ddd4a6a/pages/63ec710e8e503f763651791a" target="_blank">Refer here</a>
|
||||
To know the list of identified flaky tests - <a href="https://internal.appsmith.com/app/cypressdashboard/identified-flaky-tests-6541e22b0c243558fe2288ca?branch=master" target="_blank">Refer here</a>
|
||||
|
||||
- name: Add a comment on the PR when ci-test is success
|
||||
if: needs.ci-test.result == 'success' || steps.combine_ci.outputs.specs_failed == '0'
|
||||
- name: Add a comment on the PR when ci-test is failed but no specs found
|
||||
if: needs.ci-test.result != 'success' && steps.combine_ci.outputs.specs_failed == '0'
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.client_payload.pull_request.number }}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
Cypress dashboard url: <a href="${{ steps.dashboard_url.outputs.dashboard_url }}" target="_blank">Click here!</a>
|
||||
Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}" target="_blank">Click here!</a>
|
||||
It seems like there are some failures 😔. We are not able to recognize it, please check this manually <a href="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" target="_blank">here.</a>
|
||||
|
||||
- name: Add a comment on the PR when ci-test is success
|
||||
if: needs.ci-test.result == 'success' && steps.combine_ci.outputs.specs_failed == '0'
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.client_payload.pull_request.number }}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}" target="_blank">Click here!</a>
|
||||
All cypress tests have passed 🎉🎉🎉
|
||||
|
||||
# Update check run called "ci-test-result"
|
||||
|
|
@ -261,11 +276,11 @@ jobs:
|
|||
run: echo "$PAYLOAD_CONTEXT"
|
||||
|
||||
- name: Check ci-test set status
|
||||
if: needs.ci-test.result != 'success' || needs.perf-test.result != 'success'
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: exit 1
|
||||
|
||||
package:
|
||||
needs: [ ci-test ]
|
||||
needs: [ci-test]
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,323 @@
|
|||
name: Appsmith External Integration Test (with DocumentDB ) Workflow
|
||||
|
||||
on:
|
||||
# This workflow is only triggered by the ok to test command dispatch
|
||||
repository_dispatch:
|
||||
types: [ok-to-test-with-documentdb-command]
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# This step creates a comment on the PR with a link to this workflow run.
|
||||
- name: Add a comment on the PR with link to workflow run
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
with:
|
||||
issue-number: ${{ github.event.client_payload.pull_request.number }}
|
||||
body: |
|
||||
Tests running at: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Workflow: `${{ github.workflow }}`.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
PR: ${{ github.event.client_payload.pull_request.number }}.
|
||||
|
||||
server-build:
|
||||
name: server-build
|
||||
uses: ./.github/workflows/server-build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
skip-tests: true
|
||||
|
||||
client-build:
|
||||
name: client-build
|
||||
uses: ./.github/workflows/client-build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
check-test-files: "true"
|
||||
|
||||
rts-build:
|
||||
name: rts-build
|
||||
uses: ./.github/workflows/rts-build.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
test-appsmithctl:
|
||||
name: appsmithctl
|
||||
uses: ./.github/workflows/appsmithctl.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
build-docker-image:
|
||||
needs: [client-build, server-build, rts-build]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: build-docker-image
|
||||
uses: ./.github/workflows/build-docker-image.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
ci-test:
|
||||
needs: [build-docker-image]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: ci-test-with-documentDB
|
||||
uses: ./.github/workflows/ci-test-with-documentdb.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
ci-test-result:
|
||||
needs: [ci-test]
|
||||
# Only run if the ci-test with matrices step is successful
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- name: Dump the client payload context
|
||||
env:
|
||||
PAYLOAD_CONTEXT: ${{ toJson(github.event.client_payload) }}
|
||||
run: echo "$PAYLOAD_CONTEXT"
|
||||
|
||||
# Deleting the existing dir's if any
|
||||
- name: Delete existing directories
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: |
|
||||
rm -f ~/failed_spec_ci
|
||||
rm -f ~/combined_failed_spec_ci
|
||||
|
||||
# Force store previous cypress dashboard url from cache
|
||||
- name: Store the previous cypress dashboard url
|
||||
continue-on-error: true
|
||||
if: success()
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/cypress_url
|
||||
key: ${{ github.run_id }}-dashboard-url-${{ github.run_attempt }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-dashboard-url
|
||||
|
||||
- name: Print cypress dashboard url
|
||||
continue-on-error: true
|
||||
id: dashboard_url
|
||||
run: |
|
||||
cypress_url="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}"
|
||||
echo "dashboard_url=$cypress_url" >> $GITHUB_OUTPUT
|
||||
|
||||
# Download failed_spec list for all jobs
|
||||
- uses: actions/download-artifact@v3
|
||||
if: needs.ci-test.result != 'success'
|
||||
id: download_ci
|
||||
with:
|
||||
name: failed-spec-ci-${{github.run_attempt}}
|
||||
path: ~/failed_spec_ci
|
||||
|
||||
# In case for any ci job failure, create combined failed spec
|
||||
- name: combine all specs for CI
|
||||
id: combine_ci
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: |
|
||||
echo "Debugging: failed specs in ~/failed_spec_ci/failed_spec_ci*"
|
||||
cat ~/failed_spec_ci/failed_spec_ci*
|
||||
cat ~/failed_spec_ci/failed_spec_ci* | sort -u >> ~/combined_failed_spec_ci
|
||||
if [[ -z $(grep '[^[:space:]]' ~/combined_failed_spec_ci) ]] ; then
|
||||
echo "specs_failed=0" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "specs_failed=1" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
# Upload combined failed CI spec list to a file
|
||||
# This is done for debugging.
|
||||
- name: upload combined failed spec
|
||||
if: needs.ci-test.result != 'success'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: combined_failed_spec_ci
|
||||
path: ~/combined_failed_spec_ci
|
||||
|
||||
- name: Get Latest flaky Tests
|
||||
shell: bash
|
||||
run: |
|
||||
curl --request POST --url https://yatin-s-workspace-jk8ru5.us-east-1.xata.sh/db/CypressKnownFailures:main/tables/CypressKnownFailuires/query --header 'Authorization: Bearer ${{ secrets.XATA_TOKEN }}' --header 'Content-Type: application/json'|jq -r |grep Spec|cut -d ':' -f 2 2> /dev/null|sed 's/"//g'|sed 's/,//g' > ~/knownfailures
|
||||
|
||||
# Verify CI test failures against known failures
|
||||
- name: Verify CI test failures against known failures
|
||||
if: needs.ci-test.result != 'success'
|
||||
shell: bash
|
||||
run: |
|
||||
new_failed_spec_env="<ol>$(comm -1 -3 <(sort ~/knownfailures) <(sort -u ~/combined_failed_spec_ci) | sed 's/|cypress|cypress/\n/g' | sed 's/^/<li>/')</ol>"
|
||||
echo "$new_failed_spec_env"
|
||||
echo "new_failed_spec_env<<EOF" >> $GITHUB_ENV
|
||||
echo "$new_failed_spec_env" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
- name: Add a comment on the PR with new CI failures
|
||||
if: needs.ci-test.result != 'success' && steps.combine_ci.outputs.specs_failed == '1'
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.client_payload.pull_request.number }}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
Cypress dashboard: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}&selectiontype=test&testsstatus=failed&specsstatus=fail" target="_blank"> Click here!</a>
|
||||
The following are new failures, please fix them before merging the PR: ${{env.new_failed_spec_env}}
|
||||
To know the list of identified flaky tests - <a href="https://internal.appsmith.com/app/cypressdashboard/identified-flaky-tests-6541e22b0c243558fe2288ca?branch=master" target="_blank">Refer here</a>
|
||||
|
||||
- name: Add a comment on the PR when ci-test is success
|
||||
if: needs.ci-test.result == 'success' || steps.combine_ci.outputs.specs_failed == '0'
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
issue-number: ${{ github.event.client_payload.pull_request.number }}
|
||||
body: |
|
||||
Workflow run: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}>.
|
||||
Commit: `${{ github.event.client_payload.slash_command.args.named.sha }}`.
|
||||
Cypress dashboard: <a href="https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}" target="_blank">Click here!</a>
|
||||
All cypress tests have passed 🎉🎉🎉
|
||||
|
||||
# Update check run called "ci-test-result"
|
||||
- name: Mark ci-test-result job as complete
|
||||
uses: actions/github-script@v6
|
||||
id: update-check-run
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
run_id: ${{ github.run_id }}
|
||||
repository: ${{ github.repository }}
|
||||
number: ${{ github.event.client_payload.pull_request.number }}
|
||||
job: ${{ github.job }}
|
||||
# Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run
|
||||
conclusion: ${{ job.status }}
|
||||
matrix_result: ${{ toJson(needs.ci-test) }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { data: pull } = await github.rest.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: process.env.number
|
||||
});
|
||||
const ref = pull.head.sha;
|
||||
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
...context.repo,
|
||||
ref
|
||||
});
|
||||
|
||||
const check = checks.check_runs.filter(c => c.name === process.env.job);
|
||||
|
||||
if(check.length == 0) {
|
||||
const head_sha = pull.head.sha;
|
||||
const { data: completed_at } = await github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
head_sha: head_sha,
|
||||
name: process.env.job,
|
||||
status: 'completed',
|
||||
conclusion: JSON.parse(process.env.matrix_result).result,
|
||||
output: {
|
||||
title: "Integration tests result for ok to test",
|
||||
summary: "https://github.com/" + process.env.repository + "/actions/runs/" + process.env.run_id
|
||||
}
|
||||
});
|
||||
|
||||
return completed_at;
|
||||
} else {
|
||||
try {
|
||||
const { data: result } = await github.rest.checks.update({
|
||||
...context.repo,
|
||||
check_run_id: check[0].id,
|
||||
status: 'completed',
|
||||
conclusion: JSON.parse(process.env.matrix_result).result,
|
||||
output: {
|
||||
title: "Integration tests result for ok to test",
|
||||
summary: "https://github.com/" + process.env.repository + "/actions/runs/" + process.env.run_id
|
||||
}
|
||||
});
|
||||
console.log({ result });
|
||||
return result;
|
||||
} catch(e) {
|
||||
console.error({ error: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
- name: Dump the client payload context
|
||||
env:
|
||||
PAYLOAD_CONTEXT: ${{ toJson(github.event.client_payload) }}
|
||||
run: echo "$PAYLOAD_CONTEXT"
|
||||
|
||||
- name: Check ci-test set status
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: exit 1
|
||||
|
||||
package:
|
||||
needs: [ci-test]
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: app/client
|
||||
# Run this job only if all the previous steps are a success and the reference if the release or master branch
|
||||
if: success() && (github.ref == 'refs/heads/release' || github.ref == 'refs/heads/master')
|
||||
|
||||
steps:
|
||||
# Update check run called "package"
|
||||
- name: Mark package job as complete
|
||||
uses: actions/github-script@v6
|
||||
id: update-check-run
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
run_id: ${{ github.run_id }}
|
||||
repository: ${{ github.repository }}
|
||||
number: ${{ github.event.client_payload.pull_request.number }}
|
||||
job: ${{ github.job }}
|
||||
# Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run
|
||||
conclusion: ${{ job.status }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { data: pull } = await github.rest.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: process.env.number
|
||||
});
|
||||
const ref = pull.head.sha;
|
||||
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
...context.repo,
|
||||
ref
|
||||
});
|
||||
|
||||
const check = checks.check_runs.filter(c => c.name === process.env.job);
|
||||
|
||||
if(check.length == 0) {
|
||||
const head_sha = pull.head.sha;
|
||||
const { data: completed_at } = await github.rest.checks.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
head_sha: head_sha,
|
||||
name: process.env.job,
|
||||
status: 'completed',
|
||||
conclusion: process.env.conclusion,
|
||||
output: {
|
||||
title: "Package result for ok to test",
|
||||
summary: "https://github.com/" + process.env.repository + "/actions/runs/" + process.env.run_id
|
||||
}
|
||||
});
|
||||
|
||||
return completed_at;
|
||||
} else {
|
||||
const { data: result } = await github.rest.checks.update({
|
||||
...context.repo,
|
||||
check_run_id: check[0].id,
|
||||
status: 'completed',
|
||||
conclusion: process.env.conclusion,
|
||||
output: {
|
||||
title: "Package result for ok to test",
|
||||
summary: "https://github.com/" + process.env.repository + "/actions/runs/" + process.env.run_id
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
# If someone with write access comments "/ok-to-test" on a pull request, emit a repository_dispatch event
|
||||
name: Ok To Test with DocumentDB
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
ok-to-test:
|
||||
runs-on: ubuntu-latest
|
||||
# Only run for PRs, not issue comments
|
||||
if: |
|
||||
github.event.issue.pull_request
|
||||
steps:
|
||||
- name: Generate token
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@v1
|
||||
with:
|
||||
app_id: ${{ secrets.APPSMITH_INTEGRATION_TESTING_ID }}
|
||||
private_key: ${{ secrets.APPSMITH_INTEGRATION_TESTING_KEY }}
|
||||
|
||||
- if: contains(github.event.comment.body, '/ok-to-test-with-documentdb')
|
||||
name: Slash Command Dispatch
|
||||
uses: peter-evans/slash-command-dispatch@v3
|
||||
env:
|
||||
TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||
with:
|
||||
token: ${{ env.TOKEN }} # GitHub App installation access token
|
||||
reaction-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-type: pull-request
|
||||
commands: |
|
||||
ok-to-test-with-documentdb
|
||||
permission: write
|
||||
|
|
@ -187,6 +187,7 @@ jobs:
|
|||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-dp:${{ vars.EDITION }}-${{ github.event.client_payload.pull_request.number }}
|
||||
build-args: |
|
||||
APPSMITH_CLOUD_SERVICES_BASE_URL=https://release-cs.appsmith.com
|
||||
BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:release
|
||||
|
||||
outputs:
|
||||
imageHash: ${{ vars.EDITION }}-${{ github.event.client_payload.pull_request.number }}
|
||||
|
|
@ -207,23 +208,31 @@ jobs:
|
|||
ref: "refs/pull/${{ github.event.client_payload.pull_request.number }}/merge"
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Print versions of tools
|
||||
run: |
|
||||
set -o errexit
|
||||
set -o xtrace
|
||||
aws --version || true
|
||||
kubectl version || true
|
||||
helm version || true
|
||||
|
||||
- name: Install mongosh
|
||||
run: |
|
||||
curl -fsSL https://pgp.mongodb.com/server-6.0.asc \
|
||||
| sudo gpg -o /usr/share/keyrings/mongodb-server-6.0.gpg --dearmor
|
||||
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" \
|
||||
| sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y wget gnupg
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add -
|
||||
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y mongodb-mongosh
|
||||
sudo apt-get install --yes mongodb-mongosh
|
||||
echo "MongoSH version: $(mongosh --version)"
|
||||
|
||||
- name: Install relevant packages
|
||||
run: |
|
||||
which aws
|
||||
sudo apt update -q && sudo apt install -y curl unzip less jq
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.6/bin/linux/amd64/kubectl && \
|
||||
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \
|
||||
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 && \
|
||||
chmod 700 get_helm.sh; ./get_helm.sh
|
||||
set -o errexit
|
||||
# We still need Kubectl v1.23. Once we up the cluster version, we can get rid of this step.
|
||||
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.23.6/bin/linux/amd64/kubectl
|
||||
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
|
||||
kubectl version || true
|
||||
|
||||
- name: Deploy Helm chart
|
||||
env:
|
||||
|
|
@ -241,7 +250,7 @@ jobs:
|
|||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||
DB_URL: ${{ secrets.DB_URL }}
|
||||
DP_EFS_ID: ${{ secrets.APPSMITH_DP_EFS_ID }}
|
||||
REDIS_URL: ${{ secrets.APPSMITH_DP_REDIS_URL }}
|
||||
REDIS_URL: ${{ secrets.APPSMITH_DP_REDIS_URL }}
|
||||
run: |
|
||||
echo "environment variables set to deploy the image" $IMAGE_HASH
|
||||
/bin/bash ./scripts/deploy_preview.sh
|
||||
|
|
|
|||
|
|
@ -0,0 +1,259 @@
|
|||
name: Appsmith Performance Test (on DocumentDB) Workflow
|
||||
|
||||
on:
|
||||
# This line enables manual triggering of this workflow.
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
pr:
|
||||
description: "This is the PR number in case the workflow is being called in a pull request"
|
||||
required: false
|
||||
type: number
|
||||
|
||||
# Change the working directory for all the jobs in this workflow
|
||||
defaults:
|
||||
run:
|
||||
working-directory: app/client
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
perf-test:
|
||||
runs-on: ubuntu-latest-4-cores
|
||||
# Only run this workflow for internally triggered events
|
||||
if: |
|
||||
github.event.pull_request.head.repo.full_name == github.repository ||
|
||||
github.event_name == 'push' ||
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
github.event_name == 'repository_dispatch'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: app/client
|
||||
shell: bash
|
||||
|
||||
# Service containers to run with this job. Required for running tests
|
||||
services:
|
||||
# Label used to access the service container
|
||||
redis:
|
||||
# Docker Hub image for Redis
|
||||
image: redis
|
||||
ports:
|
||||
# Opens tcp port 6379 on the host and service container
|
||||
- 6379:6379
|
||||
|
||||
steps:
|
||||
- name: Checkout the merged commit from PR and base branch
|
||||
if: inputs.pr != 0
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: refs/pull/${{ inputs.pr }}/merge
|
||||
|
||||
# Checkout the code in the current branch in case the workflow is called because of a branch push event
|
||||
- name: Checkout the head commit of the branch
|
||||
if: inputs.pr == 0
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Figure out the PR number
|
||||
run: echo ${{ inputs.pr }}
|
||||
|
||||
- name: Print the Github event
|
||||
run: echo ${{ github.event_name }}
|
||||
|
||||
# Timestamp will be used to create cache key
|
||||
- id: timestamp
|
||||
run: echo "timestamp=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_OUTPUT
|
||||
|
||||
# In case this is second attempt try restoring status of the prior attempt from cache
|
||||
- name: Restore the previous run result
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/run_result
|
||||
key: ${{ github.run_id }}-${{ github.job }}-${{ steps.timestamp.outputs.timestamp }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-${{ github.job }}-
|
||||
|
||||
# Fetch prior run result
|
||||
- name: Get the previous run result
|
||||
id: run_result
|
||||
run: cat ~/run_result 2>/dev/null || echo 'default'
|
||||
|
||||
# In case of prior failure run the job
|
||||
- if: steps.run_result.outputs.run_result != 'success'
|
||||
run: echo "I'm alive!" && exit 0
|
||||
|
||||
# Set status = success
|
||||
- name: Save the status of the run
|
||||
run: echo "run_result=success" >> $GITHUB_OUTPUT > ~/run_result
|
||||
|
||||
# Set up Node.js cache yarn dependencies.
|
||||
# actions/setup-node@v3 now support caching of dependencies using actions/cache under the hood
|
||||
# https://github.com/actions/setup-node#caching-global-packages-data
|
||||
- name: Set up Node.js
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: app/client/package.json
|
||||
|
||||
- name: Download Docker image artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: cicontainer
|
||||
|
||||
- name: Load Docker image from tar file
|
||||
working-directory: "."
|
||||
run: |
|
||||
gunzip cicontainer.tar.gz
|
||||
docker load -i cicontainer.tar
|
||||
|
||||
- name: Create folder
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
env:
|
||||
APPSMITH_LICENSE_KEY: ${{ secrets.APPSMITH_LICENSE_KEY }}
|
||||
working-directory: "."
|
||||
run: |
|
||||
mkdir -p cicontainerlocal/stacks/configuration/
|
||||
|
||||
- name: Set up SSH key for tunnel
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.APPSMITH_CI_TUNNEL_PRIVATE_KEY }}
|
||||
run: |
|
||||
echo "$SSH_PRIVATE_KEY" > ssh_key.pem \
|
||||
chmod 600 ssh_key.pem
|
||||
|
||||
- name: Setup SSH tunnel to AWS DocumentDB instance
|
||||
run: |
|
||||
ssh -4 -o StrictHostKeyChecking=no -o ServerAliveInterval=180 -o ServerAliveCountMax=5 -i "ssh_key.pem" -L 0.0.0.0:27010:docdb-ansible-test-cluster.cluster-cz8diybf9wdj.ap-south-1.docdb.amazonaws.com:27017 ubuntu@65.1.106.35 -N -f
|
||||
|
||||
- name: Run docker image
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
env:
|
||||
APPSMITH_LICENSE_KEY: ${{ secrets.APPSMITH_LICENSE_KEY }}
|
||||
APPSMITH_MONGODB_URI: ${{ secrets.INTERNAL_CI_DOC_DB_URI }}
|
||||
working-directory: "."
|
||||
run: |
|
||||
timestamp=$(date +%s)
|
||||
hash=$(echo -n "$timestamp" | sha1sum | awk '{print $1}')
|
||||
current_date=$(date -d "@$timestamp" +"%d-%m")
|
||||
DB_NAME="ci${hash:1:3}-${current_date}"
|
||||
mkdir -p ~/git-server/keys
|
||||
mkdir -p ~/git-server/repos
|
||||
docker run --name test-event-driver -d -p 2222:22 -p 5001:5001 -p 3306:3306 \
|
||||
-p 5432:5432 -p 28017:27017 -p 25:25 -p 5000:5000 -p 3000:3000 --privileged --pid=host --ipc=host --volume /:/host -v ~/git-server/keys:/git-server/keys \
|
||||
-v ~/git-server/repos:/git-server/repos appsmith/test-event-driver:latest
|
||||
cd cicontainerlocal
|
||||
docker run -d --name appsmith -p 80:80 -p 9001:9001 \
|
||||
-v "$PWD/stacks:/appsmith-stacks" -e APPSMITH_LICENSE_KEY=$APPSMITH_LICENSE_KEY \
|
||||
-e APPSMITH_DISABLE_TELEMETRY=true \
|
||||
-e APPSMITH_CLOUD_SERVICES_BASE_URL=http://host.docker.internal:5001 \
|
||||
-e APPSMITH_MONGODB_URI="${APPSMITH_MONGODB_URI}${DB_NAME}?retryWrites=false&replicaSet=rs0&directConnection=true" \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
cicontainer
|
||||
|
||||
# Start rts
|
||||
- name: Start RTS Server
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: ./app/client/packages/rts
|
||||
run: |
|
||||
cp .env.example .env
|
||||
./start-server.sh &
|
||||
|
||||
- name: Setting up the perf tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_URL: ${{ secrets.CYPRESS_URL }}
|
||||
CYPRESS_USERNAME: ${{ secrets.CYPRESS_USERNAME }}
|
||||
CYPRESS_PASSWORD: ${{ secrets.CYPRESS_PASSWORD }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME1 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME2: ${{ secrets.CYPRESS_TESTUSERNAME2 }}
|
||||
CYPRESS_TESTPASSWORD2: ${{ secrets.CYPRESS_TESTPASSWORD1 }}
|
||||
CYPRESS_TESTUSERNAME3: ${{ secrets.CYPRESS_TESTUSERNAME3 }}
|
||||
CYPRESS_TESTPASSWORD3: ${{ secrets.CYPRESS_TESTPASSWORD3 }}
|
||||
CYPRESS_TESTUSERNAME4: ${{ secrets.CYPRESS_TESTUSERNAME4 }}
|
||||
CYPRESS_TESTPASSWORD4: ${{ secrets.CYPRESS_TESTPASSWORD4 }}
|
||||
CYPRESS_S3_ACCESS_KEY: ${{ secrets.CYPRESS_S3_ACCESS_KEY }}
|
||||
CYPRESS_S3_SECRET_KEY: ${{ secrets.CYPRESS_S3_SECRET_KEY }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GOOGLE_CLIENT_SECRET }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_ID }}
|
||||
CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET: ${{ secrets.CYPRESS_APPSMITH_OAUTH2_GITHUB_CLIENT_SECRET }}
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
APPSMITH_GOOGLE_MAPS_API_KEY: ${{ secrets.APPSMITH_GOOGLE_MAPS_API_KEY }}
|
||||
POSTGRES_PASSWORD: postgres
|
||||
run: |
|
||||
chmod a+x ./perf/setup-perf-test.sh
|
||||
./perf/setup-perf-test.sh
|
||||
|
||||
- name: Get the performance-infra branch/ref
|
||||
id: perf_infra_ref
|
||||
run: |
|
||||
ref=${{ github.event.client_payload.slash_command.args.named.ref }}
|
||||
if [[ -z "$ref" ]]; then ref="main"; fi
|
||||
echo ref=$ref >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Checkout Performance Infra code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: appsmithorg/performance-infra
|
||||
token: ${{ secrets.APPSMITH_PERF_INFRA_REPO_PAT }}
|
||||
ref: ${{ steps.perf_infra_ref.outputs.ref }}
|
||||
path: perf
|
||||
|
||||
- name: Installing performance tests dependencies
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: perf
|
||||
shell: bash
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Change test script permissions
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: perf
|
||||
run: chmod +x ./start-test.sh
|
||||
|
||||
- name: Run performance tests
|
||||
if: steps.run_result.outputs.run_result != 'success'
|
||||
working-directory: perf
|
||||
shell: bash
|
||||
env:
|
||||
APPSMITH_SSL_CERTIFICATE: ${{ secrets.APPSMITH_SSL_CERTIFICATE }}
|
||||
APPSMITH_SSL_KEY: ${{ secrets.APPSMITH_SSL_KEY }}
|
||||
CYPRESS_TESTUSERNAME1: ${{ secrets.CYPRESS_TESTUSERNAME9 }}
|
||||
CYPRESS_TESTPASSWORD1: ${{ secrets.CYPRESS_TESTPASSWORD9 }}
|
||||
APPSMITH_PERFORMANCE_DB_CONFIG: ${{ secrets.APPSMITH_PERFORMANCE_DB_CONFIG }}
|
||||
APPSMITH_PERFORMANCE_S3_KEY: ${{secrets.APPSMITH_PERFORMANCE_S3_KEY}}
|
||||
APPSMITH_PERFORMANCE_S3_SECRET: ${{secrets.APPSMITH_PERFORMANCE_S3_SECRET}}
|
||||
APPSMITH_PERFORMANCE_DB_PASSWORD: ${{secrets.APPSMITH_PERFORMANCE_DB_PASSWORD}}
|
||||
APPSMITH_PERFORMANCE_DB_HOST: ${{secrets.APPSMITH_PERFORMANCE_DB_HOST}}
|
||||
APPSMITH_PERFORMANCE_DB_V2_CONFIG: ${{ secrets.APPSMITH_PERFORMANCE_DB_V2_CONFIG }}
|
||||
PERF_GITHUB_PAT: ${{ secrets.APPSMITH_PERF_INFRA_REPO_PAT }}
|
||||
APPSMITH_DISABLE_TELEMETRY: true
|
||||
POSTGRES_PASSWORD: postgres
|
||||
NODE_TLS_REJECT_UNAUTHORIZED: "0"
|
||||
MACHINE: ubuntu-latest-4-cores
|
||||
|
||||
run: ./start-test.sh
|
||||
|
||||
# Restore the previous built bundle if present. If not push the newly built into the cache
|
||||
- name: Restore the previous bundle
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
perf/traces
|
||||
key: ${{ github.run_id }}-${{ github.job }}-${{ steps.timestamp.outputs.timestamp }}
|
||||
restore-keys: |
|
||||
${{ github.run_id }}-${{ github.job }}
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: performance-test-logs
|
||||
path: perf/traces/reports
|
||||
|
||||
# Set status = success
|
||||
- name: Save the status of the run
|
||||
run: echo "run_result=success" >> $GITHUB_OUTPUT > ~/run_result
|
||||
|
|
@ -29,6 +29,11 @@ jobs:
|
|||
run:
|
||||
working-directory: app/client
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job: [0, 1]
|
||||
|
||||
# Service containers to run with this job. Required for running tests
|
||||
services:
|
||||
|
|
@ -222,6 +227,7 @@ jobs:
|
|||
POSTGRES_PASSWORD: postgres
|
||||
NODE_TLS_REJECT_UNAUTHORIZED: "0"
|
||||
MACHINE: ubuntu-latest-4-cores
|
||||
JOB: ${{ matrix.job }}
|
||||
|
||||
run: ./start-test.sh
|
||||
|
||||
|
|
|
|||
|
|
@ -60,3 +60,13 @@ jobs:
|
|||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
||||
perf-test-v2:
|
||||
needs: [ build-docker-image ]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: perf-test-v2
|
||||
uses: ./.github/workflows/perf-test-v2.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: ${{ github.event.client_payload.pull_request.number }}
|
||||
|
|
@ -69,9 +69,6 @@ jobs:
|
|||
- name: Print the Github event
|
||||
run: echo ${{ github.event_name }}
|
||||
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
# In case this is second attempt try restoring status of the prior attempt from cache
|
||||
- name: Restore the previous run result
|
||||
uses: actions/cache@v3
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ jobs:
|
|||
ACTIVE_PROFILE: test
|
||||
APPSMITH_MONGODB_URI: "mongodb://localhost:27017/mobtools"
|
||||
APPSMITH_CLOUD_SERVICES_BASE_URL: "https://release-cs.appsmith.com"
|
||||
APPSMITH_CLOUD_SERVICES_TEMPLATE_UPLOAD_AUTH: ${{ secrets.APPSMITH_CLOUD_SERVICES_TEMPLATE_UPLOAD_AUTH }}
|
||||
APPSMITH_REDIS_URL: "redis://127.0.0.1:6379"
|
||||
APPSMITH_ENCRYPTION_PASSWORD: "password"
|
||||
APPSMITH_ENCRYPTION_SALT: "salt"
|
||||
|
|
|
|||
|
|
@ -45,16 +45,6 @@ jobs:
|
|||
with:
|
||||
pr: 0
|
||||
|
||||
perf-test:
|
||||
needs: [build-docker-image]
|
||||
# Only run if the build step is successful
|
||||
if: success()
|
||||
name: perf-test
|
||||
uses: ./.github/workflows/perf-test.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
pr: 0
|
||||
|
||||
ci-test:
|
||||
needs: [build-docker-image]
|
||||
# Only run if the build step is successful
|
||||
|
|
@ -106,7 +96,7 @@ jobs:
|
|||
if: needs.ci-test.result != 'success'
|
||||
shell: bash
|
||||
run: |
|
||||
new_failed_spec_env="<ol>$(sort -u ~/combined_failed_spec_ci | sed 's/|cypress|cypress/\n/g' | sed 's/^/<li>/')</ol>"
|
||||
new_failed_spec_env="<ol>$(sort -u ~/combined_failed_spec_ci | sed 's/|cypress|cypress/<\/li>\n<li>/g' | sed -e 's/^<li>//' -e 's/<\/li>$//' -e 's/<\/li>/<\/li>\n/')</ol>"
|
||||
echo "$new_failed_spec_env"
|
||||
echo "new_failed_spec_env<<EOF" >> $GITHUB_ENV
|
||||
echo "$new_failed_spec_env" >> $GITHUB_ENV
|
||||
|
|
@ -116,13 +106,23 @@ jobs:
|
|||
continue-on-error: true
|
||||
if: always()
|
||||
id: slack_notification
|
||||
env:
|
||||
EVENT_COMMITS: ${{ toJson(github.event.commits[0].message) }}
|
||||
run: |
|
||||
if [[ "${{ needs.ci-test.result }}" != "success" ]]; then
|
||||
echo "slack_message=There are test failures in the run.<br>${{env.new_failed_spec_env}}<br>Please check the <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Github Actions> for more details." >> $GITHUB_OUTPUT
|
||||
eventCommit=$(echo ${{env.EVENT_COMMITS}} | sed "s/'//g")
|
||||
echo "slack_username=$(echo "$eventCommit" | awk -F '\\\\n' '{print $1}' | sed 's/^"//;s/"$//')" >> $GITHUB_OUTPUT
|
||||
if [[ ${{ needs.ci-test.result }} == 'failure' ]]; then
|
||||
echo "slack_message=There are test failures in the run. Cypress Dashboard: <https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}&selectiontype=test&testsstatus=failed&specsstatus=fail|Click here!>" >> $GITHUB_OUTPUT
|
||||
echo "slack_color=#FF0000" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "slack_message=All tests passed successfully :tada: . Github Action: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Click here!>" >> $GITHUB_OUTPUT
|
||||
echo "slack_icon=:no_entry:" >> $GITHUB_OUTPUT
|
||||
elif [[ ${{ needs.ci-test.result }} == 'success' ]]; then
|
||||
echo "slack_message=All tests passed successfully :tada: Cypress Dashboard: <https://internal.appsmith.com/app/cypressdashboard/rundetails-64ec3df0c632e24c00764938?branch=master&workflowId=${{ github.run_id }}&attempt=${{ github.run_attempt }}|Click here!>" >> $GITHUB_OUTPUT
|
||||
echo "slack_color=#00FF00" >> $GITHUB_OUTPUT
|
||||
echo "slack_icon=:white_check_mark:" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "slack_message=There are build failures. To analyze run go <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|here>" >> $GITHUB_OUTPUT
|
||||
echo "slack_color=#FF0000" >> $GITHUB_OUTPUT
|
||||
echo "slack_icon=:warning:" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Slack Notification
|
||||
|
|
@ -132,12 +132,13 @@ jobs:
|
|||
env:
|
||||
SLACK_CHANNEL: cypresspushworkflow
|
||||
SLACK_COLOR: ${{steps.slack_notification.outputs.slack_color}}
|
||||
SLACK_ICON_EMOJI: ${{steps.slack_notification.outputs.slack_icon}}
|
||||
SLACK_ICON: https://app.slack.com/services/B05D17E4QVB
|
||||
SLACK_TITLE: 'Result:'
|
||||
SLACK_USERNAME: Cypress Push Workflows
|
||||
SLACK_TITLE: "Result:"
|
||||
SLACK_USERNAME: ${{steps.slack_notification.outputs.slack_username}}
|
||||
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_HOSTED }}
|
||||
MSG_MINIMAL: Ref,Event,Commit
|
||||
SLACK_FOOTER: 'Appsmith Push Workflows'
|
||||
SLACK_FOOTER: "Push Workflow"
|
||||
SLACK_MESSAGE: ${{steps.slack_notification.outputs.slack_message}}
|
||||
|
||||
# Force save the CI failed spec list into a cache
|
||||
|
|
@ -173,7 +174,6 @@ jobs:
|
|||
exit 1;
|
||||
fi
|
||||
|
||||
|
||||
package-release:
|
||||
needs: build-docker-image
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -220,6 +220,12 @@ jobs:
|
|||
echo "Cleaning up the tar files"
|
||||
rm app/client/packages/rts/dist/rts-dist.tar
|
||||
|
||||
- name: Generate info.json
|
||||
run: |
|
||||
if [[ -f scripts/generate_info_json.sh ]]; then
|
||||
scripts/generate_info_json.sh
|
||||
fi
|
||||
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
|
|
@ -239,6 +245,7 @@ jobs:
|
|||
build-args: |
|
||||
APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY_RELEASE }}
|
||||
APPSMITH_CLOUD_SERVICES_BASE_URL=https://release-cs.appsmith.com
|
||||
BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:release
|
||||
tags: |
|
||||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-${{ vars.EDITION }}:release
|
||||
|
||||
|
|
@ -288,6 +295,12 @@ jobs:
|
|||
echo "Cleaning up the tar files"
|
||||
rm app/client/packages/rts/dist/rts-dist.tar
|
||||
|
||||
- name: Generate info.json
|
||||
run: |
|
||||
if [[ -f scripts/generate_info_json.sh ]]; then
|
||||
scripts/generate_info_json.sh
|
||||
fi
|
||||
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
|
||||
|
|
@ -306,6 +319,44 @@ jobs:
|
|||
platforms: linux/arm64,linux/amd64
|
||||
build-args: |
|
||||
APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY }}
|
||||
BASE=${{ vars.DOCKER_HUB_ORGANIZATION }}/base-${{ vars.EDITION }}:nightly
|
||||
tags: |
|
||||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-${{ vars.EDITION }}:${{ github.sha }}
|
||||
${{ vars.DOCKER_HUB_ORGANIZATION }}/appsmith-${{ vars.EDITION }}:nightly
|
||||
|
||||
notify-slack-for-promotion:
|
||||
needs: ci-test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
if: ( failure() && github.ref == 'refs/heads/master' )
|
||||
|
||||
steps:
|
||||
- name: Notify failure on workflow run and on Slack
|
||||
run: |
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o xtrace
|
||||
|
||||
run_url='${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}'
|
||||
common_parent_sha='${{ steps.merge.outputs.common_parent_sha }}'
|
||||
common_parent_sha_short="$(echo "$common_parent_sha" | grep -o '^.\{8\}' || true)"
|
||||
merged_upto_sha='${{ steps.merge.outputs.merged_upto_sha }}'
|
||||
merged_upto_sha_short="$(echo "$merged_upto_sha" | grep -o '^.\{8\}' || true)"
|
||||
|
||||
details="🚨 TBP workflow failed in <$run_url|${{ github.run_id }}/attempts/${{ github.run_attempt }}>.
|
||||
|
||||
# This unweildy horror of a sed command, converts standard Markdown links to Slack's unweildy link syntax.
|
||||
slack_message="$(echo "$details" | sed -E 's/\[([^]]+)\]\(([^)]+)\)/<\2|\1>/g')"
|
||||
|
||||
# This is the ChannelId of the tech channel.
|
||||
body="$(jq -nc \
|
||||
--arg channel CGBPVEJ5C \
|
||||
--arg text "$slack_message" \
|
||||
'$ARGS.named'
|
||||
)"
|
||||
|
||||
curl -v https://slack.com/api/chat.postMessage \
|
||||
--fail-with-body \
|
||||
--header 'Authorization: Bearer ${{ secrets.SLACK_APPSMITH_ALERTS_TOKEN }}' \
|
||||
--header 'Content-Type: application/json; charset=utf-8' \
|
||||
--data-raw "$body"
|
||||
|
|
|
|||
|
|
@ -121,4 +121,4 @@ jobs:
|
|||
|
||||
- name: Check ci-test set status
|
||||
if: needs.ci-test.result != 'success'
|
||||
run: exit 1
|
||||
run: exit 1
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
app/client/cypress.env.json
|
||||
dist
|
||||
stacks
|
||||
/info.json
|
||||
/deploy/docker/fs/opt/appsmith/info.json
|
||||
|
||||
# to ignore the node_modeules folder
|
||||
node_modules
|
||||
|
|
|
|||
174
CODEOWNERS
174
CODEOWNERS
|
|
@ -23,12 +23,12 @@ app/client/tsconfig.json @KelvinOm
|
|||
app/client/tsconfig.path.json @KelvinOm
|
||||
|
||||
# App viewers pod
|
||||
app/client/src/widgets/* @appsmithorg/app-viewers @rajatagrawal
|
||||
app/client/src/widgets/* @appsmithorg/app-viewers
|
||||
app/client/cypress/e2e/Regression/ClientSide/Widgets/* @rajatagrawal
|
||||
app/client/src/components/propertyControls/* @appsmithorg/app-viewers
|
||||
app/client/src/sagas/OneClickBindingSaga.ts @sbalaji1192 @berzerkeer
|
||||
app/client/src/WidgetQueryGenerators/* @sbalaji1192 @berzerkeer
|
||||
app/client/src/components/editorComponents/WidgetQueryGeneratorForm/* @sbalaji1192 @berzerkeer
|
||||
app/client/src/sagas/OneClickBindingSaga.ts @sbalaji1192
|
||||
app/client/src/WidgetQueryGenerators/* @sbalaji1192
|
||||
app/client/src/components/editorComponents/WidgetQueryGeneratorForm/* @sbalaji1192
|
||||
app/client/src/pages/AppViewer/* @appsmithorg/app-viewers
|
||||
app/client/src/pages/Editor/AppSettingsPane/AppSettings/NavigationSettings/* @dhruvikn
|
||||
app/client/src/ce/pages/AppViewer/NavigationLogo.tsx @dhruvikn
|
||||
|
|
@ -63,26 +63,16 @@ app/client/src/actions/autoLayoutActions.ts @appsmithorg/ui-builders
|
|||
app/client/src/actions/canvasSelectionActions.ts @appsmithorg/ui-builders
|
||||
app/client/src/actions/reflowActions.ts @appsmithorg/ui-builders
|
||||
app/client/src/actions/widgetSelectionActions.ts @appsmithorg/ui-builders
|
||||
app/client/src/components/autoHeight/* @appsmithorg/ui-builders
|
||||
app/client/src/components/autoHeightOverlay/* @appsmithorg/ui-builders
|
||||
app/client/src/components/designSystems/appsmith/PositionedContainer.tsx @appsmithorg/ui-builders
|
||||
app/client/src/components/editorComponents/DraggableComponent.tsx @appsmithorg/ui-builders
|
||||
app/client/src/components/editorComponents/ResizableComponent.tsx @appsmithorg/ui-builders
|
||||
app/client/src/components/editorComponents/ResizableUtils.ts @appsmithorg/ui-builders
|
||||
app/client/src/components/editorComponents/ResizeStyledComponents.tsx @appsmithorg/ui-builders
|
||||
app/client/src/components/editorComponents/WidgetNameComponent/* @appsmithorg/ui-builders
|
||||
app/client/src/components/propertyControls/* @appsmithorg/ui-builders
|
||||
app/client/src/layoutSystems/* @appsmithorg/ui-builders
|
||||
app/client/src/normalizers/CanvasWidgetsNormalizer.tsx @appsmithorg/ui-builders
|
||||
app/client/src/pages/Editor/Canvas.tsx @appsmithorg/ui-builders
|
||||
app/client/src/pages/Editor/CanvasLayoutConversion/* @appsmithorg/ui-builders
|
||||
app/client/src/pages/Editor/PropertyPane/* @appsmithorg/ui-builders
|
||||
app/client/src/pages/Editor/WidgetsMultiSelectBox.tsx @appsmithorg/ui-builders
|
||||
app/client/src/pages/common/CanvasArenas/* @appsmithorg/ui-builders
|
||||
app/client/src/reducers/entityReducers/autoHeightReducers/* @appsmithorg/ui-builders
|
||||
app/client/src/reducers/entityReducers/canvasWidgetsReducer.ts @appsmithorg/ui-builders
|
||||
app/client/src/reducers/entityReducers/widgetConfigReducer.ts @appsmithorg/ui-builders
|
||||
app/client/src/reflow/* @appsmithorg/ui-builders
|
||||
app/client/src/resizable/* @appsmithorg/ui-builders
|
||||
app/client/src/sagas/AutoLayoutUpdateSagas.tsx @appsmithorg/ui-builders
|
||||
app/client/src/sagas/CanvasSagas/* @appsmithorg/ui-builders
|
||||
app/client/src/sagas/ReplaySaga.ts @appsmithorg/ui-builders
|
||||
|
|
@ -102,7 +92,6 @@ app/client/src/selectors/canvasSelectors.ts @appsmithorg/ui-builders
|
|||
app/client/src/selectors/widgetSelectors.ts @appsmithorg/ui-builders
|
||||
app/client/src/utils/DSLConversions/* @appsmithorg/ui-builders
|
||||
app/client/src/utils/autoHeight/* @appsmithorg/ui-builders
|
||||
app/client/src/utils/autoLayout/* @appsmithorg/ui-builders
|
||||
app/client/src/utils/hooks/autoHeightUIHooks.ts @appsmithorg/ui-builders
|
||||
app/client/src/utils/hooks/useAllowEditorDragToSelect.ts @appsmithorg/ui-builders
|
||||
app/client/src/utils/hooks/useClickToSelectWidget.tsx @appsmithorg/ui-builders
|
||||
|
|
@ -111,7 +100,7 @@ app/client/src/utils/hooks/usePositionedContainerZIndex.ts @appsmithorg/ui-build
|
|||
app/client/src/utils/hooks/useReflow.ts @appsmithorg/ui-builders
|
||||
app/client/src/utils/hooks/useWidgetSelection.ts @appsmithorg/ui-builders
|
||||
app/client/src/widgets/BaseWidget.tsx @appsmithorg/ui-builders
|
||||
app/client/src/widgets/CanvasResizer.tsx @appsmithorg/ui-builders
|
||||
app/client/src/widgets/BaseWidgetHOC/* @appsmithorg/ui-builders
|
||||
app/client/src/widgets/CanvasWidget.tsx @appsmithorg/ui-builders
|
||||
app/client/src/widgets/ContainerWidget/* @appsmithorg/ui-builders
|
||||
app/client/src/widgets/MetaHOC.tsx @appsmithorg/ui-builders
|
||||
|
|
@ -132,82 +121,115 @@ app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/GitUtils.ja
|
|||
|
||||
# Data Platform
|
||||
|
||||
app/client/src/actions/datasourceActions.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/api/ActionAPI.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/ce/components/DSDataFilter/index.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/ce/constants/ReduxActionConstants.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/ce/sagas/ApplicationSagas.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/ce/selectors/environmentSelectors.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/ce/utils/Environments/index.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/components/BottomBar/index.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/components/formControls/utils.test.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/components/formControls/utils.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/entities/Datasource/index.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/entities/FeatureFlags.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/navigation/FocusEntity.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/APIEditor/* @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/DataSourceEditor/* @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/IntegrationEditor/IntegrationsHomeScreen.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/IntegrationEditor/NewApi.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/QueryEditor/EditorJSONtoForm.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/SaaSEditor/DatasourceCard.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/pages/common/datasourceAuth/index.tsx @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/reducers/entityReducers/datasourceReducer.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/sagas/ActionExecution/PluginActionSaga.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/sagas/DatasourcesSagas.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/sagas/QueryPaneSagas.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/transformers/RestAPIDatasourceFormTransformer.ts @ayushpahwa @ChandanBalajiBP
|
||||
app/client/src/actions/datasourceActions.ts @ayushpahwa
|
||||
app/client/src/api/ActionAPI.tsx @ayushpahwa
|
||||
app/client/src/ce/components/DSDataFilter/index.tsx @ayushpahwa
|
||||
app/client/src/ce/constants/ReduxActionConstants.tsx @ayushpahwa
|
||||
app/client/src/ce/sagas/ApplicationSagas.tsx @ayushpahwa
|
||||
app/client/src/ce/selectors/environmentSelectors.tsx @ayushpahwa
|
||||
app/client/src/ce/utils/Environments/index.tsx @ayushpahwa
|
||||
app/client/src/components/BottomBar/index.tsx @ayushpahwa
|
||||
app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx @ayushpahwa
|
||||
app/client/src/components/formControls/utils.test.ts @ayushpahwa
|
||||
app/client/src/components/formControls/utils.ts @ayushpahwa
|
||||
app/client/src/entities/Datasource/index.ts @ayushpahwa
|
||||
app/client/src/entities/FeatureFlags.ts @ayushpahwa
|
||||
app/client/src/navigation/FocusEntity.ts @ayushpahwa
|
||||
app/client/src/pages/Editor/APIEditor/* @ayushpahwa
|
||||
app/client/src/pages/Editor/DataSourceEditor/* @ayushpahwa
|
||||
app/client/src/pages/Editor/IntegrationEditor/DatasourceCard.tsx @ayushpahwa
|
||||
app/client/src/pages/Editor/IntegrationEditor/IntegrationsHomeScreen.tsx @ayushpahwa
|
||||
app/client/src/pages/Editor/IntegrationEditor/NewApi.tsx @ayushpahwa
|
||||
app/client/src/pages/Editor/QueryEditor/EditorJSONtoForm.tsx @ayushpahwa
|
||||
app/client/src/pages/Editor/SaaSEditor/DatasourceCard.tsx @ayushpahwa
|
||||
app/client/src/pages/Editor/SaaSEditor/DatasourceForm.tsx @ayushpahwa
|
||||
app/client/src/pages/Editor/gitSync/ReconnectDatasourceModal.tsx @ayushpahwa
|
||||
app/client/src/pages/common/datasourceAuth/index.tsx @ayushpahwa
|
||||
app/client/src/reducers/entityReducers/datasourceReducer.ts @ayushpahwa
|
||||
app/client/src/sagas/ActionExecution/PluginActionSaga.ts @ayushpahwa
|
||||
app/client/src/sagas/DatasourcesSagas.ts @ayushpahwa
|
||||
app/client/src/sagas/QueryPaneSagas.ts @ayushpahwa
|
||||
app/client/src/transformers/RestAPIDatasourceFormTransformer.ts @ayushpahwa
|
||||
|
||||
|
||||
# Followed Globstar paths in combination with wildcard paths. Reference https://docs.gitlab.com/ee/user/project/codeowners/reference.html#globstar-paths
|
||||
# Data Platform server - Interfaces
|
||||
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/OAuth2* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/Datasource* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-interfaces/src/main/java/com/appsmith/external/**/OAuth2* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - Controllers
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/**/Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/**/Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/**/Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/**/Datasource* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - Domains
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/**/Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/**/Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/**/Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/**/Datasource* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - DTOs
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/**/Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/**/Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/**/Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/**/Datasource* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - Repositories
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/**/*Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/**/*Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/**/*Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/**/*Datasource* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - Services
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Authentication* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Datasource* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/services/**/*Authentication* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - Solutions
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Action* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Authentication* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Environment* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Action* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Datasource* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Authentication* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/**/*Environment* @nidhi-nair @sondermanish
|
||||
|
||||
# Data Platform server - Misc
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/**/Datasource* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError* @nidhi-nair @sondermanish @tkappsmith
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/**/Datasource* @nidhi-nair @sondermanish
|
||||
app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError* @nidhi-nair @sondermanish
|
||||
|
||||
# Team Managers pod
|
||||
app/client/src/ce/* @ankitakinger
|
||||
app/client/src/ee/* @ankitakinger
|
||||
app/client/src/pages/Settings/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/Enterprise/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/EE/Enterprise/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/AdminSettings/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/Google/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/Github/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/FormLogin/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/Auditlogs/* @ankitakinger
|
||||
app/client/src/pages/Settings/**/* @ankitakinger
|
||||
app/client/src/pages/workspace/settings.tsx @ankitakinger
|
||||
app/client/src/pages/workspace/AppInviteUsersForm.tsx @ankitakinger
|
||||
app/client/src/pages/workspace/WorkspaceInviteUsersForm.tsx @ankitakinger
|
||||
app/client/src/components/editorComponents/form/FormDialogComponent.tsx @ankitakinger
|
||||
app/client/src/ce/pages/AdminSettings/**/* @ankitakinger
|
||||
app/client/src/ee/pages/AdminSettings/**/* @ankitakinger
|
||||
app/client/src/ce/pages/Applications/EmbedSnippetTab.tsx @ankitakinger
|
||||
app/client/src/ee/pages/Applications/EmbedSnippetTab.tsx @ankitakinger
|
||||
app/client/src/ce/pages/Applications/PrivateEmbedSettings.tsx @ankitakinger
|
||||
app/client/src/ee/pages/Applications/PrivateEmbedSettings.tsx @ankitakinger
|
||||
app/client/src/ce/pages/workspace/Members.tsx @ankitakinger
|
||||
app/client/src/ee/pages/workspace/Members.tsx @ankitakinger
|
||||
app/client/src/ce/pages/workspace/InviteUsersForm.tsx @ankitakinger
|
||||
app/client/src/ee/pages/workspace/InviteUsersForm.tsx @ankitakinger
|
||||
app/client/src/ce/pages/Upgrade/**/* @ankitakinger
|
||||
app/client/src/ee/pages/Auditlogs/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/Enterprise/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/EE/Enterprise/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/AdminSettings/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/Google/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/Github/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/FormLogin/**/* @ankitakinger
|
||||
app/client/cypress/e2e/Regression/ClientSide/Auditlogs/**/* @ankitakinger
|
||||
|
||||
#FE pod
|
||||
app/client/src/actions/evaluationActions.ts @ApekshaBhosale
|
||||
app/client/src/ce/entities/DataTree/**/* @ApekshaBhosale
|
||||
app/client/src/ce/entities/DependencyMap/**/* @ApekshaBhosale
|
||||
app/client/src/ce/entities/workers/**/* @ApekshaBhosale
|
||||
app/client/src/ee/entities/DataTree* @ApekshaBhosale
|
||||
app/client/src/ee/entities/workers/**/* @ApekshaBhosale
|
||||
app/client/src/sagas/EvaluationsSaga.ts @ApekshaBhosale
|
||||
app/client/src/sagas/EvalWorkerActionSagas.ts @ApekshaBhosale
|
||||
app/client/src/sagas/LintingSagas.ts @ApekshaBhosale
|
||||
app/client/src/sagas/PostEvaluationSags.ts @ApekshaBhosale
|
||||
app/client/src/sagas/PostLintingSagas.ts @ApekshaBhosale
|
||||
app/client/src/workers/**/* @ApekshaBhosale
|
||||
app/client/src/sagas/JSLibrarySaga.ts @ApekshaBhosale
|
||||
app/client/src/ce/ActionExecution/ActionExecutionSagas.ts @ApekshaBhosale
|
||||
app/client/src/ee/ActionExecution/ActionExecutionSagas.ts @ApekshaBhosale
|
||||
app/client/src/ce/JSFunctionExecutionSaga.ts @ApekshaBhosale
|
||||
app/client/src/ee/JSFunctionExecutionSaga.ts @ApekshaBhosale
|
||||
|
|
|
|||
46
Dockerfile
46
Dockerfile
|
|
@ -14,7 +14,9 @@ ENV APPSMITH_CLOUD_SERVICES_BASE_URL=${APPSMITH_CLOUD_SERVICES_BASE_URL}
|
|||
ARG APPSMITH_SEGMENT_CE_KEY
|
||||
ENV APPSMITH_SEGMENT_CE_KEY=${APPSMITH_SEGMENT_CE_KEY}
|
||||
#Create the plugins directory
|
||||
RUN mkdir -p ./backend ./editor ./rts ./backend/plugins ./templates ./utils
|
||||
RUN mkdir -p ./editor ./rts ./backend/plugins
|
||||
|
||||
COPY deploy/docker/fs /
|
||||
|
||||
#Add the jar to the container
|
||||
COPY ${JAR_FILE} backend/server.jar
|
||||
|
|
@ -24,45 +26,19 @@ COPY ${PLUGIN_JARS} backend/plugins/
|
|||
COPY ./app/client/build editor/
|
||||
|
||||
# Add RTS - Application Layer
|
||||
COPY ./app/client/packages/rts/package.json ./app/client/packages/rts/dist rts/
|
||||
COPY ./app/client/packages/rts/dist rts/
|
||||
|
||||
# Nginx, MongoDB and PostgreSQL data config template - Configuration layer
|
||||
COPY ./deploy/docker/templates/nginx/* \
|
||||
./deploy/docker/templates/docker.env.sh \
|
||||
./deploy/docker/templates/mockdb_postgres.sql \
|
||||
./deploy/docker/templates/users_postgres.sql \
|
||||
./deploy/docker/templates/appsmith_starting.html \
|
||||
./deploy/docker/templates/appsmith_initializing.html \
|
||||
templates/
|
||||
ENV PATH /opt/appsmith/utils/node_modules/.bin:/opt/java/bin:/opt/node/bin:$PATH
|
||||
|
||||
# Add bootstrapfile
|
||||
COPY ./deploy/docker/entrypoint.sh ./deploy/docker/scripts/* info.*json ./
|
||||
RUN cd ./utils && npm install --only=prod && npm install --only=prod -g . && cd - \
|
||||
&& chmod 0644 /etc/cron.d/* \
|
||||
&& chmod +x *.sh templates/nginx-app.conf.sh /watchtower-hooks/*.sh \
|
||||
# Disable setuid/setgid bits for the files inside container.
|
||||
&& find / \( -path /proc -prune \) -o \( \( -perm -2000 -o -perm -4000 \) -print -exec chmod -s '{}' + \) || true \
|
||||
&& node prepare-image.mjs
|
||||
|
||||
# Add util tools
|
||||
COPY ./deploy/docker/utils ./utils
|
||||
RUN cd ./utils && npm install --only=prod && npm install --only=prod -g .
|
||||
|
||||
# Add process config to be run by supervisord
|
||||
COPY ./deploy/docker/templates/supervisord.conf /etc/supervisor/supervisord.conf
|
||||
COPY ./deploy/docker/templates/supervisord/ templates/supervisord/
|
||||
|
||||
# Add defined cron job
|
||||
COPY ./deploy/docker/templates/cron.d /etc/cron.d/
|
||||
RUN chmod 0644 /etc/cron.d/*
|
||||
|
||||
RUN chmod +x entrypoint.sh renew-certificate.sh healthcheck.sh
|
||||
|
||||
# Disable setuid/setgid bits for the files inside container.
|
||||
RUN find / \( -path /proc -prune \) -o \( \( -perm -2000 -o -perm -4000 \) -print -exec chmod -s '{}' + \) || true
|
||||
|
||||
# Update path to load appsmith utils tool as default
|
||||
ENV PATH /opt/appsmith/utils/node_modules/.bin:$PATH
|
||||
LABEL com.centurylinklabs.watchtower.lifecycle.pre-check=/watchtower-hooks/pre-check.sh
|
||||
LABEL com.centurylinklabs.watchtower.lifecycle.pre-update=/watchtower-hooks/pre-update.sh
|
||||
COPY ./deploy/docker/watchtower-hooks /watchtower-hooks
|
||||
RUN chmod +x /watchtower-hooks/pre-check.sh
|
||||
RUN chmod +x /watchtower-hooks/pre-update.sh
|
||||
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
|
|
|||
2
app.json
2
app.json
|
|
@ -31,7 +31,7 @@
|
|||
"value": ""
|
||||
},
|
||||
"APPSMITH_DISABLE_TELEMETRY": {
|
||||
"description" : "We want to be transparent and request that you share anonymous usage data with us. This data is purely statistical in nature and helps us understand your needs & provide better support to your self-hosted instance. You can read more about what information is collected in our documentation https://docs.appsmith.com/v/v1.2.1/setup/telemetry",
|
||||
"description" : "We want to be transparent and request that you share anonymous usage data with us. This data is purely statistical in nature and helps us understand your needs & provide better support to your self-hosted instance. You can read more about what information is collected in our documentation https://docs.appsmith.com/product/telemetry",
|
||||
"value": "false"
|
||||
},
|
||||
"APPSMITH_SUPERVISOR_PASSWORD": {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
"$schema": "http://json.schemastore.org/eslintrc",
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"ignorePatterns": [
|
||||
"jest.config.js",
|
||||
"jest.setup.ts",
|
||||
"rollup.config.js",
|
||||
".eslintrc.js"
|
||||
],
|
||||
"plugins": [
|
||||
"react",
|
||||
"@typescript-eslint",
|
||||
|
|
@ -22,9 +28,14 @@
|
|||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": "error",
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/strict-boolean-expressions": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-unused-vars": "warn",
|
||||
"jest/no-focused-tests": "error",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ const baseNoRestrictedImports =
|
|||
const eslintConfig = {
|
||||
extends: [".eslintrc.base.json"],
|
||||
rules: {
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"react/display-name": "off",
|
||||
"react/prop-types": "off",
|
||||
|
|
@ -86,6 +88,9 @@ const eslintConfig = {
|
|||
},
|
||||
],
|
||||
},
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
};
|
||||
|
||||
eslintConfig.overrides = [
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ cypress/videos
|
|||
cypress/screenshots
|
||||
cypress/limited-tests.txt
|
||||
cypress.env.json
|
||||
cypress/cypress-logs
|
||||
results/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,13 @@
|
|||
is_server_change=$(git diff --cached --name-only | grep -c "app/server")
|
||||
is_client_change=$(git diff --cached --name-only | grep -c "app/client")
|
||||
|
||||
if [ "$is_server_change" -ge 1 ]; then
|
||||
echo "Running Spotless check ..."
|
||||
is_merge_commit=$(git rev-parse -q --verify MERGE_HEAD)
|
||||
|
||||
if [ "$is_merge_commit" ]; then
|
||||
echo "Skipping server and client checks for merge commit"
|
||||
else
|
||||
if [ "$is_server_change" -ge 1 ]; then
|
||||
echo "Running Spotless check ..."
|
||||
pushd app/server > /dev/null
|
||||
if (mvn spotless:check 1> /dev/null && popd > /dev/null) then
|
||||
popd
|
||||
|
|
@ -12,13 +17,14 @@ if [ "$is_server_change" -ge 1 ]; then
|
|||
echo "Spotless check failed, please run mvn spotless:apply"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping server side check..."
|
||||
fi
|
||||
else
|
||||
echo "Skipping server side check..."
|
||||
fi
|
||||
|
||||
if [ "$is_client_change" -ge 1 ]; then
|
||||
echo "Running client check ..."
|
||||
npx lint-staged --cwd app/client && git-secrets --scan --untracked && git-secrets --scan -r
|
||||
else
|
||||
echo "Skipping client side check..."
|
||||
if [ "$is_client_change" -ge 1 ]; then
|
||||
echo "Running client check ..."
|
||||
npx lint-staged --cwd app/client
|
||||
else
|
||||
echo "Skipping client side check..."
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"src/**/*.{js,ts,tsx}": ["npx eslint --fix"],
|
||||
"src/**/*.{js,ts,tsx,css,md,json}": ["npx prettier --write"],
|
||||
"cypress/**/*.{js,ts}": ["npx eslint --fix"],
|
||||
"cypress/**/*.{js,ts,json}": ["npx prettier --write"],
|
||||
"packages/**/*.{js,ts,tsx}": ["npx eslint --fix"],
|
||||
"packages/**/*.{js,ts,tsx,css,mdx,json}": ["npx prettier --write"]
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"src/**/*.{js,ts,tsx}": ["eslint --fix --cache"],
|
||||
"src/**/*.{css,md,json}": ["prettier --write --cache"],
|
||||
"cypress/**/*.{js,ts}": [
|
||||
"cd ./cypress && eslint -c .eslintrc.json --fix --cache"
|
||||
],
|
||||
"cypress/**/*.json": ["prettier --write --cache"],
|
||||
"packages/**/*.{js,ts,tsx}": ["eslint --fix --cache"],
|
||||
"packages/**/*.{css,mdx,json}": ["prettier --write --cache"],
|
||||
"*": ["git-secrets --scan --cached"]
|
||||
}
|
||||
|
|
@ -1,13 +1,8 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const CracoAlias = require("craco-alias");
|
||||
const CracoLessPlugin = require("craco-less");
|
||||
const {
|
||||
DefinePlugin,
|
||||
EnvironmentPlugin
|
||||
} = require("webpack");
|
||||
const {
|
||||
merge
|
||||
} = require("webpack-merge");
|
||||
const { DefinePlugin, EnvironmentPlugin } = require("webpack");
|
||||
const { merge } = require("webpack-merge");
|
||||
const CracoBabelLoader = require("craco-babel-loader");
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
|
@ -44,25 +39,78 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.m?js/,
|
||||
resolve: {
|
||||
fullySpecified: false,
|
||||
rules: [
|
||||
{
|
||||
test: /\.m?js/,
|
||||
resolve: {
|
||||
fullySpecified: false,
|
||||
},
|
||||
},
|
||||
}, ],
|
||||
{
|
||||
test: /\.module\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: "postcss-loader",
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: [
|
||||
"postcss-nesting",
|
||||
"postcss-import",
|
||||
"postcss-at-rules-variables",
|
||||
"postcss-each",
|
||||
"postcss-url",
|
||||
"postcss-modules-values",
|
||||
[
|
||||
"cssnano",
|
||||
{
|
||||
preset: ["default"],
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
icons: {
|
||||
// This determines which modules are considered icons
|
||||
test: (module) => {},
|
||||
test: (module) => {
|
||||
const modulePath = module.resource;
|
||||
if (!modulePath) return false;
|
||||
|
||||
return (
|
||||
modulePath.match(
|
||||
/node_modules[\\\/]remixicon-react[\\\/]/,
|
||||
) ||
|
||||
modulePath.endsWith(".svg.js") ||
|
||||
modulePath.endsWith(".svg")
|
||||
);
|
||||
},
|
||||
// This determines which chunk to put the icon into.
|
||||
//
|
||||
// Why have three separate cache groups for three different kinds of
|
||||
// icons? Purely as an optimization: not every page needs all icons,
|
||||
// so we can avoid loading unused icons sometimes.
|
||||
name: (module) => {},
|
||||
name: (module) => {
|
||||
if (
|
||||
module.resource?.match(
|
||||
/node_modules[\\\/]remixicon-react[\\\/]/,
|
||||
)
|
||||
) {
|
||||
return "remix-icons";
|
||||
}
|
||||
|
||||
if (module.resource?.includes("blueprint")) {
|
||||
return "blueprint-icons";
|
||||
}
|
||||
|
||||
return "svg-icons";
|
||||
},
|
||||
// This specifies that only icons from import()ed chunks should be moved
|
||||
chunks: "async",
|
||||
// This makes webpack ignore the minimum chunk size requirement
|
||||
|
|
@ -93,10 +141,8 @@ module.exports = {
|
|||
],
|
||||
};
|
||||
const scopePluginIndex = webpackConfig.resolve.plugins.findIndex(
|
||||
({
|
||||
constructor
|
||||
}) =>
|
||||
constructor && constructor.name === "ModuleScopePlugin",
|
||||
({ constructor }) =>
|
||||
constructor && constructor.name === "ModuleScopePlugin",
|
||||
);
|
||||
webpackConfig.resolve.plugins.splice(scopePluginIndex, 1);
|
||||
return merge(webpackConfig, config);
|
||||
|
|
@ -131,10 +177,10 @@ module.exports = {
|
|||
],
|
||||
},
|
||||
},
|
||||
|
||||
},
|
||||
},
|
||||
plugins: [{
|
||||
plugins: [
|
||||
{
|
||||
plugin: CracoAlias,
|
||||
options: {
|
||||
source: "tsconfig",
|
||||
|
|
@ -175,9 +221,7 @@ module.exports = {
|
|||
// This matters for cases where `src/<dirname>` and `node_modules/<dirname>` both exist –
|
||||
// e.g., when `<dirname>` is `entities`: https://github.com/appsmithorg/appsmith/pull/20964#discussion_r1124782356
|
||||
plugin: {
|
||||
overrideWebpackConfig: ({
|
||||
webpackConfig
|
||||
}) => {
|
||||
overrideWebpackConfig: ({ webpackConfig }) => {
|
||||
webpackConfig.resolve.modules = [
|
||||
path.resolve(__dirname, "src"),
|
||||
...webpackConfig.resolve.modules,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ export default defineConfig({
|
|||
requestTimeout: 60000,
|
||||
responseTimeout: 60000,
|
||||
pageLoadTimeout: 60000,
|
||||
videoUploadOnPasses: false,
|
||||
videoCompression: false,
|
||||
video: true,
|
||||
numTestsKeptInMemory: 5,
|
||||
experimentalMemoryManagement: true,
|
||||
reporterOptions: {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
{
|
||||
"extends": ["../.eslintrc.base.json"],
|
||||
"ignorePatterns": ["locators", "fixtures"],
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/no-array-constructor": "off",
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
|
|
|
|||
|
|
@ -1,187 +0,0 @@
|
|||
/* eslint-disable no-console */
|
||||
import globby from "globby";
|
||||
import minimatch from "minimatch";
|
||||
import { exec } from "child_process";
|
||||
|
||||
const fs = require("fs/promises");
|
||||
|
||||
type GetEnvOptions = {
|
||||
required?: boolean;
|
||||
};
|
||||
|
||||
// some default properties
|
||||
const ignoreTestFiles = [
|
||||
"cypress/e2e/**/spec_utility.ts",
|
||||
"cypress/e2e/GSheet/**/*",
|
||||
];
|
||||
|
||||
// used to roughly determine how many tests are in a file
|
||||
const testPattern = /(^|\s)(it)\(/g;
|
||||
|
||||
// This function will get all the spec paths using the pattern
|
||||
async function getSpecFilePaths(specPattern: any): Promise<string[]> {
|
||||
const files = globby.sync(specPattern, {
|
||||
ignore: ignoreTestFiles,
|
||||
});
|
||||
|
||||
// ignore the files that doesn't match
|
||||
const ignorePatterns = [...(ignoreTestFiles || [])];
|
||||
|
||||
// a function which returns true if the file does NOT match
|
||||
const doesNotMatchAllIgnoredPatterns = (file: string) => {
|
||||
// using {dot: true} here so that folders with a '.' in them are matched
|
||||
const MINIMATCH_OPTIONS = { dot: true, matchBase: true };
|
||||
return ignorePatterns.every((pattern) => {
|
||||
return !minimatch(file, pattern, MINIMATCH_OPTIONS);
|
||||
});
|
||||
};
|
||||
const filtered = files.filter(doesNotMatchAllIgnoredPatterns);
|
||||
return filtered;
|
||||
}
|
||||
|
||||
// This function will determine the test counts in each file to sort it further
|
||||
async function getTestCount(filePath: string): Promise<number> {
|
||||
const content = await fs.readFile(filePath, "utf8");
|
||||
return content.match(testPattern)?.length || 0;
|
||||
}
|
||||
|
||||
// Sorting the spec files as per the test count in it
|
||||
async function sortSpecFilesByTestCount(
|
||||
specPathsOriginal: string[],
|
||||
): Promise<string[]> {
|
||||
const specPaths = [...specPathsOriginal];
|
||||
|
||||
const testPerSpec: Record<string, number> = {};
|
||||
|
||||
for (const specPath of specPaths) {
|
||||
testPerSpec[specPath] = await getTestCount(specPath);
|
||||
}
|
||||
|
||||
return (
|
||||
Object.entries(testPerSpec)
|
||||
// Sort by the number of tests per spec file. And this will create a consistent file list/ordering so that file division proper.
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.map((x) => x[0])
|
||||
);
|
||||
}
|
||||
|
||||
// This function will split the specs between the runners by calculating the modulus between spec index and the totalRunners
|
||||
function splitSpecs(
|
||||
specs: string[],
|
||||
totalRunnersCount: number,
|
||||
currentRunner: number,
|
||||
): string[] {
|
||||
let specs_to_run = specs.filter((_, index) => {
|
||||
return index % totalRunnersCount === currentRunner;
|
||||
});
|
||||
return specs_to_run;
|
||||
}
|
||||
|
||||
// This function will finally get the specs as a comma separated string to pass the specs to the command
|
||||
async function getSpecsToRun(
|
||||
totalRunnersCount = 0,
|
||||
currentRunner = 0,
|
||||
specPattern = "cypress/e2e/**/**/*.{js,ts}",
|
||||
): Promise<string> {
|
||||
{
|
||||
try {
|
||||
const specFilePaths = await sortSpecFilesByTestCount(
|
||||
await getSpecFilePaths(specPattern),
|
||||
);
|
||||
|
||||
if (!specFilePaths.length) {
|
||||
throw Error("No spec files found.");
|
||||
}
|
||||
const specsToRun = splitSpecs(
|
||||
specFilePaths,
|
||||
totalRunnersCount,
|
||||
currentRunner,
|
||||
);
|
||||
return specsToRun.join(",");
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function will help to get and convert the env variables
|
||||
function getEnvNumber(
|
||||
varName: string,
|
||||
{ required = false }: GetEnvOptions = {},
|
||||
): number {
|
||||
if (required && process.env[varName] === undefined) {
|
||||
throw Error(`${varName} is not set.`);
|
||||
}
|
||||
const value = Number(process.env[varName]);
|
||||
if (isNaN(value)) {
|
||||
throw Error(`${varName} is not a number.`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// This function will helps to check and get env variables
|
||||
function getEnvValue(
|
||||
varName: string,
|
||||
{ required = false }: GetEnvOptions = {},
|
||||
) {
|
||||
if (required && process.env[varName] === undefined) {
|
||||
throw Error(`${varName} is not set.`);
|
||||
}
|
||||
const value = process.env[varName] === undefined ? "" : process.env[varName];
|
||||
return value;
|
||||
}
|
||||
|
||||
// This is to fetch the env variables from CI
|
||||
function getArgs() {
|
||||
return {
|
||||
totalRunners: getEnvNumber("TOTAL_RUNNERS", { required: true }),
|
||||
thisRunner: getEnvNumber("THIS_RUNNER", { required: true }),
|
||||
specsPattern: getEnvValue("CYPRESS_SPEC_PATTERN", { required: true }),
|
||||
env: getEnvValue("CYPRESS_ENV", { required: false }),
|
||||
configFile: getEnvValue("CYPRESS_CONFIG_FILE", { required: false }),
|
||||
headless: getEnvValue("CYPRESS_HEADLESS", { required: false }),
|
||||
browser: getEnvValue("CYPRESS_BROWSER", { required: false }),
|
||||
};
|
||||
}
|
||||
|
||||
// This will finally segregate the specs and run the command to execute cypress
|
||||
(async () => {
|
||||
try {
|
||||
const {
|
||||
browser,
|
||||
configFile,
|
||||
env,
|
||||
headless,
|
||||
specsPattern,
|
||||
thisRunner,
|
||||
totalRunners,
|
||||
} = getArgs();
|
||||
|
||||
let command = "yarn cypress run ";
|
||||
command += browser != "" ? `--browser ${browser} ` : "";
|
||||
command += configFile != "" ? `--config-file ${configFile} ` : "";
|
||||
command += env != "" ? `--env ${env} ` : "";
|
||||
command += headless == "false" ? `--headed ` : "";
|
||||
|
||||
const specs = await getSpecsToRun(totalRunners, thisRunner, specsPattern);
|
||||
const final_command = `${command} --spec "${specs}"`;
|
||||
const commandProcess = exec(final_command);
|
||||
|
||||
// pipe output because we want to see the results of the run
|
||||
if (commandProcess.stdout) {
|
||||
commandProcess.stdout.pipe(process.stdout);
|
||||
}
|
||||
|
||||
if (commandProcess.stderr) {
|
||||
commandProcess.stderr.pipe(process.stderr);
|
||||
}
|
||||
|
||||
commandProcess.on("exit", (code) => {
|
||||
process.exit(code || 0);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
||||
|
|
@ -6,6 +6,9 @@ import {
|
|||
dataSources,
|
||||
agHelper,
|
||||
entityExplorer,
|
||||
table,
|
||||
assertHelper,
|
||||
appSettings,
|
||||
} from "../../support/Objects/ObjectsCore";
|
||||
|
||||
const workspaceName = "gsheet apps";
|
||||
|
|
@ -22,8 +25,7 @@ describe("GSheet-Functional Tests With All Access", function () {
|
|||
|
||||
//Adding query to insert a new spreadsheet
|
||||
homePage.NavigateToHome();
|
||||
homePage.CreateAppInWorkspace(workspaceName);
|
||||
homePage.RenameApplication(appName);
|
||||
homePage.CreateAppInWorkspace(workspaceName, appName);
|
||||
gsheetHelper.AddNewSpreadsheetQuery(
|
||||
dataSourceName,
|
||||
spreadSheetName,
|
||||
|
|
@ -173,21 +175,20 @@ describe("GSheet-Functional Tests With All Access", function () {
|
|||
dataSources.RunQueryNVerifyResponseViews(8);
|
||||
dataSources.AssertQueryTableResponse(0, "87bbb472ef9d90dcef140a551665c929");
|
||||
|
||||
// Currently commenting this until https://github.com/appsmithorg/appsmith/issues/25447 is fixed.
|
||||
// Filter by cell range and verify
|
||||
// dataSources.ValidateNSelectDropdown(
|
||||
// "Filter Format",
|
||||
// "Where Clause",
|
||||
// "Cell range",
|
||||
// );
|
||||
// agHelper.EnterValue("A2:A5", {
|
||||
// propFieldName: "",
|
||||
// directInput: false,
|
||||
// inputFieldName: "Cell range",
|
||||
// });
|
||||
// dataSources.RunQuery();
|
||||
// dataSources.RunQueryNVerifyResponseViews(8);
|
||||
// dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"Filter Format",
|
||||
"Where Clause",
|
||||
"Cell range",
|
||||
);
|
||||
agHelper.EnterValue("A2:A5", {
|
||||
propFieldName: "",
|
||||
directInput: false,
|
||||
inputFieldName: "Cell range",
|
||||
});
|
||||
dataSources.RunQuery();
|
||||
dataSources.RunQueryNVerifyResponseViews(4);
|
||||
dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
|
||||
it("5. Update a record which is not present and verify the error", () => {
|
||||
|
|
@ -286,8 +287,44 @@ describe("GSheet-Functional Tests With All Access", function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("8. Import an app with all access sheet", function () {
|
||||
homePage.NavigateToHome();
|
||||
homePage.ImportApp("ImportAppAllAccess.json", workspaceName);
|
||||
assertHelper.WaitForNetworkCall("importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
//Validate table is not empty!
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("ImportAppAllAccess");
|
||||
});
|
||||
|
||||
it("9. App level import of app with all access gsheet", function () {
|
||||
homePage.CreateAppInWorkspace(workspaceName, "AppLevelImport");
|
||||
appSettings.OpenAppSettings();
|
||||
appSettings.GoToImport();
|
||||
agHelper.ClickButton("Import");
|
||||
homePage.ImportApp("ImportAppAllAccess.json", "", true);
|
||||
cy.wait("@importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
agHelper.RefreshPage();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("AppLevelImport");
|
||||
});
|
||||
|
||||
after("Delete spreadsheet and app", function () {
|
||||
// Delete spreadsheet and app
|
||||
homePage.SearchAndOpenApp(appName);
|
||||
gsheetHelper.DeleteSpreadsheetQuery(dataSourceName, spreadSheetName);
|
||||
cy.get("@postExecute").then((interception: any) => {
|
||||
expect(interception.response.body.data.body.message).to.deep.equal(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
deployMode,
|
||||
locators,
|
||||
draggableWidgets,
|
||||
appSettings,
|
||||
} from "../../support/Objects/ObjectsCore";
|
||||
|
||||
const workspaceName = "gsheet apps";
|
||||
|
|
@ -45,6 +46,7 @@ describe("GSheet Miscellaneous Tests", function () {
|
|||
JSON.stringify(GSHEET_DATA),
|
||||
);
|
||||
cy.get("@postExecute").then((interception: any) => {
|
||||
agHelper.Sleep();
|
||||
expect(
|
||||
interception.response.body.data.body.properties.title,
|
||||
).to.deep.equal(spreadSheetName);
|
||||
|
|
@ -119,7 +121,7 @@ describe("GSheet Miscellaneous Tests", function () {
|
|||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
|
||||
//deploy the app and verify the table data
|
||||
|
|
@ -176,7 +178,7 @@ describe("GSheet Miscellaneous Tests", function () {
|
|||
assertHelper.AssertNetworkStatus("@getActions", 200);
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
|
||||
//deploy the app and verify the table data
|
||||
|
|
@ -212,8 +214,62 @@ describe("GSheet Miscellaneous Tests", function () {
|
|||
table.WaitUntilTableLoad();
|
||||
});
|
||||
|
||||
it("6. Bug: 16391 - Verify placeholder texts for insert one/many queries", function () {
|
||||
// Verify place holder text for Insert one query
|
||||
let placeholderText =
|
||||
'{\n "name": {{nameInput.text}},\n "dob": {{dobPicker.formattedDate}},\n "gender": {{genderSelect.selectedOptionValue}} \n}';
|
||||
gsheetHelper.EnterBasicQueryValues(
|
||||
"Insert One",
|
||||
dataSourceName,
|
||||
spreadSheetName,
|
||||
false,
|
||||
);
|
||||
agHelper.AssertText(
|
||||
dataSources._gSheetQueryPlaceholder,
|
||||
"text",
|
||||
placeholderText,
|
||||
);
|
||||
|
||||
// Verify place holder text for Insert many query
|
||||
placeholderText =
|
||||
'[{\n "name": {{nameInput.text}},\n "dob": {{dobPicker.formattedDate}},\n "gender": {{genderSelect.selectedOptionValue}} \n}]';
|
||||
|
||||
gsheetHelper.EnterBasicQueryValues(
|
||||
"Insert Many",
|
||||
dataSourceName,
|
||||
spreadSheetName,
|
||||
false,
|
||||
);
|
||||
agHelper.AssertText(
|
||||
dataSources._gSheetQueryPlaceholder,
|
||||
"text",
|
||||
placeholderText,
|
||||
);
|
||||
});
|
||||
|
||||
// This test is commented since we can't use Cypress to go to the Google authorization screen. We will uncomment it whenever we figure out how to do it.
|
||||
// it("7. Bug#26024 App level import of gsheet app", function () {
|
||||
// homePage.NavigateToHome();
|
||||
// homePage.CreateNewWorkspace("AppLevelImport");
|
||||
// homePage.CreateAppInWorkspace("AppLevelImport", "AppLevelImportCheck");
|
||||
// appSettings.OpenAppSettings();
|
||||
// appSettings.GoToImport();
|
||||
// agHelper.ClickButton("Import");
|
||||
// homePage.ImportApp("ImportAppAllAccess.json", "", true);
|
||||
// cy.wait("@importNewApplication").then(() => {
|
||||
// agHelper.Sleep();
|
||||
// agHelper.ClickButton("Save & Authorize");
|
||||
// });
|
||||
// cy.url().should("contain", "accounts.google.com");
|
||||
// homePage.NavigateToHome();
|
||||
// homePage.DeleteApplication("AppLevelImportCheck");
|
||||
// homePage.DeleteWorkspace("AppLevelImport");
|
||||
// });
|
||||
|
||||
after("Delete spreadsheet and app", function () {
|
||||
// Delete spreadsheet and app
|
||||
homePage.NavigateToHome();
|
||||
homePage.SearchAndOpenApp(appName);
|
||||
gsheetHelper.DeleteSpreadsheetQuery(dataSourceName, spreadSheetName);
|
||||
cy.get("@postExecute").then((interception: any) => {
|
||||
expect(interception.response.body.data.body.message).to.deep.equal(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import {
|
|||
dataSources,
|
||||
agHelper,
|
||||
entityExplorer,
|
||||
assertHelper,
|
||||
table,
|
||||
appSettings,
|
||||
} from "../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("GSheet-Functional Tests With Read/Write Access", function () {
|
||||
|
|
@ -26,8 +29,7 @@ describe("GSheet-Functional Tests With Read/Write Access", function () {
|
|||
|
||||
//Adding query to insert a new spreadsheet
|
||||
homePage.NavigateToHome();
|
||||
homePage.CreateAppInWorkspace(workspaceName);
|
||||
homePage.RenameApplication(appName);
|
||||
homePage.CreateAppInWorkspace(workspaceName, appName);
|
||||
gsheetHelper.AddNewSpreadsheetQuery(
|
||||
dataSourceName.readNWrite,
|
||||
spreadSheetName,
|
||||
|
|
@ -170,21 +172,20 @@ describe("GSheet-Functional Tests With Read/Write Access", function () {
|
|||
dataSources.RunQuery();
|
||||
dataSources.RunQueryNVerifyResponseViews(8);
|
||||
dataSources.AssertQueryTableResponse(0, "87bbb472ef9d90dcef140a551665c929");
|
||||
// Currently commenting this until https://github.com/appsmithorg/appsmith/issues/25447 is fixed.
|
||||
// Filter by cell range and verify
|
||||
// dataSources.ValidateNSelectDropdown(
|
||||
// "Filter Format",
|
||||
// "Where Clause",
|
||||
// "Cell range",
|
||||
// );
|
||||
// agHelper.EnterValue("A2:A5", {
|
||||
// propFieldName: "",
|
||||
// directInput: false,
|
||||
// inputFieldName: "Cell range",
|
||||
// });
|
||||
// dataSources.RunQuery();
|
||||
// dataSources.RunQueryNVerifyResponseViews(8);
|
||||
// dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"Filter Format",
|
||||
"Where Clause",
|
||||
"Cell range",
|
||||
);
|
||||
agHelper.EnterValue("A2:A5", {
|
||||
propFieldName: "",
|
||||
directInput: false,
|
||||
inputFieldName: "Cell range",
|
||||
});
|
||||
dataSources.RunQuery();
|
||||
dataSources.RunQueryNVerifyResponseViews(4);
|
||||
dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
|
||||
it("5. Update a record which is not present and verify the error", () => {
|
||||
|
|
@ -297,8 +298,44 @@ describe("GSheet-Functional Tests With Read/Write Access", function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("9. Import an app with read write access sheet", function () {
|
||||
homePage.NavigateToHome();
|
||||
homePage.ImportApp("ImportAppReadWriteAccess.json", workspaceName);
|
||||
assertHelper.WaitForNetworkCall("importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
//Validate table is not empty!
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("ImportAppReadWriteAccess");
|
||||
});
|
||||
|
||||
it("10. App level import of app with read and write access gsheet", function () {
|
||||
homePage.CreateAppInWorkspace(workspaceName, "AppLevelImportReadNWrite");
|
||||
appSettings.OpenAppSettings();
|
||||
appSettings.GoToImport();
|
||||
agHelper.ClickButton("Import");
|
||||
homePage.ImportApp("ImportAppReadWriteAccess.json", "", true);
|
||||
cy.wait("@importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
agHelper.RefreshPage();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("AppLevelImportReadNWrite");
|
||||
});
|
||||
|
||||
after("Delete spreadsheet and app", function () {
|
||||
// Delete spreadsheet and app
|
||||
homePage.SearchAndOpenApp(appName);
|
||||
gsheetHelper.DeleteSpreadsheetQuery(
|
||||
dataSourceName.allAccess,
|
||||
spreadSheetName,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import {
|
|||
dataSources,
|
||||
agHelper,
|
||||
entityExplorer,
|
||||
assertHelper,
|
||||
table,
|
||||
appSettings,
|
||||
} from "../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("GSheet-Functional Tests With Read Access", function () {
|
||||
|
|
@ -26,8 +29,7 @@ describe("GSheet-Functional Tests With Read Access", function () {
|
|||
|
||||
//Adding query to insert a new spreadsheet
|
||||
homePage.NavigateToHome();
|
||||
homePage.CreateAppInWorkspace(workspaceName);
|
||||
homePage.RenameApplication(appName);
|
||||
homePage.CreateAppInWorkspace(workspaceName, appName);
|
||||
gsheetHelper.AddNewSpreadsheetQuery(
|
||||
dataSourceName.allAccess,
|
||||
spreadSheetName,
|
||||
|
|
@ -178,21 +180,20 @@ describe("GSheet-Functional Tests With Read Access", function () {
|
|||
dataSources.RunQuery();
|
||||
dataSources.RunQueryNVerifyResponseViews(8);
|
||||
dataSources.AssertQueryTableResponse(0, "87bbb472ef9d90dcef140a551665c929");
|
||||
// Currently commenting this until https://github.com/appsmithorg/appsmith/issues/25447 is fixed.
|
||||
// Filter by cell range and verify
|
||||
// dataSources.ValidateNSelectDropdown(
|
||||
// "Filter Format",
|
||||
// "Where Clause",
|
||||
// "Cell range",
|
||||
// );
|
||||
// agHelper.EnterValue("A2:A5", {
|
||||
// propFieldName: "",
|
||||
// directInput: false,
|
||||
// inputFieldName: "Cell range",
|
||||
// });
|
||||
// dataSources.RunQuery();
|
||||
// dataSources.RunQueryNVerifyResponseViews(8);
|
||||
// dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"Filter Format",
|
||||
"Where Clause",
|
||||
"Cell range",
|
||||
);
|
||||
agHelper.EnterValue("A2:A5", {
|
||||
propFieldName: "",
|
||||
directInput: false,
|
||||
inputFieldName: "Cell range",
|
||||
});
|
||||
dataSources.RunQuery();
|
||||
dataSources.RunQueryNVerifyResponseViews(4);
|
||||
dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
|
||||
it("5. Convert field to JS and verify", () => {
|
||||
|
|
@ -279,8 +280,47 @@ describe("GSheet-Functional Tests With Read Access", function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("8. Import an app with read only access sheet", function () {
|
||||
homePage.NavigateToHome();
|
||||
homePage.ImportApp("ImportAppReadAccess.json", workspaceName);
|
||||
assertHelper.WaitForNetworkCall("importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
//Validate table is not empty!
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("ImportAppReadAccess");
|
||||
});
|
||||
|
||||
it("9. App level import of app with read only access gsheet", function () {
|
||||
homePage.CreateAppInWorkspace(
|
||||
workspaceName,
|
||||
"AppLevelImportReadOnlyAccess",
|
||||
);
|
||||
appSettings.OpenAppSettings();
|
||||
appSettings.GoToImport();
|
||||
agHelper.ClickButton("Import");
|
||||
homePage.ImportApp("ImportAppReadAccess.json", "", true);
|
||||
cy.wait("@importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
agHelper.RefreshPage();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("AppLevelImportReadOnlyAccess");
|
||||
});
|
||||
|
||||
after("Delete spreadsheet and app", function () {
|
||||
// Delete spreadsheet and app
|
||||
homePage.SearchAndOpenApp(appName);
|
||||
gsheetHelper.DeleteSpreadsheetQuery(
|
||||
dataSourceName.allAccess,
|
||||
spreadSheetName,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import {
|
|||
dataSources,
|
||||
agHelper,
|
||||
entityExplorer,
|
||||
assertHelper,
|
||||
table,
|
||||
appSettings,
|
||||
} from "../../support/Objects/ObjectsCore";
|
||||
|
||||
const workspaceName = "gsheet apps";
|
||||
|
|
@ -20,8 +23,7 @@ describe("GSheet-Functional Tests With Selected Access", function () {
|
|||
|
||||
//Adding app
|
||||
homePage.NavigateToHome();
|
||||
homePage.CreateAppInWorkspace(workspaceName);
|
||||
homePage.RenameApplication(appName);
|
||||
homePage.CreateAppInWorkspace(workspaceName, appName);
|
||||
});
|
||||
|
||||
it("1. Add and verify fetch details query", () => {
|
||||
|
|
@ -161,21 +163,20 @@ describe("GSheet-Functional Tests With Selected Access", function () {
|
|||
dataSources.RunQueryNVerifyResponseViews(8);
|
||||
dataSources.AssertQueryTableResponse(0, "87bbb472ef9d90dcef140a551665c929");
|
||||
|
||||
// Currently commenting this until https://github.com/appsmithorg/appsmith/issues/25447 is fixed.
|
||||
// Filter by cell range and verify
|
||||
// dataSources.ValidateNSelectDropdown(
|
||||
// "Filter Format",
|
||||
// "Where Clause",
|
||||
// "Cell range",
|
||||
// );
|
||||
// agHelper.EnterValue("A2:A5", {
|
||||
// propFieldName: "",
|
||||
// directInput: false,
|
||||
// inputFieldName: "Cell range",
|
||||
// });
|
||||
// dataSources.RunQuery();
|
||||
// dataSources.RunQueryNVerifyResponseViews(8);
|
||||
// dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"Filter Format",
|
||||
"Where Clause",
|
||||
"Cell range",
|
||||
);
|
||||
agHelper.EnterValue("A2:A5", {
|
||||
propFieldName: "",
|
||||
directInput: false,
|
||||
inputFieldName: "Cell range",
|
||||
});
|
||||
dataSources.RunQuery();
|
||||
dataSources.RunQueryNVerifyResponseViews(4);
|
||||
dataSources.AssertQueryTableResponse(0, "eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
|
||||
it("5. Update a record which is not present and verify the error", () => {
|
||||
|
|
@ -291,9 +292,46 @@ describe("GSheet-Functional Tests With Selected Access", function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("8. Import an app with selected access sheet", function () {
|
||||
homePage.NavigateToHome();
|
||||
homePage.ImportApp("ImportAppSelectedAccess.json", workspaceName);
|
||||
assertHelper.WaitForNetworkCall("importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
//Validate table is not empty!
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("ImportAppSelectedAccess");
|
||||
});
|
||||
|
||||
it("9. App level import of app with Selected sheet access gsheet", function () {
|
||||
homePage.CreateAppInWorkspace(
|
||||
workspaceName,
|
||||
"AppLevelImportSelectedAccess",
|
||||
);
|
||||
appSettings.OpenAppSettings();
|
||||
appSettings.GoToImport();
|
||||
agHelper.ClickButton("Import");
|
||||
homePage.ImportApp("ImportAppSelectedAccess.json", "", true);
|
||||
cy.wait("@importNewApplication").then(() => {
|
||||
agHelper.Sleep();
|
||||
agHelper.RefreshPage();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
// Assert table data
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication("AppLevelImportSelectedAccess");
|
||||
});
|
||||
|
||||
after("Delete app", function () {
|
||||
// Delete app
|
||||
homePage.NavigateToHome();
|
||||
homePage.DeleteApplication(appName);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ describe("GSheet-widget binding", function () {
|
|||
|
||||
// Adding suggested widgets and verify
|
||||
dataSources.AddSuggestedWidget(Widgets.Table);
|
||||
agHelper.RefreshPage();
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ describe("GSheet-widget binding for selected sheet access", function () {
|
|||
|
||||
// Adding suggested widgets and verify
|
||||
dataSources.AddSuggestedWidget(Widgets.Table);
|
||||
agHelper.RefreshPage();
|
||||
table.ReadTableRowColumnData(0, 0, "v2").then((cellData) => {
|
||||
expect(cellData).to.eq("eac7efa5dbd3d667f26eb3d3ab504464");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
entityExplorer,
|
||||
locators,
|
||||
assertHelper,
|
||||
draggableWidgets,
|
||||
} from "../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("AForce - Community Issues page validations", function () {
|
||||
|
|
@ -30,12 +31,15 @@ describe("AForce - Community Issues page validations", function () {
|
|||
homePage.ImportApp("CommunityIssuesExport.json");
|
||||
assertHelper
|
||||
.WaitForNetworkCall("importNewApplication")
|
||||
.then((interception: any) => {
|
||||
.then((response: any) => {
|
||||
agHelper.Sleep();
|
||||
const { isPartialImport } = interception.response.body.data;
|
||||
const { isPartialImport } = response.body.data;
|
||||
if (isPartialImport) {
|
||||
// should reconnect modal
|
||||
dataSources.ReconnectSingleDSNAssert("AForceDB", "PostgreSQL");
|
||||
dataSources.ReconnectSingleDSNAssert(
|
||||
String.raw`AForceDB`,
|
||||
"PostgreSQL",
|
||||
);
|
||||
homePage.AssertNCloseImport();
|
||||
} else {
|
||||
homePage.AssertImportToast();
|
||||
|
|
@ -66,7 +70,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
|
||||
it("2. Validate table navigation with Server Side pagination enabled with Default selected row", () => {
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
agHelper.AssertExistingToggleState("serversidepagination", "true");
|
||||
agHelper.AssertExistingToggleState("Server side pagination", "true");
|
||||
|
||||
propPane
|
||||
.ValidatePropertyFieldValue("Default selected row", "0")
|
||||
|
|
@ -139,7 +143,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
//propPane.EnterJSContext("Default search text", "Bug", false);
|
||||
propPane.TypeTextIntoField("Default search text", "Bug");
|
||||
deployMode.DeployApp();
|
||||
table.AssertSearchText("Bug", 2);
|
||||
table.AssertSearchText("Bug");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
deployMode.NavigateBacktoEditor();
|
||||
|
|
@ -149,7 +153,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
propPane.TypeTextIntoField("Default search text", "Quest", true, false);
|
||||
|
||||
deployMode.DeployApp();
|
||||
table.AssertSearchText("Quest", 2);
|
||||
table.AssertSearchText("Quest");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad();
|
||||
|
|
@ -168,42 +172,75 @@ describe("AForce - Community Issues page validations", function () {
|
|||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
});
|
||||
|
||||
it.skip("6. Validate Search table with Client Side Search enabled & disabled", () => {
|
||||
it("6. Validate Search table with Client Side Search enabled & disabled & onSearchTextChanged is set", () => {
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
agHelper.AssertExistingToggleState("clientsidesearch", "true");
|
||||
agHelper.AssertExistingToggleState("Client side search", "true");
|
||||
|
||||
deployMode.DeployApp();
|
||||
table.WaitUntilTableLoad();
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Bug", 2);
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.SearchTable("Best");
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("Quest");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
table.ResetSearch();
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
propPane.TogglePropertyState("Client side search", "Off");
|
||||
|
||||
deployMode.DeployApp();
|
||||
table.WaitUntilTableLoad();
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Bug", 2);
|
||||
table.WaitForTableEmpty("v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.SearchTable("Bug");
|
||||
table.WaitUntilTableLoad(0, 1, "v2"); //Since onSearchTextChanged is set , Search is queried for Search text with Client side search On or Off
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("Quest");
|
||||
table.WaitForTableEmpty("v2");
|
||||
cy.xpath(table._searchBoxCross).click();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
table.ResetSearch();
|
||||
|
||||
//Remove onSearchTextChanged & test
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
propPane.TogglePropertyState("Client side search", "On");
|
||||
propPane.EnterJSContext("onSearchTextChanged", "");
|
||||
propPane.ToggleJSMode("onSearchTextChanged", false);
|
||||
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Xano");
|
||||
table.WaitForTableEmpty("v2"); //Since Xano is present in 2nd page & Client side search is On
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("SSL");
|
||||
table.WaitUntilTableLoad(0, 1, "v2"); //as 1st page has SSL entries
|
||||
table.ResetSearch();
|
||||
|
||||
//if the client side search is off, and there is no text in onSearchTextChanged, we still go ahead with client side search. this is a known limitation deployMode.NavigateBacktoEditor();
|
||||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
propPane.TogglePropertyState("Client side search", "Off");
|
||||
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 1, "v2");
|
||||
|
||||
table.SearchTable("Xano");
|
||||
table.WaitForTableEmpty("v2"); //Since Xano is present in 2nd page & Client side search is Off
|
||||
table.ResetSearch();
|
||||
|
||||
table.SearchTable("SSL");
|
||||
table.WaitUntilTableLoad(0, 1, "v2"); //as 1st page has SSL entries
|
||||
table.ResetSearch();
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
||||
it("7. Validate Filter table", () => {
|
||||
|
|
@ -293,8 +330,8 @@ describe("AForce - Community Issues page validations", function () {
|
|||
agHelper.ClickButton("Confirm");
|
||||
agHelper.AssertElementAbsence(locators._toastMsg); //Making sure internal api doesnt throw error
|
||||
agHelper.Sleep(3000);
|
||||
table.SearchTable("Suggestion", 2);
|
||||
table.WaitUntilTableLoad();
|
||||
table.SearchTable("Suggestion");
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
|
||||
table.ReadTableRowColumnData(0, 0, "v1", 4000).then((cellData) => {
|
||||
expect(cellData).to.be.equal("Suggestion");
|
||||
|
|
@ -311,6 +348,7 @@ describe("AForce - Community Issues page validations", function () {
|
|||
agHelper.Sleep(2000);
|
||||
table.SelectTableRow(0, 1, true, "v2");
|
||||
agHelper.AssertElementVisibility(locators._widgetInDeployed("tabswidget"));
|
||||
agHelper.Sleep(2000);
|
||||
agHelper
|
||||
.GetNClick(locators._inputWidgetv1InDeployed, 0, true, 0)
|
||||
.type("-updating title");
|
||||
|
|
|
|||
|
|
@ -117,26 +117,23 @@ describe("Content Management System App", function () {
|
|||
gitSync.CreateNConnectToGit(repoName);
|
||||
cy.get("@gitRepoName").then((repName) => {
|
||||
repoName = repName;
|
||||
});
|
||||
cy.latestDeployPreview();
|
||||
cy.wait(2000);
|
||||
cy.xpath("//span[text()='Curt50@gmail.com']")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(appPage.mailButton).closest("div").click();
|
||||
cy.xpath(appPage.sendMailText).should("be.visible");
|
||||
cy.xpath(appPage.subjectField).type("Test");
|
||||
cy.get(appPage.contentField)
|
||||
.last()
|
||||
.find("textarea")
|
||||
.type("Task completed", { force: true });
|
||||
cy.get(appPage.confirmButton).closest("div").click({ force: true });
|
||||
cy.get(appPage.closeButton).closest("div").click({ force: true });
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
//clean up
|
||||
gitSync.DeleteTestGithubRepo(repoName);
|
||||
cy.latestDeployPreview();
|
||||
cy.wait(2000);
|
||||
cy.xpath("//span[text()='Curt50@gmail.com']")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(appPage.mailButton).closest("div").click();
|
||||
cy.xpath(appPage.sendMailText).should("be.visible");
|
||||
cy.xpath(appPage.subjectField).type("Test");
|
||||
cy.get(appPage.contentField)
|
||||
.last()
|
||||
.find("textarea")
|
||||
.type("Task completed", { force: true });
|
||||
cy.get(appPage.confirmButton).closest("div").click({ force: true });
|
||||
cy.get(appPage.closeButton).closest("div").click({ force: true });
|
||||
deployMode.NavigateBacktoEditor();
|
||||
gitSync.DeleteTestGithubRepo(repoName);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
jsEditor,
|
||||
apiPage,
|
||||
dataManager,
|
||||
assertHelper,
|
||||
} from "../../../support/Objects/ObjectsCore";
|
||||
const commonlocators = require("../../../locators/commonlocators.json");
|
||||
|
||||
|
|
@ -84,46 +85,38 @@ describe("JSEditor tests", function () {
|
|||
);
|
||||
});
|
||||
// move to page 2 on table widget
|
||||
cy.get(commonlocators.tableNextPage).click();
|
||||
agHelper.GetNClick(commonlocators.tableNextPage);
|
||||
cy.get(".t--table-widget-page-input").within(() => {
|
||||
cy.get("input.bp3-input").should("have.value", "2");
|
||||
});
|
||||
cy.wait(3000);
|
||||
cy.wait(1000);
|
||||
|
||||
// hit audio play button and trigger actions
|
||||
/* cy.openPropertyPane("audiowidget");
|
||||
cy.get(widgetsPage.autoPlay).click({ force: true });
|
||||
cy.wait("@postExecute").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
entityExplorer.SelectEntityByName("Audio1", "Widgets");
|
||||
agHelper.GetElement("audio").then(($audio) => {
|
||||
$audio[0].play();
|
||||
});
|
||||
assertHelper.AssertNetworkStatus("@postExecute");
|
||||
// verify text is visible
|
||||
agHelper.AssertContains(
|
||||
"Step 4: Value is Green and will default to GREEN",
|
||||
"be.visible",
|
||||
".t--draggable-textwidget span",
|
||||
);
|
||||
cy.wait(1000)
|
||||
// verify text is visible
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.eq(2)
|
||||
.invoke("text")
|
||||
.then((text) => {
|
||||
expect(text).to.equal("Step 4: Value is Green and will default to Green");
|
||||
});
|
||||
cy.get(commonlocators.tableNextPage).click()
|
||||
cy.get('.t--table-widget-page-input').within(()=>{
|
||||
cy.get('input.bp3-input').should('have.value', '1')
|
||||
})
|
||||
cy.get(homePageLocators.toastMessage).should(
|
||||
"contain",
|
||||
"Success running API query",
|
||||
"GREEN",
|
||||
); */
|
||||
|
||||
agHelper.GetNClick(commonlocators.tableNextPage);
|
||||
agHelper.ValidateToastMessage("Success running API query");
|
||||
agHelper.ValidateToastMessage("GREEN");
|
||||
agHelper.GetElement(".t--table-widget-page-input").within(() => {
|
||||
agHelper.ValidateFieldInputValue("input.bp3-input", "2");
|
||||
});
|
||||
});
|
||||
|
||||
//Skipping reason? to add
|
||||
it.skip("2. Testing dynamic widgets display using consecutive storeValue calls", () => {
|
||||
it("2. Testing dynamic widgets display using consecutive storeValue calls", () => {
|
||||
entityExplorer.SelectEntityByName("JSObject1", "Queries/JS");
|
||||
jsEditor.SelectFunctionDropdown("clearStore");
|
||||
jsEditor.RunJSObj();
|
||||
cy.wait("@postExecute")
|
||||
.its("response.body.responseMeta.status")
|
||||
.should("eq", 200);
|
||||
entityExplorer.SelectEntityByName("Page1", "Pages");
|
||||
cy.xpath("//span[text()='Clear store']").click({ force: true });
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.eq(5)
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
import {
|
||||
agHelper,
|
||||
draggableWidgets,
|
||||
entityExplorer,
|
||||
locators,
|
||||
propPane,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("JS to non-JS mode in Action Selector", () => {
|
||||
before(() => {
|
||||
agHelper.AddDsl("promisesBtnDsl", locators._buttonByText("Submit"));
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON);
|
||||
});
|
||||
|
||||
it("1. shows fields for navigate to from js to non-js mode", () => {
|
||||
entityExplorer.SelectEntityByName("Page1", "Pages");
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
|
||||
propPane.EnterJSContext("onClick", "{{navigateTo()}}", true, false);
|
||||
propPane.ToggleJSMode("onClick", false);
|
||||
|
||||
|
|
@ -508,7 +505,7 @@ describe("JS to non-JS mode in Action Selector", () => {
|
|||
propPane.ToggleJSMode("onClick");
|
||||
propPane.ValidatePropertyFieldValue(
|
||||
"onClick",
|
||||
`{{copyToClipboard('line1\\nline2\\nline3a');}}`,
|
||||
`{{copyToClipboard('aline1\\nline2\\nline3');}}`,
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -251,16 +251,16 @@ describe("JS to non-JS mode in Action Selector", () => {
|
|||
0,
|
||||
);
|
||||
agHelper.GetNAssertElementText(
|
||||
propPane._actionPopupTextLabel,
|
||||
"Target iframe",
|
||||
propPane._windowTargetDropdown,
|
||||
"Window",
|
||||
"have.text",
|
||||
1,
|
||||
0,
|
||||
);
|
||||
agHelper.GetNAssertElementText(
|
||||
propPane._actionPopupTextLabel,
|
||||
"Allowed origins",
|
||||
"have.text",
|
||||
2,
|
||||
1,
|
||||
);
|
||||
|
||||
propPane.EnterJSContext(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ describe("Post window message", () => {
|
|||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.SelectPlatformFunction("onClick", "Post message");
|
||||
agHelper.EnterActionValue("Message", "After postMessage");
|
||||
agHelper.EnterActionValue("Target iframe", "Iframe1");
|
||||
agHelper.GetNClick(propPane._windowTargetDropdown);
|
||||
agHelper.GetNClick(locators._dropDownValue("Iframe1"), 0, true);
|
||||
|
||||
entityExplorer.SelectEntityByName("Iframe1", "Widgets");
|
||||
propPane.UpdatePropertyFieldValue(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
jsEditor,
|
||||
propPane,
|
||||
deployMode,
|
||||
debuggerHelper,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("storeValue Action test", () => {
|
||||
|
|
@ -198,4 +199,40 @@ describe("storeValue Action test", () => {
|
|||
agHelper.ValidateToastMessage(JSON.stringify(TEST_OBJECT), 0);
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
||||
it("4. Bug 24882. StoreValue, removeValue and clearStore should emit platform generated logs", function () {
|
||||
const jsObjectBody = `export default {
|
||||
storeFns: () => {
|
||||
storeValue("xyz", 123);
|
||||
removeValue("xyz");
|
||||
clearStore();
|
||||
}
|
||||
}`;
|
||||
|
||||
jsEditor.CreateJSObject(jsObjectBody, {
|
||||
paste: true,
|
||||
completeReplace: true,
|
||||
toRun: true,
|
||||
shouldCreateNewJSObj: true,
|
||||
});
|
||||
|
||||
entityExplorer.DragDropWidgetNVerify("buttonwidget", 400, 400);
|
||||
entityExplorer.SelectEntityByName("Button3", "Widgets");
|
||||
propPane.UpdatePropertyFieldValue("Label", "Test store logs");
|
||||
cy.get("@jsObjName").then((jsObj: any) => {
|
||||
propPane.SelectJSFunctionToExecute(
|
||||
"onClick",
|
||||
jsObj as string,
|
||||
"storeFns",
|
||||
);
|
||||
});
|
||||
agHelper.ClickButton("Test store logs");
|
||||
|
||||
debuggerHelper.ClickDebuggerIcon();
|
||||
debuggerHelper.ClickLogsTab();
|
||||
debuggerHelper.changeLogsGroup("System logs");
|
||||
debuggerHelper.DoesConsoleLogExist("storeValue('xyz', '123', true)");
|
||||
debuggerHelper.DoesConsoleLogExist("removeValue('xyz')");
|
||||
debuggerHelper.DoesConsoleLogExist("clearStore()");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ describe("Admin settings page", function () {
|
|||
cy.visit("/settings/general", { timeout: 60000 });
|
||||
// non super users are redirected to home page
|
||||
cy.url().should("contain", "/applications");
|
||||
cy.LogOut();
|
||||
cy.LogOut(false);
|
||||
});
|
||||
|
||||
it("3. Should test that settings page is redirected to default tab", () => {
|
||||
|
|
@ -62,8 +62,8 @@ describe("Admin settings page", function () {
|
|||
cy.url().should("contain", "/settings/authentication");
|
||||
cy.get(adminsSettings.emailTab).click();
|
||||
cy.url().should("contain", "/settings/email");
|
||||
cy.get(adminsSettings.googleMapsTab).click();
|
||||
cy.url().should("contain", "/settings/google-maps");
|
||||
cy.get(adminsSettings.developerSettingsTab).click();
|
||||
cy.url().should("contain", "/settings/developer-settings");
|
||||
cy.get(adminsSettings.versionTab).click();
|
||||
cy.url().should("contain", "/settings/version");
|
||||
},
|
||||
|
|
@ -71,7 +71,7 @@ describe("Admin settings page", function () {
|
|||
|
||||
it(
|
||||
"airgap",
|
||||
"4. Should test that settings page tab redirects and google maps doesn't exist - airgap",
|
||||
"4. Should test that settings page tab redirects and developer settings doesn't exist - airgap",
|
||||
() => {
|
||||
cy.visit("/applications", { timeout: 60000 });
|
||||
if (!Cypress.env("AIRGAPPED")) {
|
||||
|
|
@ -90,7 +90,7 @@ describe("Admin settings page", function () {
|
|||
cy.url().should("contain", "/settings/authentication");
|
||||
cy.get(adminsSettings.emailTab).click();
|
||||
cy.url().should("contain", "/settings/email");
|
||||
cy.get(adminsSettings.googleMapsTab).should("not.exist");
|
||||
cy.get(adminsSettings.developerSettingsTab).should("not.exist");
|
||||
cy.get(adminsSettings.versionTab).click();
|
||||
cy.url().should("contain", "/settings/version");
|
||||
},
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ import {
|
|||
adminSettings,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import { CURRENT_REPO, REPO } from "../../../../fixtures/REPO";
|
||||
import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags";
|
||||
|
||||
describe("Admin Settings Page - General page validations", () => {
|
||||
it("1. TC# 2439 Verify 'Page title' changes upon changing Instance name", () => {
|
||||
featureFlagIntercept({ license_branding_enabled: true });
|
||||
adminSettings.NavigateToAdminSettings();
|
||||
agHelper.ClearNType(adminSettings._instanceName, "Testing Instance name");
|
||||
agHelper.ClickButton("Save");
|
||||
|
|
@ -15,4 +17,12 @@ describe("Admin Settings Page - General page validations", () => {
|
|||
else if (CURRENT_REPO === REPO.EE)
|
||||
cy.title().should("eq", "Testing Instance name"); //verifying that Instance name is not changed in EE
|
||||
});
|
||||
it("2. TC# 2439 Verify 'Page title' does not change upon changing Instance name in free plan", () => {
|
||||
featureFlagIntercept({ license_branding_enabled: false });
|
||||
adminSettings.NavigateToAdminSettings();
|
||||
agHelper.ClearNType(adminSettings._instanceName, "Testing Instance name 2");
|
||||
agHelper.ClickButton("Save");
|
||||
agHelper.ValidateToastMessage("Successfully saved");
|
||||
cy.title().should("eq", "Appsmith");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ describe("General checks for app navigation", function () {
|
|||
homePage.ImportApp("appNavigationTestingApp.json");
|
||||
assertHelper
|
||||
.WaitForNetworkCall("@importNewApplication")
|
||||
.then((interception) => {
|
||||
.then((response) => {
|
||||
agHelper.Sleep();
|
||||
const { isPartialImport } = interception.response.body.data;
|
||||
const { isPartialImport } = response.body.data;
|
||||
if (isPartialImport) {
|
||||
homePage.AssertNCloseImport();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ describe("Test Sidebar navigation style", function () {
|
|||
homePage.ImportApp("appNavigationTestingAppWithLongPageNamesAndTitle.json");
|
||||
assertHelper
|
||||
.WaitForNetworkCall("@importNewApplication")
|
||||
.then((interception) => {
|
||||
.then((response) => {
|
||||
agHelper.Sleep();
|
||||
const { isPartialImport } = interception.response.body.data;
|
||||
const { isPartialImport } = response.body.data;
|
||||
if (isPartialImport) {
|
||||
homePage.AssertNCloseImport();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -15,11 +15,9 @@ describe("Test Top + Inline navigation style", function () {
|
|||
|
||||
assertHelper
|
||||
.WaitForNetworkCall("@importNewApplication")
|
||||
.then((interception) => {
|
||||
.then((response) => {
|
||||
agHelper.Sleep();
|
||||
|
||||
const { isPartialImport } = interception.response.body.data;
|
||||
|
||||
const { isPartialImport } = response.body.data;
|
||||
if (isPartialImport) {
|
||||
homePage.AssertNCloseImport();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ describe("Test Top + Stacked navigation style", function () {
|
|||
homePage.ImportApp("appNavigationTestingAppWithLongPageNamesAndTitle.json");
|
||||
assertHelper
|
||||
.WaitForNetworkCall("importNewApplication")
|
||||
.then((interception: any) => {
|
||||
.then((response: any) => {
|
||||
agHelper.Sleep();
|
||||
const { isPartialImport } = interception.response.body.data;
|
||||
const { isPartialImport } = response.body.data;
|
||||
if (isPartialImport) {
|
||||
homePage.AssertNCloseImport();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,150 @@
|
|||
import {
|
||||
agHelper,
|
||||
locators,
|
||||
entityExplorer,
|
||||
jsEditor,
|
||||
propPane,
|
||||
apiPage,
|
||||
dataManager,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Assistive Binding", function () {
|
||||
before(() => {
|
||||
// Button1
|
||||
entityExplorer.DragDropWidgetNVerify("buttonwidget", 200, 200);
|
||||
|
||||
// Create JSObject1
|
||||
jsEditor.CreateJSObject(
|
||||
`export default {
|
||||
myFun1: ()=>{
|
||||
f;
|
||||
return "yes"
|
||||
}
|
||||
}`,
|
||||
{
|
||||
paste: true,
|
||||
completeReplace: true,
|
||||
toRun: false,
|
||||
shouldCreateNewJSObj: true,
|
||||
prettify: false,
|
||||
},
|
||||
);
|
||||
|
||||
// Create JSObject2
|
||||
jsEditor.CreateJSObject(
|
||||
`export default {
|
||||
myFun1: ()=>{
|
||||
f;
|
||||
return "yes"
|
||||
}
|
||||
}`,
|
||||
{
|
||||
paste: true,
|
||||
completeReplace: true,
|
||||
toRun: false,
|
||||
shouldCreateNewJSObj: true,
|
||||
prettify: false,
|
||||
},
|
||||
);
|
||||
|
||||
// Create Api1
|
||||
apiPage.CreateAndFillApi(
|
||||
dataManager.dsValues[dataManager.defaultEnviorment].echoApiUrl,
|
||||
);
|
||||
// Create Api2
|
||||
apiPage.CreateAndFillApi(
|
||||
dataManager.dsValues[dataManager.defaultEnviorment].echoApiUrl,
|
||||
);
|
||||
});
|
||||
it("1. Shows hints without curly braces when user types in data fields", () => {
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "JS");
|
||||
// Assert that no hint shows up when length of text is less than 3
|
||||
agHelper.AssertElementAbsence(locators._hints);
|
||||
propPane.TypeTextIntoField("Label", "JSo");
|
||||
// Assert that hints show up when length of text is equal to or greater than 3
|
||||
agHelper.AssertElementExist(locators._hints);
|
||||
propPane.TypeTextIntoField("Label", "unknownVar");
|
||||
// Assert that no hint shows up text doesn't match any entity name within the app
|
||||
agHelper.AssertElementAbsence(locators._hints);
|
||||
propPane.TypeTextIntoField("Label", "API");
|
||||
// Assert that hints show up without considering capitalization
|
||||
agHelper.AssertElementExist(locators._hints);
|
||||
propPane.TypeTextIntoField("Label", "{");
|
||||
// Assert that hints show up when 1 curly brace is entered
|
||||
agHelper.AssertElementExist(locators._hints);
|
||||
});
|
||||
it("2. Selects correct value when hint is selected", () => {
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "JSo");
|
||||
agHelper.GetNClickByContains(locators._hints, "JSObject1.myFun1");
|
||||
// After selecting "JSObject1.myFun1", expect "{{JSObject1.myFun1.data}}" in binding
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{JSObject1.myFun1.data}}");
|
||||
propPane.TypeTextIntoField("Label", "Api");
|
||||
agHelper.GetNClickByContains(locators._hints, "Api1");
|
||||
// After selecting "Api1", expect "{{Api1.data}}" in binding
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{Api1.data}}");
|
||||
});
|
||||
it("3. Shows hints after every white space", () => {
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "JSo JSo");
|
||||
// Assert that hints show up when length of text after any previous blank space is equal to or greater than 3
|
||||
agHelper.AssertElementExist(locators._hints);
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "JSo tab\tJSo");
|
||||
// Assert that hints show up when length of text after any previous tab is equal to or greater than 3
|
||||
agHelper.AssertElementExist(locators._hints);
|
||||
propPane.TypeTextIntoField("Label", "JSo \nJSo");
|
||||
// Assert that hints show up when length of text after any previous new line is equal to or greater than 3
|
||||
agHelper.AssertElementExist(locators._hints);
|
||||
});
|
||||
|
||||
it("4. Selects correct value and inserts in right place when hint is selected after whitespace ", () => {
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "JSo JSo");
|
||||
agHelper.GetNClickByContains(locators._hints, "JSObject1.myFun1");
|
||||
// After selecting "JSObject1.myFun1", expect "JSo {{JSObject1.myFun1.data}}" in binding
|
||||
propPane.ValidatePropertyFieldValue(
|
||||
"Label",
|
||||
"JSo {{JSObject1.myFun1.data}}",
|
||||
);
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "JSo tab\tJSo");
|
||||
agHelper.GetNClickByContains(locators._hints, "JSObject1.myFun1");
|
||||
// After selecting "JSObject1.myFun1", expect "JSo tab {{JSObject1.myFun1.data}}" in binding
|
||||
propPane.ValidatePropertyFieldValue(
|
||||
"Label",
|
||||
"JSo tab {{JSObject1.myFun1.data}}",
|
||||
);
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", `JSo \nJSo`);
|
||||
agHelper.GetNClickByContains(locators._hints, "JSObject1.myFun1");
|
||||
// After selecting "JSObject1.myFun1", expect `JSo \n{{JSObject1.myFun1.data}}` in binding
|
||||
propPane.ValidatePropertyFieldValue(
|
||||
"Label",
|
||||
`JSo {{JSObject1.myFun1.data}}`,
|
||||
);
|
||||
});
|
||||
|
||||
it("5. Partial binding {} syntax is replaced with correct values ", () => {
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "{");
|
||||
agHelper.GetNClickByContains(locators._hints, "JSObject1.myFun1");
|
||||
// After selecting "JSObject1.myFun1", expect "{{JSObject1.myFun1.data}}" in binding
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{JSObject1.myFun1.data}}");
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "{");
|
||||
agHelper.GetNClickByContains(locators._hints, "Add a binding");
|
||||
// After selecting "Add a binding", expect "{{}}" in binding
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{}}");
|
||||
});
|
||||
|
||||
it("6. Works correctly when user toggles JS", () => {
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.ToggleJSMode("onClick");
|
||||
propPane.ValidatePropertyFieldValue("onClick", "{{}}");
|
||||
propPane.TypeTextIntoField("onClick", "hello", false);
|
||||
// This asserts that cursor was originally between the curly braces after the user switched to js mode
|
||||
propPane.ValidatePropertyFieldValue("onClick", "{{hello}}");
|
||||
});
|
||||
});
|
||||
|
|
@ -40,22 +40,22 @@ describe("Autocomplete tests for setters", () => {
|
|||
|
||||
agHelper.GetElementsNAssertTextPresence(
|
||||
locators._hints,
|
||||
"Button1.setColor()",
|
||||
"Button1.setColor",
|
||||
);
|
||||
agHelper.GetElementsNAssertTextPresence(
|
||||
locators._hints,
|
||||
"Button1.setDisabled()",
|
||||
"Button1.setDisabled",
|
||||
);
|
||||
agHelper.GetElementsNAssertTextPresence(
|
||||
locators._hints,
|
||||
"Button1.setVisibility()",
|
||||
"Button1.setVisibility",
|
||||
);
|
||||
|
||||
agHelper.RemoveCharsNType(locators._codeMirrorTextArea, 7, "Input1.set");
|
||||
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setValue()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setVisibility()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setValue");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setVisibility");
|
||||
|
||||
agHelper.RemoveCharsNType(
|
||||
locators._codeMirrorTextArea,
|
||||
|
|
@ -63,14 +63,14 @@ describe("Autocomplete tests for setters", () => {
|
|||
"Checkbox1.set",
|
||||
);
|
||||
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setValue()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setVisibility()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setValue");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setVisibility");
|
||||
|
||||
agHelper.RemoveCharsNType(locators._codeMirrorTextArea, 13, "Switch1.set");
|
||||
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setRequired()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setRequired");
|
||||
agHelper.Sleep(); //a bit for time for CI
|
||||
});
|
||||
|
||||
|
|
@ -78,6 +78,6 @@ describe("Autocomplete tests for setters", () => {
|
|||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.INPUT_V2, 500, 500);
|
||||
entityExplorer.SelectEntityByName("Button1");
|
||||
propPane.EnterJSContext("onClick", "{{Input1.set", true, false);
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled()");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "setDisabled");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -130,22 +130,22 @@ describe("Autocomplete tests", () => {
|
|||
// eval function verification
|
||||
{
|
||||
type: "eval",
|
||||
expected: "eval()",
|
||||
expected: "eval",
|
||||
haveOrNotHave: false,
|
||||
},
|
||||
{
|
||||
type: "Blob",
|
||||
expected: "Blob()",
|
||||
expected: "Blob",
|
||||
haveOrNotHave: true,
|
||||
},
|
||||
{
|
||||
type: "FormData",
|
||||
expected: "FormData()",
|
||||
expected: "FormData",
|
||||
haveOrNotHave: true,
|
||||
},
|
||||
{
|
||||
type: "FileReader",
|
||||
expected: "FileReader()",
|
||||
expected: "FileReader",
|
||||
haveOrNotHave: true,
|
||||
},
|
||||
];
|
||||
|
|
@ -167,7 +167,7 @@ describe("Autocomplete tests", () => {
|
|||
agHelper.GetNClick(jsEditor._lineinJsEditor(5));
|
||||
agHelper.TypeText(locators._codeMirrorTextArea, "this.");
|
||||
|
||||
["myFun2()", "myVar1", "myVar2"].forEach((element, index) => {
|
||||
["myFun2", "myVar1", "myVar2"].forEach((element, index) => {
|
||||
agHelper.AssertContains(element);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ describe("Autocomplete tests", () => {
|
|||
0,
|
||||
);
|
||||
|
||||
agHelper.GetNAssertElementText(locators._hints, "myFun1()", "have.text", 4);
|
||||
agHelper.GetNAssertElementText(locators._hints, "myFun1", "have.text", 4);
|
||||
|
||||
// Same check in JSObject1
|
||||
entityExplorer.SelectEntityByName("JSObject1", "Queries/JS");
|
||||
|
|
@ -65,7 +65,7 @@ describe("Autocomplete tests", () => {
|
|||
0,
|
||||
);
|
||||
|
||||
agHelper.GetNAssertElementText(locators._hints, "myFun1()", "have.text", 4);
|
||||
agHelper.GetNAssertElementText(locators._hints, "myFun1", "have.text", 4);
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "JSObject1",
|
||||
action: "Delete",
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ describe("Property Pane Suggestions", () => {
|
|||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
propPane.TypeTextIntoField("Label", "/");
|
||||
agHelper.Sleep(500);
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "New binding");
|
||||
agHelper.GetNClickByContains(locators._hints, "New binding");
|
||||
agHelper.GetElementsNAssertTextPresence(locators._hints, "Add a binding");
|
||||
agHelper.GetNClickByContains(locators._hints, "Add a binding");
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{}}");
|
||||
|
||||
//typing {{}}
|
||||
|
|
@ -46,6 +46,6 @@ describe("Property Pane Suggestions", () => {
|
|||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
cy.get("body").tab();
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{appsmith}}");
|
||||
propPane.ValidatePropertyFieldValue("Label", "{{JSObject1}}");
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ describe("Dynamic input autocomplete", () => {
|
|||
cy.wait(1000);
|
||||
|
||||
cy.evaluateErrorMessage(
|
||||
"Found a reference to {{actionName}} during evaluation. Data fields cannot execute framework actions. Please remove any direct/indirect references to {{actionName}} and try again.".replaceAll(
|
||||
"Please remove any direct/indirect references to {{actionName}} and try again. Data fields cannot execute framework actions.".replaceAll(
|
||||
"{{actionName}}",
|
||||
"storeValue()",
|
||||
),
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ describe("Test Create Api and Bind to List widget", function () {
|
|||
|
||||
it("3. Test_Validate the list widget ", function () {
|
||||
deployMode.NavigateBacktoEditor();
|
||||
cy.wait("@postExecute");
|
||||
cy.wait("@postExecute").then((interception) => {
|
||||
valueToTest = JSON.stringify(
|
||||
interception.response.body.data.body[0].name,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ describe("Binding the button Widgets and validating NavigateTo Page functionalit
|
|||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.BUTTON));
|
||||
cy.wait(2000);
|
||||
agHelper.ClickButton("Submit");
|
||||
cy.wait(2000); //for page to load
|
||||
cy.wait(4000); //for page to load
|
||||
agHelper.AssertElementAbsence(
|
||||
locators._widgetInDeployed(draggableWidgets.BUTTON),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,54 +15,18 @@ describe(
|
|||
.GetText(_.locators._widgetInCanvas("textwidget") + " span")
|
||||
.should("be.empty");
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v2");
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v2",
|
||||
);
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper
|
||||
.GetText(_.locators._widgetInCanvas("textwidget") + " span")
|
||||
.should("be.empty");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v3");
|
||||
});
|
||||
|
||||
//This test to be enabled once the product bug is fixed
|
||||
it.skip("Validate the Button binding with Text Widget with Recaptcha Token with invalid key before using valid key", function () {
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.testCodeMirrorLast(testdata.invalidKey);
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).to.be.empty;
|
||||
});
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
|
||||
cy.get(".t--property-control-googlerecaptchaversion .bp3-popover-target")
|
||||
.last()
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(".t--dropdown-option:contains('reCAPTCHA v2')").click({
|
||||
force: true,
|
||||
});
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(".t--toast-action span").should("have.text", testdata.errorMsg);
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.wait(3000);
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).to.be.empty;
|
||||
});
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v3",
|
||||
);
|
||||
});
|
||||
|
||||
it("2. Validate the Button binding with Text Widget with Recaptcha Token with v2Key & upward compatibilty doesnt work", function () {
|
||||
|
|
@ -77,13 +41,19 @@ describe(
|
|||
.GetText(_.locators._widgetInCanvas("textwidget") + " span")
|
||||
.should("be.empty");
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v2");
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v2",
|
||||
);
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.Sleep();
|
||||
_.agHelper
|
||||
.GetText(_.locators._widgetInCanvas("textwidget") + " span")
|
||||
.should("not.be.empty");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v3");
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v3",
|
||||
);
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.Sleep();
|
||||
});
|
||||
|
|
@ -94,20 +64,24 @@ describe(
|
|||
"Google reCAPTCHA key",
|
||||
testdata.v3Key,
|
||||
);
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v3");
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v3",
|
||||
);
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.Sleep();
|
||||
cy.get("body").then(($ele) => {
|
||||
if (
|
||||
$ele.find(
|
||||
_.locators._specificToast(
|
||||
"Google Re-Captcha token generation failed!",
|
||||
"Google reCAPTCHA token generation failed!",
|
||||
),
|
||||
).length ||
|
||||
$ele
|
||||
.find(_.locators._widgetInCanvas("textwidget") + " span")
|
||||
.text() == ""
|
||||
) {
|
||||
_.agHelper.WaitUntilAllToastsDisappear();
|
||||
_.agHelper.ClickButton("Submit");
|
||||
}
|
||||
});
|
||||
|
|
@ -115,50 +89,30 @@ describe(
|
|||
.GetText(_.locators._widgetInCanvas("textwidget") + " span")
|
||||
.should("not.be.empty");
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.agHelper.SelectDropdownList("Google reCAPTCHA version", "reCAPTCHA v2");
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v2",
|
||||
);
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.AssertContains("Google Re-Captcha token generation failed!"); //toast doesnt come when run in CI!
|
||||
_.agHelper.AssertContains("Google reCAPTCHA token generation failed!");
|
||||
});
|
||||
|
||||
//This test to be enabled once the product bug is fixed
|
||||
it.skip("Validate the Button binding with Text Widget with Recaptcha Token with invalid key", function () {
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.testCodeMirrorLast(testdata.invalidKey);
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).not.to.be.empty;
|
||||
});
|
||||
it("4. Validate the Button binding with Text Widget with Recaptcha Token with invalid key (after using valid key)", function () {
|
||||
_.propPane.DeleteWidgetFromPropertyPane("Text1");
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
|
||||
cy.get(".t--property-control-googlerecaptchaversion .bp3-popover-target")
|
||||
.last()
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
cy.get(".t--dropdown-option:contains('reCAPTCHA v2')").click({
|
||||
force: true,
|
||||
});
|
||||
cy.get("button")
|
||||
.contains("Submit")
|
||||
.should("be.visible")
|
||||
.click({ force: true });
|
||||
_.entityExplorer.SelectEntityByName("Text1");
|
||||
|
||||
cy.wait(3000);
|
||||
cy.get(".t--draggable-textwidget span")
|
||||
.last()
|
||||
.invoke("text")
|
||||
.then((x) => {
|
||||
cy.log(x);
|
||||
expect(x).not.to.be.empty;
|
||||
});
|
||||
_.propPane.UpdatePropertyFieldValue(
|
||||
"Google reCAPTCHA key",
|
||||
testdata.invalidKey,
|
||||
);
|
||||
_.agHelper.ClickButton("Submit"); //for version 3
|
||||
_.agHelper.WaitUntilToastDisappear(testdata.errorMsg);
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
_.propPane.SelectPropertiesDropDown(
|
||||
"Google reCAPTCHA version",
|
||||
"reCAPTCHA v2",
|
||||
);
|
||||
_.agHelper.ClickButton("Submit");
|
||||
_.agHelper.WaitUntilToastDisappear(testdata.errorMsg);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -41,11 +41,7 @@ describe("Bind a button and Api usecase", function () {
|
|||
it("2. Button-Name updation & API datasource binding with button name validation", function () {
|
||||
_.entityExplorer.SelectEntityByName("Button1");
|
||||
//changing the Button Name
|
||||
cy.widgetText(
|
||||
testdata.buttonName,
|
||||
widgetsPage.buttonWidget,
|
||||
widgetsPage.widgetNameSpan,
|
||||
);
|
||||
_.propPane.RenameWidget("Button1", testdata.buttonName);
|
||||
|
||||
//API datasource binding with button name validation
|
||||
_.entityExplorer.SelectEntityByName("Api1", "Queries/JS");
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const queryLocators = require("../../../../locators/QueryEditor.json");
|
|||
const queryEditor = require("../../../../locators/QueryEditor.json");
|
||||
import homePage from "../../../../locators/HomePage";
|
||||
import * as _ from "../../../../support/Objects/ObjectsCore";
|
||||
import { Widgets } from "../../../../support/Pages/DataSources";
|
||||
|
||||
import * as _ from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ describe("Addwidget from Query and bind with other widgets", function () {
|
|||
fixture: "addWidgetTable-mock",
|
||||
});
|
||||
cy.onlyQueryRun();
|
||||
cy.get(queryEditor.suggestedTableWidget).click();
|
||||
_.dataSources.AddSuggestedWidget(Widgets.Table);
|
||||
_.jsEditor.CreateJSObject("return Query1.data;");
|
||||
cy.CheckAndUnfoldEntityItem("Widgets");
|
||||
cy.get(".t--entity-name").contains("Table1").click({ force: true });
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ Object.entries(widgetsToTest).forEach(([widgetSelector, testConfig]) => {
|
|||
cy.updateCodeInput(PROPERTY_SELECTOR.text, testConfig.textBindingValue);
|
||||
cy.closePropertyPane();
|
||||
|
||||
cy.get(".rc-select-selector").click({ force: true });
|
||||
agHelper.GetNClick(".rc-select-selector", 0, true);
|
||||
cy.wait(1000);
|
||||
cy.get('.rc-select-item-option:contains("Blue")').click({ force: true });
|
||||
cy.wait(1000);
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ showAlert("Wonderful! all apis executed", "success")).catch(() => showAlert("Ple
|
|||
deployMode.DeployApp();
|
||||
agHelper.ClickButton("Submit");
|
||||
//agHelper.AssertElementLength(locator._toastMsg, 3); //Below incases of some api's failure
|
||||
agHelper.WaitUntilEleAppear(locator._toastMsg);
|
||||
agHelper
|
||||
.GetElementLength(locator._toastMsg)
|
||||
.then(($len) => expect($len).to.be.at.least(2));
|
||||
|
|
|
|||
|
|
@ -43,34 +43,34 @@ describe("Validate basic binding of Input widget to Input widget", () => {
|
|||
});
|
||||
});
|
||||
|
||||
//Till bug fixed
|
||||
it.skip("2. Validation of default displayed in Select widget based on row selected + Bug 12531", function () {
|
||||
table.SelectTableRow(1);
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("#2");
|
||||
});
|
||||
// //Till bug fixed
|
||||
// it.skip("2. Validation of default displayed in Select widget based on row selected + Bug 12531", function () {
|
||||
// table.SelectTableRow(1);
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("#2");
|
||||
// });
|
||||
|
||||
table.SelectTableRow(0);
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("#1");
|
||||
});
|
||||
// table.SelectTableRow(0);
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("#1");
|
||||
// });
|
||||
|
||||
table.SelectTableRow(2);
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("Select option");
|
||||
});
|
||||
// table.SelectTableRow(2);
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("Select option");
|
||||
// });
|
||||
|
||||
//Change select value now - failing here!
|
||||
agHelper.SelectDropDown("#1");
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("#1");
|
||||
});
|
||||
// //Change select value now - failing here!
|
||||
// agHelper.SelectDropDown("#1");
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("#1");
|
||||
// });
|
||||
|
||||
table.SelectTableRow(2, 0, false); //Deselecting here!
|
||||
agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
expect($selectedValue).to.eq("Select option");
|
||||
});
|
||||
});
|
||||
// table.SelectTableRow(2, 0, false); //Deselecting here!
|
||||
// agHelper.ReadSelectedDropDownValue().then(($selectedValue) => {
|
||||
// expect($selectedValue).to.eq("Select option");
|
||||
// });
|
||||
// });
|
||||
|
||||
it("3. Verify Selecting the already selected row deselects it", () => {
|
||||
table.SelectTableRow(0); //select here
|
||||
|
|
|
|||
|
|
@ -136,24 +136,15 @@ describe("Test Create Api and Bind to Table widget", function () {
|
|||
cy.executeDbQuery("Api2", "onPageChange");
|
||||
});
|
||||
|
||||
it.skip("5. Table-Text, Validate Server Side Pagination of Paginate with response URL", function () {
|
||||
it("5. Table-Text, Validate Server Side Pagination of Paginate with response URL", function () {
|
||||
/**Validate Response data with Table data in Text Widget */
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
|
||||
cy.ValidatePaginateResponseUrlData(
|
||||
apiLocators.apiPaginationPrevTest,
|
||||
false,
|
||||
);
|
||||
cy.ValidatePaginateResponseUrlData(apiLocators.apiPaginationPrevTest);
|
||||
cy.get("@postExecute.all");
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE_V1));
|
||||
table.WaitUntilTableLoad(0, 0);
|
||||
agHelper.Sleep(3000);
|
||||
cy.wait("@postExecute").then((interception) => {
|
||||
let valueToTest = JSON.stringify(
|
||||
interception.response.body.data.body[0].name,
|
||||
);
|
||||
cy.ValidatePaginationInputData(valueToTest);
|
||||
});
|
||||
deployMode.NavigateBacktoEditor();
|
||||
cy.wait(3000);
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ describe("Test Create Api and Bind to Table widget", function () {
|
|||
cy.executeDbQuery("Api2", "onPageChange");
|
||||
});
|
||||
|
||||
it.skip("5. Table-Text, Validate Server Side Pagination of Paginate with Response URL", function () {
|
||||
it("5. Table-Text, Validate Server Side Pagination of Paginate with Response URL", function () {
|
||||
/**Validate Response data with Table data in Text Widget */
|
||||
cy.get("body").then(($ele) => {
|
||||
if ($ele.find(locators._backToEditor).length) {
|
||||
|
|
@ -144,20 +144,11 @@ describe("Test Create Api and Bind to Table widget", function () {
|
|||
});
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
|
||||
cy.ValidatePaginateResponseUrlDataV2(
|
||||
apiPageLocators.apiPaginationPrevTest,
|
||||
false,
|
||||
);
|
||||
cy.ValidatePaginateResponseUrlDataV2(apiPageLocators.apiPaginationPrevTest);
|
||||
cy.get("@postExecute.all");
|
||||
deployMode.DeployApp(locators._widgetInDeployed(draggableWidgets.TABLE));
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
agHelper.Sleep(3000);
|
||||
cy.wait("@postExecute").then((interception) => {
|
||||
let valueToTest = JSON.stringify(
|
||||
interception.response.body.data.body[0].name,
|
||||
);
|
||||
cy.ValidatePaginationInputDataV2(valueToTest);
|
||||
});
|
||||
deployMode.NavigateBacktoEditor();
|
||||
entityExplorer.SelectEntityByName("Table1", "Widgets");
|
||||
cy.ValidatePaginateResponseUrlDataV2(
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
import {
|
||||
agHelper,
|
||||
apiPage,
|
||||
table,
|
||||
dataManager,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
import OneClickBinding from "../../../../locators/OneClickBindingLocator";
|
||||
import FirstTimeUserOnboarding from "../../../../locators/FirstTimeUserOnboarding.json";
|
||||
|
||||
describe("Test Create Api and Bind to Table widget V2", function () {
|
||||
before(() => {
|
||||
agHelper.AddDsl("tableV2WidgetDsl");
|
||||
});
|
||||
|
||||
it("1. Test_Add users api, execute it and go to sniping mode.", function () {
|
||||
apiPage.CreateAndFillApi(
|
||||
dataManager.dsValues[dataManager.defaultEnviorment].mockApiUrl,
|
||||
);
|
||||
apiPage.RunAPI();
|
||||
agHelper.GetNClick(FirstTimeUserOnboarding.selectWidgetBtn);
|
||||
agHelper.AssertElementVisibility(FirstTimeUserOnboarding.snipingBanner);
|
||||
//Click on table name controller to bind the data and exit sniping mode
|
||||
agHelper.GetNClick(table._tableV2Widget);
|
||||
agHelper.AssertContains(
|
||||
"Api1",
|
||||
"exist",
|
||||
OneClickBinding.datasourceDropdownSelector,
|
||||
);
|
||||
agHelper.AssertElementAbsence(FirstTimeUserOnboarding.snipingBanner);
|
||||
});
|
||||
});
|
||||
|
|
@ -92,7 +92,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(1000);
|
||||
propPane.EnterJSContext("Text color", testdata.bindingTextColor);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS("0", "0", "color", "rgb(0, 128, 0)");
|
||||
cy.readTableV2dataValidateCSS("1", "0", "color", "rgb(255, 0, 0)");
|
||||
});
|
||||
|
|
@ -104,7 +103,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
cy.moveToStyleTab();
|
||||
cy.wait(1000);
|
||||
propPane.EnterJSContext("Cell Background", testdata.bindingTextColor);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS(
|
||||
"0",
|
||||
"0",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
cy.moveToStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Text align", testdata.bindingAlign);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS("0", "0", "justify-content", "flex-start");
|
||||
cy.readTableV2dataValidateCSS("1", "0", "justify-content", "flex-end");
|
||||
});
|
||||
|
|
@ -36,7 +35,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
"Vertical alignment",
|
||||
testdata.bindingVerticalAlig,
|
||||
);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS("0", "0", "align-items", "flex-start");
|
||||
cy.readTableV2dataValidateCSS("1", "0", "align-items", "flex-end");
|
||||
});
|
||||
|
|
@ -45,7 +43,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
//cy.movetoStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Text size", testdata.bindingNewSize);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS("0", "0", "font-size", "14px");
|
||||
cy.readTableV2dataValidateCSS("1", "0", "font-size", "24px");
|
||||
});
|
||||
|
|
@ -53,7 +50,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
it("5. Table widget V2 toggle test for style Alignment", function () {
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Emphasis", testdata.bindingStyle);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS("0", "0", "font-style", "normal");
|
||||
cy.readTableV2dataValidateCSS("1", "0", "font-style", "italic");
|
||||
});
|
||||
|
|
@ -62,7 +58,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
cy.moveToStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Text color", testdata.bindingTextColor);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS("0", "0", "color", "rgb(0, 128, 0)");
|
||||
cy.readTableV2dataValidateCSS("1", "0", "color", "rgb(255, 0, 0)");
|
||||
});
|
||||
|
|
@ -71,7 +66,6 @@ describe("Table Widget V2 property pane feature validation", function () {
|
|||
cy.moveToStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Cell Background", testdata.bindingTextColor);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTableV2dataValidateCSS(
|
||||
"0",
|
||||
"0",
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
import * as _ from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Test Create Api and Bind to Table widget", function () {
|
||||
before(() => {
|
||||
_.agHelper.AddDsl("tableWidgetDsl");
|
||||
});
|
||||
|
||||
it("1. Test_Add users api, execute it and go to sniping mode.", function () {
|
||||
cy.createAndFillApi(this.dataSet.userApi, "/mock-api?records=10");
|
||||
cy.RunAPI();
|
||||
cy.get(".t--select-in-canvas").click();
|
||||
cy.get(".t--sniping-mode-banner").should("be.visible");
|
||||
//Click on table name controller to bind the data and exit sniping mode
|
||||
cy.get(".t--draggable-tablewidget").trigger("mouseover");
|
||||
cy.get(".t--settings-sniping-control").click();
|
||||
cy.get(".t--property-control-tabledata .CodeMirror").contains(
|
||||
"{{Api1.data}}",
|
||||
);
|
||||
cy.get(".t--sniping-mode-banner").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
|
@ -15,7 +15,6 @@ describe("Table Widget property pane feature validation", function () {
|
|||
//cy.movetoStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Text align", testdata.bindingAlign);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("0", "0", "justify-content", "flex-start");
|
||||
cy.readTabledataValidateCSS("1", "0", "justify-content", "flex-end");
|
||||
});
|
||||
|
|
@ -36,7 +35,6 @@ describe("Table Widget property pane feature validation", function () {
|
|||
"Vertical alignment",
|
||||
testdata.bindingVerticalAlig,
|
||||
);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("0", "0", "align-items", "flex-start");
|
||||
cy.readTabledataValidateCSS("1", "0", "align-items", "flex-end");
|
||||
});
|
||||
|
|
@ -46,7 +44,6 @@ describe("Table Widget property pane feature validation", function () {
|
|||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Text size", testdata.bindingSize);
|
||||
cy.wait(2000);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("0", "0", "font-size", "14px");
|
||||
cy.readTabledataValidateCSS("1", "0", "font-size", "24px");
|
||||
});
|
||||
|
|
@ -55,7 +52,6 @@ describe("Table Widget property pane feature validation", function () {
|
|||
//cy.movetoStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Font Style", testdata.bindingStyle);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("0", "0", "font-style", "normal");
|
||||
cy.readTabledataValidateCSS("1", "0", "font-style", "italic");
|
||||
});
|
||||
|
|
@ -64,7 +60,6 @@ describe("Table Widget property pane feature validation", function () {
|
|||
//cy.movetoStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Text color", testdata.bindingTextColor);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS("0", "0", "color", "rgb(0, 128, 0)");
|
||||
cy.readTabledataValidateCSS("1", "0", "color", "rgb(255, 0, 0)");
|
||||
});
|
||||
|
|
@ -73,7 +68,6 @@ describe("Table Widget property pane feature validation", function () {
|
|||
//cy.movetoStyleTab();
|
||||
_.agHelper.Sleep();
|
||||
_.propPane.EnterJSContext("Cell Background", testdata.bindingTextColor);
|
||||
cy.wait("@updateLayout");
|
||||
cy.readTabledataValidateCSS(
|
||||
"0",
|
||||
"0",
|
||||
|
|
|
|||
|
|
@ -3,9 +3,21 @@ import * as _ from "../../../../support/Objects/ObjectsCore";
|
|||
|
||||
describe("xml2json text", function () {
|
||||
before(() => {
|
||||
_.agHelper.AddDsl("xmlParser");
|
||||
_.homePage.NavigateToHome();
|
||||
_.homePage.ImportApp("xmlParser.json");
|
||||
_.homePage.AssertImportToast();
|
||||
});
|
||||
it("1. Publish widget and validate the data displayed in text widget from xmlParser function", function () {
|
||||
|
||||
it("1. Check if XMLparser v3 autocomplete works", function () {
|
||||
_.entityExplorer.SelectEntityByName("Text2", "Widgets");
|
||||
_.propPane.TypeTextIntoField("Text", "{{xmlParser.j", true);
|
||||
_.agHelper.GetNAssertElementText(_.locators._hints, "j2xParser");
|
||||
|
||||
_.propPane.TypeTextIntoField("Text", "{{new xmlParser.j2xParser().p", true);
|
||||
_.agHelper.GetNAssertElementText(_.locators._hints, "parse");
|
||||
});
|
||||
|
||||
it("2. Publish widget and validate the data displayed in text widget from xmlParser function", function () {
|
||||
_.deployMode.DeployApp();
|
||||
cy.get(publish.textWidget)
|
||||
.first()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ import {
|
|||
createMessage,
|
||||
} from "../../../../support/Objects/CommonErrorMessages";
|
||||
|
||||
const largeResponseApiUrl = "https://api.publicapis.org/entries";
|
||||
const largeResponseApiUrl = "https://api.github.com/emojis";
|
||||
//"https://api.publicapis.org/entries";
|
||||
//"https://jsonplaceholder.typicode.com/photos";//Commenting since this is faster sometimes & case is failing
|
||||
|
||||
describe("Abort Action Execution", function () {
|
||||
|
|
@ -49,7 +50,7 @@ describe("Abort Action Execution", function () {
|
|||
action: "Delete",
|
||||
entityType: entityItems.Query,
|
||||
});
|
||||
dataSources.DeleteDatasouceFromWinthinDS($dsName as unknown as string);
|
||||
dataSources.DeleteDatasourceFromWithinDS($dsName as unknown as string);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -280,8 +280,7 @@ function multiTreeSelectAndReset() {
|
|||
}
|
||||
|
||||
function radiogroupAndReset() {
|
||||
cy.get("input").last().click({ force: true });
|
||||
cy.wait(1000);
|
||||
_.agHelper.GetNClick("input", 1, true, 1000);
|
||||
_.agHelper.GetNAssertElementText(
|
||||
_.locators._textWidgetInDeployed,
|
||||
"N",
|
||||
|
|
@ -350,8 +349,7 @@ function checkboxGroupAndReset() {
|
|||
}
|
||||
|
||||
function checkboxAndReset() {
|
||||
cy.get("input").last().click({ force: true });
|
||||
cy.wait(1000);
|
||||
_.agHelper.GetNClick("input", 0, true, 1000);
|
||||
_.agHelper.GetNAssertElementText(
|
||||
_.locators._textWidgetInDeployed,
|
||||
"false",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import {
|
|||
dataManager,
|
||||
propPane,
|
||||
table,
|
||||
draggableWidgets,
|
||||
entityExplorer,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import { Widgets } from "../../../../support/Pages/DataSources";
|
||||
|
||||
|
|
@ -15,16 +17,9 @@ import {
|
|||
ERROR_ACTION_EXECUTE_FAIL,
|
||||
createMessage,
|
||||
} from "../../../../support/Objects/CommonErrorMessages";
|
||||
import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags";
|
||||
|
||||
describe("API Bugs", function () {
|
||||
before(() => {
|
||||
featureFlagIntercept(
|
||||
{
|
||||
ab_ds_binding_enabled: false,
|
||||
},
|
||||
false,
|
||||
);
|
||||
agHelper.RefreshPage();
|
||||
});
|
||||
|
||||
|
|
@ -93,4 +88,42 @@ describe("API Bugs", function () {
|
|||
value: "4{{Math.random() > 0.5 ? '¶m1=5' : '¶m2=6'}}",
|
||||
});
|
||||
});
|
||||
|
||||
it("5. Bug 26897, Invalid binding of table data when used existing suggested widgets for an action returning object & array", function () {
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.TABLE);
|
||||
entityExplorer.NavigateToSwitcher("Explorer");
|
||||
|
||||
// Case where api returns array response
|
||||
apiPage.CreateAndFillApi(
|
||||
dataManager.dsValues[dataManager.defaultEnviorment].mockApiUrl,
|
||||
"ARRAY_RESPONSE",
|
||||
);
|
||||
apiPage.RunAPI();
|
||||
dataSources.AddSuggestedWidget(
|
||||
Widgets.Table,
|
||||
dataSources._addSuggestedExisting,
|
||||
);
|
||||
debuggerHelper.AssertErrorCount(0);
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
propPane.AssertPropertiesDropDownCurrentValue(
|
||||
"Table data",
|
||||
"ARRAY_RESPONSE",
|
||||
);
|
||||
|
||||
// Create API so that it returns object response
|
||||
apiPage.CreateAndFillApi(
|
||||
dataManager.dsValues[dataManager.defaultEnviorment].mockApiObjectUrl,
|
||||
"OBJECT_RESPONSE",
|
||||
);
|
||||
apiPage.RunAPI();
|
||||
dataSources.AddSuggestedWidget(
|
||||
Widgets.Table,
|
||||
dataSources._addSuggestedExisting,
|
||||
);
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
propPane.ValidatePropertyFieldValue(
|
||||
"Table data",
|
||||
"{{OBJECT_RESPONSE.data.users}}",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ describe(
|
|||
dataSources.CreatePlugIn("Google Sheets");
|
||||
agHelper.GoBack();
|
||||
agHelper.AssertContains(
|
||||
"Save and authorize",
|
||||
"Save & Authorize",
|
||||
"exist",
|
||||
dataSources._datasourceModalSave,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
import { agHelper, dataSources } from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
let dsName: string;
|
||||
|
||||
const testString = "test";
|
||||
|
||||
describe("Bug 19933: Authenticated API DS in case of OAuth2, should have save and authorise button enabled all the times", function () {
|
||||
it("1. Create Auth API DS, save i, now edit again and check the save and authorise button state", function () {
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
agHelper.GenerateUUID();
|
||||
cy.get("@guid").then((uid) => {
|
||||
dsName = "AuthAPI " + uid;
|
||||
dataSources.CreatePlugIn("Authenticated API");
|
||||
agHelper.RenameWithInPane(dsName, false);
|
||||
dataSources.FillAuthAPIUrl();
|
||||
dataSources.AddOAuth2AuthorizationCodeDetails(
|
||||
testString,
|
||||
testString,
|
||||
testString,
|
||||
testString,
|
||||
);
|
||||
dataSources.SaveDatasource();
|
||||
});
|
||||
|
||||
dataSources.EditDatasource();
|
||||
agHelper.AssertElementEnabledDisabled(
|
||||
dataSources._saveAndAuthorizeDS,
|
||||
0,
|
||||
false,
|
||||
);
|
||||
dataSources.DeleteDSDirectly();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import * as _ from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
let guid;
|
||||
let guid: any;
|
||||
let ws1Name;
|
||||
let ws2Name;
|
||||
let app1Name;
|
||||
let repoName;
|
||||
let app1Name: any;
|
||||
let repoName: any;
|
||||
let branchName;
|
||||
|
||||
describe("Issue 24486 - Issue with Export Application", () => {
|
||||
|
|
@ -19,7 +19,7 @@ describe("Issue 24486 - Issue with Export Application", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("Should export the current branch", () => {
|
||||
it("1. Should export the current branch", () => {
|
||||
_.entityExplorer.DragDropWidgetNVerify(_.draggableWidgets.BUTTON, 200, 200);
|
||||
_.gitSync.CreateNConnectToGit();
|
||||
cy.get("@gitRepoName").then((repName) => {
|
||||
|
|
@ -60,7 +60,7 @@ describe("Issue 24486 - Issue with Export Application", () => {
|
|||
});
|
||||
});
|
||||
|
||||
it("Should import the exported branch", () => {
|
||||
it("2. Should import the exported branch", () => {
|
||||
ws2Name = "Bug24486-w2" + guid;
|
||||
_.homePage.CreateNewWorkspace(ws2Name, true);
|
||||
_.homePage.ImportApp("app-b24486.json", ws2Name);
|
||||
|
|
@ -73,7 +73,7 @@ describe("Issue 24486 - Issue with Export Application", () => {
|
|||
_.propPane.ValidatePropertyFieldValue("Label", "Submit");
|
||||
});
|
||||
|
||||
// after(() => {
|
||||
// _.gitSync.DeleteTestGithubRepo(repoName);
|
||||
// });
|
||||
after(() => {
|
||||
_.gitSync.DeleteTestGithubRepo(repoName);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,24 +1,38 @@
|
|||
import * as _ from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
const { entityExplorer, propPane } = _;
|
||||
import {
|
||||
entityExplorer,
|
||||
propPane,
|
||||
draggableWidgets,
|
||||
agHelper,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Bug 25894 - Moustache brackets should be highlighted", () => {
|
||||
it("1. should show {{ }} in bold", () => {
|
||||
entityExplorer.DragDropWidgetNVerify(_.draggableWidgets.BUTTON, 200, 200);
|
||||
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON);
|
||||
entityExplorer.SelectEntityByName("Button1", "Widgets");
|
||||
|
||||
propPane.EnterJSContext(
|
||||
"onClick",
|
||||
`{{Api1.run({
|
||||
`{{ Api1.run({
|
||||
"key": Button1.text
|
||||
}).then(() => {
|
||||
storeValue('my-secret-key', Button3.text);
|
||||
Query1.run();
|
||||
}).catch(() => {});const a = { a: "key"} }}`,
|
||||
);
|
||||
agHelper
|
||||
.GetElement("span")
|
||||
.filter((index, element) => {
|
||||
const text = Cypress.$(element).text();
|
||||
return text.includes("{{") || text.includes("{");
|
||||
})
|
||||
.should("have.class", "cm-binding-brackets");
|
||||
|
||||
cy.get("span").contains("{{").should("have.class", "cm-binding-brackets");
|
||||
cy.get("span").contains("}}").should("have.class", "cm-binding-brackets");
|
||||
agHelper
|
||||
.GetElement("span")
|
||||
.filter((index, element) => {
|
||||
const text = Cypress.$(element).text();
|
||||
return text.includes("}}") || text.includes("}");
|
||||
})
|
||||
.should("have.class", "cm-binding-brackets"); // Check the class of filtered elements
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import {
|
||||
dataSources,
|
||||
entityExplorer,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Bug 26126: Fix DS button disability", function () {
|
||||
it("ensures save button is correctly updated when DS required fields change", function () {
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
dataSources.CreatePlugIn("S3");
|
||||
dataSources.FillS3DSForm();
|
||||
dataSources.AssertSaveDSButtonDisability(false);
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"S3 service provider",
|
||||
"Amazon S3",
|
||||
"Upcloud",
|
||||
);
|
||||
dataSources.AssertSaveDSButtonDisability(true);
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"S3 service provider",
|
||||
"Upcloud",
|
||||
"Amazon S3",
|
||||
);
|
||||
|
||||
dataSources.AssertSaveDSButtonDisability(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import {
|
||||
agHelper,
|
||||
dataSources,
|
||||
entityExplorer,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
let dsName: any, userMock: string, movieMock: string;
|
||||
|
||||
describe(
|
||||
"excludeForAirgap",
|
||||
"Bug 26716: Datasource selected from entity explorer should be correctly highlighted",
|
||||
function () {
|
||||
it("1. Create users and movies mock datasources and switch between them through entity explorer, check the active state", function () {
|
||||
dataSources.CreateMockDB("Users").then((mockDBName) => {
|
||||
userMock = mockDBName;
|
||||
cy.log("Mock DB Name: " + userMock);
|
||||
dataSources.CreateQueryAfterDSSaved(); //create dummy query for DS to be visible in entity explorer
|
||||
dataSources.CreateMockDB("Movies").then((mockDBName) => {
|
||||
movieMock = mockDBName;
|
||||
cy.log("Mock DB Name: " + mockDBName);
|
||||
dataSources.CreateQueryAfterDSSaved(); //create dummy query for DS to be visible in entity explorer
|
||||
dataSources.CreateDataSource("Postgres");
|
||||
dataSources.CreateQueryAfterDSSaved(); //create dummy query for DS to be visible in entity explorer
|
||||
cy.get("@dsName").then(($dsName) => {
|
||||
dsName = $dsName;
|
||||
// Select Users
|
||||
entityExplorer.SelectEntityByName(userMock, "Datasources");
|
||||
agHelper.Sleep(200);
|
||||
agHelper.AssertClassExists(
|
||||
dataSources._entityExplorerID(userMock),
|
||||
"active",
|
||||
);
|
||||
|
||||
// Switch to Movies
|
||||
entityExplorer.SelectEntityByName(movieMock, "Datasources");
|
||||
agHelper.Sleep(200);
|
||||
agHelper.AssertClassExists(
|
||||
dataSources._entityExplorerID(movieMock),
|
||||
"active",
|
||||
);
|
||||
|
||||
// Switch to custom DS
|
||||
entityExplorer.SelectEntityByName(dsName, "Datasources");
|
||||
entityExplorer.ExpandCollapseEntity(dsName, false);
|
||||
agHelper.Sleep(200);
|
||||
agHelper.AssertClassExists(
|
||||
dataSources._entityExplorerID(dsName),
|
||||
"active",
|
||||
);
|
||||
|
||||
// Delete all datasources
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Query1",
|
||||
action: "Delete",
|
||||
});
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Query2",
|
||||
action: "Delete",
|
||||
});
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Query3",
|
||||
action: "Delete",
|
||||
});
|
||||
|
||||
dataSources.DeleteDatasouceFromActiveTab(userMock);
|
||||
dataSources.DeleteDatasouceFromActiveTab(movieMock);
|
||||
dataSources.DeleteDatasouceFromActiveTab(dsName);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import {
|
||||
agHelper,
|
||||
apiPage,
|
||||
dataManager,
|
||||
debuggerHelper,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Inconsistent Api error after the invalid chars are removed from header key", function () {
|
||||
it("1. Checking whether the appropriate error is displayed even after the removal of invalid chars in header key.", function () {
|
||||
const randomApi = `${
|
||||
dataManager.dsValues[dataManager.defaultEnviorment].mockApiUrl
|
||||
}123`;
|
||||
apiPage.CreateAndFillApi(randomApi);
|
||||
apiPage.RunAPI(false, 20, {
|
||||
expectedPath: "response.body.data.body.data.isExecutionSuccess",
|
||||
expectedRes: false,
|
||||
});
|
||||
|
||||
agHelper.AssertElementAbsence(
|
||||
debuggerHelper.locators._debuggerDownStreamErrMsg,
|
||||
);
|
||||
|
||||
apiPage.EnterHeader(">", "");
|
||||
apiPage.RunAPI(false, 20, {
|
||||
expectedPath: "response.body.data.body.data.isExecutionSuccess",
|
||||
expectedRes: false,
|
||||
});
|
||||
|
||||
cy.get("@postExecute").then((interception: any) => {
|
||||
debuggerHelper.AssertDownStreamLogError(
|
||||
interception.response.body.data.pluginErrorDetails
|
||||
.downstreamErrorMessage,
|
||||
);
|
||||
});
|
||||
|
||||
apiPage.EnterHeader("", "");
|
||||
apiPage.RunAPI(false, 20, {
|
||||
expectedPath: "response.body.data.body.data.isExecutionSuccess",
|
||||
expectedRes: false,
|
||||
});
|
||||
agHelper.AssertElementAbsence(
|
||||
debuggerHelper.locators._debuggerDownStreamErrMsg,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import {
|
||||
agHelper,
|
||||
assertHelper,
|
||||
dataSources,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags";
|
||||
|
||||
describe("Datasource structure schema preview data", () => {
|
||||
before(() => {
|
||||
featureFlagIntercept({ ab_gsheet_schema_enabled: true });
|
||||
dataSources.CreateDataSource("Postgres");
|
||||
});
|
||||
|
||||
it("1. Table selection should be enabled and add template button absent", () => {
|
||||
dataSources.selectTabOnDatasourcePage("View data");
|
||||
agHelper.TypeText(dataSources._datasourceStructureSearchInput, "users");
|
||||
agHelper.GetNClick(
|
||||
dataSources._dsPageTabContainerTableName("public.users"),
|
||||
);
|
||||
assertHelper.AssertNetworkExecutionSuccess("@schemaPreview");
|
||||
agHelper.AssertElementAbsence(
|
||||
dataSources._dsPageTableTriggermenuTarget("public.users"),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import {
|
||||
dataSources,
|
||||
agHelper,
|
||||
entityExplorer,
|
||||
propPane,
|
||||
debuggerHelper,
|
||||
draggableWidgets,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
let dsName: any;
|
||||
let queryName: string;
|
||||
|
||||
describe("Bug 28287: Binding query to widget, check query response in query editor on page load", function () {
|
||||
before("Drag drop a text widget", () => {
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.TEXT);
|
||||
});
|
||||
|
||||
it("1. Check query response in query editor on page load", () => {
|
||||
agHelper.GenerateUUID();
|
||||
cy.get("@guid").then((uuid) => {
|
||||
dataSources.CreateDataSource("Postgres");
|
||||
cy.get("@dsName").then(($dsName) => {
|
||||
dsName = $dsName;
|
||||
});
|
||||
queryName = `Query_${uuid}`;
|
||||
dataSources.CreateQueryAfterDSSaved(
|
||||
"SELECT * FROM users LIMIT 10",
|
||||
queryName,
|
||||
);
|
||||
dataSources.ToggleUsePreparedStatement(false);
|
||||
|
||||
entityExplorer.SelectEntityByName("Text1");
|
||||
propPane.TypeTextIntoField("Text", `{{${queryName}.data}}`);
|
||||
|
||||
agHelper.RefreshPage();
|
||||
|
||||
agHelper.Sleep(1000);
|
||||
|
||||
entityExplorer.SelectEntityByName(queryName, "Queries/JS");
|
||||
|
||||
agHelper.AssertElementVisibility(dataSources._queryResponse("TABLE"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -34,7 +34,7 @@ describe("Bug 9334: The Select widget value is sent as null when user switches b
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
table.WaitUntilTableLoad();
|
||||
|
||||
|
|
@ -52,10 +52,11 @@ describe("Bug 9334: The Select widget value is sent as null when user switches b
|
|||
agHelper.AssertContains("Successfully generated a page");
|
||||
//assertHelper.AssertNetworkStatus("@getActions", 200);//Since failing sometimes
|
||||
assertHelper.AssertNetworkStatus("@postExecute", 200);
|
||||
agHelper.GetNClick(dataSources._visibleTextSpan("Got it"));
|
||||
agHelper.ClickButton("Got it");
|
||||
assertHelper.AssertNetworkStatus("@updateLayout", 200);
|
||||
table.WaitUntilTableLoad();
|
||||
});
|
||||
|
||||
it("2. Navigate & Assert toast", () => {
|
||||
//Navigating between CRUD (Page3) & EmptyPage (Page2):
|
||||
entityExplorer.SelectEntityByName("Page1");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
import {
|
||||
dataSources,
|
||||
entityExplorer,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Fix UQI query switching", function () {
|
||||
it(
|
||||
"excludeForAirgap",
|
||||
"1. The command of the Mongo query must be preserved and should not default to initial value after changed.",
|
||||
function () {
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
dataSources.CreateDataSource("Mongo", false, false);
|
||||
dataSources.CreateQueryAfterDSSaved("", "MongoQuery");
|
||||
dataSources.ValidateNSelectDropdown(
|
||||
"Commands",
|
||||
"Find document(s)",
|
||||
"Insert document(s)",
|
||||
);
|
||||
dataSources.NavigateToDSCreateNew();
|
||||
dataSources.CreateDataSource("Twilio", false, false);
|
||||
dataSources.CreateQueryAfterDSSaved("", "TwilioQuery");
|
||||
dataSources.ValidateNSelectDropdown("Commands", "", "Schedule message");
|
||||
entityExplorer.SelectEntityByName("MongoQuery", "Queries/JS");
|
||||
dataSources.ValidateNSelectDropdown("Commands", "Insert document(s)");
|
||||
|
||||
entityExplorer.SelectEntityByName("TwilioQuery", "Queries/JS");
|
||||
dataSources.ValidateNSelectDropdown("Commands", "Schedule message");
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
@ -44,25 +44,6 @@ describe("datasource unsaved changes popup shows even without changes", function
|
|||
_.dataSources.EditDatasource();
|
||||
_.agHelper.GoBack();
|
||||
_.agHelper.AssertElementVisibility(_.dataSources._activeDS);
|
||||
|
||||
// Edit DS from active tab and add oauth2 details
|
||||
_.dataSources.EditDSFromActiveTab(dsName);
|
||||
_.dataSources.AddOAuth2AuthorizationCodeDetails(
|
||||
testString,
|
||||
testString,
|
||||
testString,
|
||||
testString,
|
||||
);
|
||||
_.dataSources.UpdateDatasource();
|
||||
_.agHelper.Sleep();
|
||||
|
||||
// Now edit DS, and ensure that discard popup is not shown on back button click
|
||||
// Even if custom authentication params are being initialized, we shouldnt see the popup
|
||||
// as those are not initialized by user
|
||||
_.dataSources.EditDatasource();
|
||||
_.agHelper.GoBack();
|
||||
_.agHelper.AssertElementVisibility(_.dataSources._activeDS);
|
||||
|
||||
_.dataSources.DeleteDatasouceFromActiveTab(dsName);
|
||||
});
|
||||
});
|
||||
|
|
@ -154,7 +135,7 @@ describe("datasource unsaved changes popup shows even without changes", function
|
|||
// Edit datasource, change connection string uri param and click on back button
|
||||
_.dataSources.EditDatasource();
|
||||
|
||||
_.agHelper.UpdateInputValue(_.dataSources._host, "jargons");
|
||||
_.agHelper.UpdateInputValue(_.dataSources._host(), "jargons");
|
||||
|
||||
// Assert that popup is visible
|
||||
_.dataSources.cancelDSEditAndAssertModalPopUp(true, false);
|
||||
|
|
@ -164,7 +145,7 @@ describe("datasource unsaved changes popup shows even without changes", function
|
|||
|
||||
// validate the input field value still remains as the saved value
|
||||
_.agHelper.ValidateFieldInputValue(
|
||||
_.dataSources._host,
|
||||
_.dataSources._host(),
|
||||
_.dataManager.dsValues.Staging.mongo_host,
|
||||
);
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue