Skip to content

Dashboard hardening: session cookie missing Secure/SameSite and no HSTS header #2190

Dashboard hardening: session cookie missing Secure/SameSite and no HSTS header

Dashboard hardening: session cookie missing Secure/SameSite and no HSTS header #2190

name: Run cypress tests
# trigger on every PR for all branches
on:
pull_request:
branches: ['**']
paths-ignore:
- '**/*.md'
- 'docs/**'
- '.lycheeignore'
- 'CODEOWNERS'
- 'changelogs/fragments/**'
types: [opened, synchronize, reopened, ready_for_review]
workflow_dispatch:
inputs:
test_repo:
description: 'Cypress test repo'
default: 'opensearch-project/opensearch-dashboards-functional-test'
required: true
type: string
test_branch:
description: 'Cypress test branch (default: source branch)'
required: false
type: string
specs:
description: 'Tests to run (default: osd:ciGroup)'
required: false
type: string
pr_number:
description: 'PR Number (optional)'
required: false
type: number
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
OSD_OPTIMIZER_THEMES: v8light
TEST_REPO: ${{ inputs.test_repo != '' && inputs.test_repo || 'opensearch-project/opensearch-dashboards-functional-test' }}
TEST_BRANCH: "${{ inputs.test_branch != '' && inputs.test_branch || github.base_ref }}"
FTR_PATH: 'ftr'
CYPRESS_BROWSER: 'chromium'
CYPRESS_VISBUILDER_ENABLED: true
CYPRESS_DATASOURCE_MANAGEMENT_ENABLED: false
CYPRESS_MEMORY_LIMIT: '12288'
CYPRESS_CACHE_FOLDER: '${{ github.workspace }}/.cypress-cache'
# Optimize Chrome
CYPRESS_CHROME_ARGS: >-
--disable-dev-shm-usage
--no-sandbox
--disable-gpu
--disable-software-rasterizer
--js-flags="--max-old-space-size=12288"
OSD_SNAPSHOT_SKIP_VERIFY_CHECKSUM: true
OSD_OPTIMIZER_MAX_WORKERS: 12
NODE_OPTIONS: '--max-old-space-size=12288 --max-semi-space-size=128 --dns-result-order=ipv4first'
COMMENT_TAG: '[MANUAL CYPRESS TEST RUN RESULTS]'
COMMENT_SUCCESS_MSG: ':white_check_mark: Cypress test run succeeded!'
COMMENT_FAILURE_MSG: ':x: Cypress test run failed!'
LATEST_VERSION: '3.4.0'
OPENSEARCH_VERSION: ${{ vars.OPENSEARCH_VERSION }}
jobs:
prepare-cypress:
name: Prepare Cypress source and plugins
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Get source information from PR number
if: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number != '' }}
id: get_pr_info
uses: actions/github-script@v6
with:
script: |
const { data: result } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: ${{ inputs.pr_number }}
});
core.setOutput('head_name', result.head.repo.full_name);
core.setOutput('head_ref', result.head.ref);
- name: Set source repo from PR number
if: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number != '' }}
run: |
echo "SOURCE_REPO=${{ steps.get_pr_info.outputs.head_name }}" >> $GITHUB_ENV
echo "SOURCE_BRANCH=${{ steps.get_pr_info.outputs.head_ref }}" >> $GITHUB_ENV
- name: Checkout code
uses: actions/checkout@v4
with:
repository: ${{ env.SOURCE_REPO }}
ref: '${{ env.SOURCE_BRANCH }}'
fetch-depth: 1
filter: blob:none
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
- name: Setup Yarn
run: |
npm uninstall -g yarn
npm i -g yarn@^1.22.10
yarn config set network-timeout 1000000 -g
- name: Configure Yarn Cache
shell: bash
run: echo "YARN_CACHE_LOCATION=$(yarn cache dir)" >> $GITHUB_ENV
- name: Restore Yarn Cache
id: yarn-cache
uses: actions/cache/restore@v4
with:
path: ${{ env.YARN_CACHE_LOCATION }}
key: yarn-Linux-cypress-${{ hashFiles('**/yarn.lock') }}
restore-keys: yarn-Linux-cypress-
- name: Run bootstrap
shell: bash
run: |
for i in 1 2 3; do
yarn osd bootstrap && exit 0
echo "Bootstrap attempt $i failed, retrying in 10s..."
sleep 10
done
exit 1
- name: Save Yarn Cache
if: steps.yarn-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ${{ env.YARN_CACHE_LOCATION }}
key: yarn-Linux-cypress-${{ hashFiles('**/yarn.lock') }}
- name: Build plugins
run: node scripts/build_opensearch_dashboards_platform_plugins --no-examples --workers 12
- name: Upload plugin bundles
uses: actions/upload-artifact@v4
with:
name: cypress-plugin-bundles
path: |
src/core/target/public
src/plugins/*/target/public
packages/*/target/public
retention-days: 1
if-no-files-found: error
- name: Create source archive
run: |
tar czf /tmp/cypress-source-archive.tar.gz \
--exclude='./.git' \
--exclude='./node_modules' \
--exclude='./src/plugins/*/node_modules' \
--exclude='./packages/*/node_modules' \
--exclude='./test/*/plugins/*/node_modules' \
--exclude='./examples/*/node_modules' \
--exclude='*/target/public' \
.
mv /tmp/cypress-source-archive.tar.gz .
ls -lh cypress-source-archive.tar.gz
- name: Upload source archive
uses: actions/upload-artifact@v4
with:
name: cypress-source-archive
path: cypress-source-archive.tar.gz
retention-days: 1
if-no-files-found: error
cypress-tests:
needs: [prepare-cypress]
runs-on: ubuntu-latest
timeout-minutes: 60
if: github.event.pull_request.draft == false
strategy:
fail-fast: false
matrix:
include:
# Standard test configs (groups 1-9)
- group: 1
config: standard
test_location: ftr
# Wazuh: Commented out groups because sample data of OpenSearch Dashboards is disabled
# - group: 2
# config: standard
# test_location: ftr
- group: 3
config: standard
test_location: ftr
- group: 4
config: standard
test_location: ftr
- group: 5
config: standard
test_location: ftr
# Wazuh: Commented out groups because sample data of OpenSearch Dashboards is disabled
# - group: 6
# config: standard
# test_location: ftr
# - group: 7
# config: standard
# test_location: ftr
# - group: 8
# config: standard
# test_location: ftr
# - group: 9
# config: standard
# test_location: ftr
# Dashboard tests with query enhanced - group 1
# Wazuh: These groups are commented out because uses the new home page
# - group: 10Fast
# config: query_enhanced
# test_location: source
# - group: 10Slow
# config: query_enhanced
# test_location: source
# Wazuh: Commented out groups because sample data of OpenSearch Dashboards is disabled
# Dashboard tests with no query enhanced
# - group: 11
# config: dashboard
# test_location: source
# Dashboard tests with query enhanced - group 2
# - group: 12
# config: query_enhanced
# test_location: source
# Wazuh: Commented out groups because sample data of OpenSearch Dashboards is disabled
# Dashboard tests with query enhanced - group 3
# - group: 13
# config: query_enhanced
# test_location: source
# Dashboard tests with query enhanced - group 4
# - group: 14
# config: query_enhanced
# test_location: source
# - group: 15
# config: query_enhanced
# test_location: source
# - group: 16
# config: query_enhanced
# test_location: source
# - group: 17
# config: query_enhanced
# test_location: source
# - group: 18
# config: query_enhanced
# test_location: source
# - group: 19
# config: query_enhanced
# test_location: source
# Explore tests
# Wazuh: These groups are commented out because uses the new home page
# - group: 10Explore
# config: explore
# test_location: source
# - group: 12Explore
# config: explore
# test_location: source
# - group: 13Explore
# config: explore
# test_location: source
# - group: 14Explore
# config: explore
# test_location: source
# - group: 15Explore
# config: explore
# test_location: source
# - group: 16Explore
# config: explore
# test_location: source
# - group: 17Explore
# config: explore
# test_location: source
# - group: 18Explore
# config: explore
# test_location: source
# - group: 19Explore
# config: explore
# test_location: source
# - group: 20Explore
# config: explore
# test_location: source
# - group: 21Explore
# config: explore
# test_location: source
# - group: 22Explore
# config: explore
# test_location: source
container:
image: docker://opensearchstaging/ci-runner:ci-runner-rockylinux8-opensearch-dashboards-integtest-v2
options: '--user 1001 --shm-size=4g'
env:
START_CMD: ${{ matrix.config == 'query_enhanced' &&
'node scripts/opensearch_dashboards --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --csp.warnLegacyBrowsers=false --uiSettings.overrides["query:enhancements:enabled"]=true --uiSettings.overrides[''home:useNewHomePage'']=true --data_source.enabled=true --workspace.enabled=true --opensearch.ignoreVersionMismatch=true --data.savedQueriesNewUI.enabled=true --home.disableExperienceModal=true --opensearchDashboards.branding.useExpandedHeader=true' ||
matrix.config == 'explore' &&
'node scripts/opensearch_dashboards --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --csp.warnLegacyBrowsers=false --uiSettings.overrides["query:enhancements:enabled"]=true --uiSettings.overrides[''home:useNewHomePage'']=true --data_source.enabled=true --workspace.enabled=true --opensearch.ignoreVersionMismatch=true --data.savedQueriesNewUI.enabled=true --explore.enabled=true --explore.discoverTraces.enabled=true --home.disableExperienceModal=true --datasetManagement.enabled=true --opensearchDashboards.branding.useExpandedHeader=true' ||
matrix.config == 'dashboard' &&
'node scripts/opensearch_dashboards --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --home.disableExperienceModal=true --opensearchDashboards.branding.useExpandedHeader=true' ||
'node ../scripts/opensearch_dashboards --no-base-path --no-watch --savedObjects.maxImportPayloadBytes=10485760 --server.maxPayloadBytes=1759977 --logging.json=false --data.search.aggs.shardDelay.enabled=true --csp.warnLegacyBrowsers=false --uiSettings.overrides["query:enhancements:enabled"]=false --home.disableExperienceModal=true --opensearchDashboards.branding.useExpandedHeader=true' }}
OPENSEARCH_SNAPSHOT_CMD:
${{ (matrix.config == 'query_enhanced' || matrix.config == 'explore') &&
'/bin/bash -c "./opensearch-${{ env.LATEST_VERSION }}/opensearch-tar-install.sh &"' ||
matrix.config == 'dashboard' &&
'node scripts/opensearch snapshot -E cluster.routing.allocation.disk.threshold_enabled=false -E search.concurrent_segment_search.mode=none -E action.auto_create_index=true' ||
'node ../scripts/opensearch snapshot -E cluster.routing.allocation.disk.threshold_enabled=false -E search.concurrent_segment_search.mode=none -E action.auto_create_index=true' }}
# prevents extra Cypress installation progress messages
CI: 1
# avoid warnings like "tput: No value for $TERM and no -T specified"
TERM: xterm
name: Run cypress tests (osd:ciGroup${{ matrix.group }})
steps:
- name: Download source archive
uses: actions/download-artifact@v4
timeout-minutes: 5
with:
name: cypress-source-archive
- name: Extract source archive
shell: bash
run: |
tar xzf cypress-source-archive.tar.gz && rm cypress-source-archive.tar.gz
git init -q && git -c user.name=ci -c user.email=ci commit -q --allow-empty -m "source archive"
- name: Download plugin bundles
uses: actions/download-artifact@v4
timeout-minutes: 5
with:
name: cypress-plugin-bundles
- name: Set TEST_BRANCH
run: |
if [ -n "${{ inputs.test_branch }}" ]; then
echo "TEST_BRANCH=${{ inputs.test_branch }}" >> $GITHUB_ENV
else
VERSION=$(jq -r '.version' package.json)
echo "TEST_BRANCH=$VERSION" >> $GITHUB_ENV
fi
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
- name: Setup Yarn
run: |
npm uninstall -g yarn
npm i -g yarn@^1.22.10
yarn config set network-timeout 1000000 -g
- name: Configure Yarn Cache
shell: bash
run: echo "YARN_CACHE_LOCATION=$(yarn cache dir)" >> $GITHUB_ENV
- name: Restore Yarn Cache
uses: actions/cache/restore@v4
with:
path: ${{ env.YARN_CACHE_LOCATION }}
key: yarn-Linux-cypress-${{ hashFiles('**/yarn.lock') }}
restore-keys: yarn-Linux-cypress-
- name: Run bootstrap
shell: bash
run: |
for i in 1 2 3; do
yarn osd bootstrap && exit 0
echo "Bootstrap attempt $i failed, retrying in 10s..."
sleep 10
done
exit 1
- name: Checkout FT repo
if: matrix.test_location == 'ftr'
uses: actions/checkout@v4
with:
path: ${{ env.FTR_PATH }}
repository: ${{ env.TEST_REPO }}
ref: '${{ env.TEST_BRANCH }}'
clean: true
fetch-depth: 1
filter: blob:none
- name: Setup spec files by input
if: ${{ inputs.specs != '' }}
run: |
echo "SPEC=${{ inputs.specs }}" >> $GITHUB_ENV
# Setup spec files for existing Functional Test repo cypress tests
- name: Setup spec files
if: ${{ inputs.specs == '' && matrix.test_location == 'ftr' }}
working-directory: ${{ env.FTR_PATH }}
shell: bash
run: |
IFS="," read -a SPEC_ARRAY <<< $(yarn --silent osd:ciGroup${{ matrix.group }})
FORMATTED_SPEC=''
for i in "${SPEC_ARRAY[@]}"; do
FORMATTED_SPEC+="cypress/integration/core-opensearch-dashboards/opensearch-dashboards/${i},"
done
echo "SPEC=${FORMATTED_SPEC}" >> $GITHUB_ENV
echo "SPEC=${FORMATTED_SPEC}"
# Setup spec files for OSD in-house cypress tests
- name: Setup spec files for OSD tests
if: ${{ inputs.specs == '' && matrix.test_location == 'source' }}
shell: bash
run: |
DASHBOARDS_SPEC="$(yarn --silent osd:ciGroup${{ matrix.group }})"
echo "DASHBOARDS_SPEC=${DASHBOARDS_SPEC}" >> $GITHUB_ENV
echo "DASHBOARDS_SPEC=${DASHBOARDS_SPEC}"
- name: Get Cypress version
id: cypress_version
run: |
echo "cypress_version=$(cat ./${{ env.FTR_PATH }}/package.json | jq '.devDependencies.cypress' | tr -d '"')" >> $GITHUB_OUTPUT
- name: Cache Cypress
id: cache-cypress
uses: actions/cache@v4
with:
path: ~/.cache/Cypress
key: cypress-cache-v2-${{ runner.os }}-${{ hashFiles('**/package.json') }}
env:
CYPRESS_INSTALL_BINARY: ${{ steps.cypress_version.outputs.cypress_version }}
- run: npx cypress cache list
- run: npx cypress cache path
# Run tests based on configuration
- name: Run FT repo tests
if: matrix.test_location == 'ftr'
uses: cypress-io/github-action@v6
with:
working-directory: ${{ env.FTR_PATH }}
start: ${{ env.OPENSEARCH_SNAPSHOT_CMD }}, ${{ env.START_CMD }}
wait-on: 'http://localhost:9200, http://localhost:5601'
command: yarn cypress:run-without-security --browser ${{ env.CYPRESS_BROWSER }} --config ignoreTestFiles="dashboard_sanity_test_spec.js" --spec ${{ env.SPEC }}
# Screenshots are only captured on failure, will change this once we do visual regression tests
- name: Download OpenSearch
if: matrix.config == 'query_enhanced' || matrix.config == 'explore'
uses: suisei-cn/actions-download-file@v1.4.0
with:
url: https://artifacts.opensearch.org/releases/bundle/opensearch/${{ env.LATEST_VERSION }}/opensearch-${{ env.LATEST_VERSION }}-linux-x64.tar.gz
- name: Extract OpenSearch
if: matrix.config == 'query_enhanced' || matrix.config == 'explore'
run: |
tar -xzf opensearch-*.tar.gz
rm -f opensearch-*.tar.gz
shell: bash
- name: Remove security plugin and plugins that depend on security
if: matrix.config == 'query_enhanced' || matrix.config == 'explore'
run: |
/bin/bash -c "yes | ./opensearch-${{ env.LATEST_VERSION }}/bin/opensearch-plugin remove opensearch-skills"
/bin/bash -c "yes | ./opensearch-${{ env.LATEST_VERSION }}/bin/opensearch-plugin remove opensearch-ml"
/bin/bash -c "yes | ./opensearch-${{ env.LATEST_VERSION }}/bin/opensearch-plugin remove opensearch-anomaly-detection"
/bin/bash -c "yes | ./opensearch-${{ env.LATEST_VERSION }}/bin/opensearch-plugin remove opensearch-flow-framework"
/bin/bash -c "yes | ./opensearch-${{ env.LATEST_VERSION }}/bin/opensearch-plugin remove opensearch-security"
shell: bash
- name: Configure OpenSearch for index creation
if: matrix.config == 'query_enhanced' || matrix.config == 'explore'
run: |
echo "action.auto_create_index: true" >> ./opensearch-${{ env.LATEST_VERSION }}/config/opensearch.yml
echo "cluster.routing.allocation.disk.threshold_enabled: false" >> ./opensearch-${{ env.LATEST_VERSION }}/config/opensearch.yml
shell: bash
- name: Run OpenSearch
if: matrix.config == 'query_enhanced' || matrix.config == 'explore'
run: |
/bin/bash -c "./opensearch-${{ env.LATEST_VERSION }}/opensearch-tar-install.sh &"
sleep 30
shell: bash
- name: Start Prometheus
if: matrix.group == '14Explore'
run: |
PROM_VERSION="3.8.1"
curl -sL https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/prometheus-${PROM_VERSION}.linux-amd64.tar.gz | tar xzf -
# Start Prometheus with fixture config
./prometheus-${PROM_VERSION}.linux-amd64/prometheus \
--config.file=./cypress/fixtures/prometheus/prometheus.yml \
--storage.tsdb.path=/tmp/prometheus-data \
--web.listen-address=:9090 \
--web.enable-lifecycle \
--web.enable-admin-api &
# Wait for Prometheus to be ready
echo "Waiting for Prometheus to start..."
for i in {1..30}; do
if curl -s http://localhost:9090/-/healthy > /dev/null 2>&1; then
echo "Prometheus is ready!"
break
fi
echo "Attempt $i: Prometheus not ready yet..."
sleep 2
done
shell: bash
# Clear Cypress Cache before running OSD tests
- name: Clear Cypress Cache
if: matrix.test_location == 'source'
run: npx cypress cache clear
# Run OSD Cypress tests within the source repo
- name: Run OSD Cypress tests with query enhancements
if: matrix.test_location == 'source' && (matrix.config == 'query_enhanced' || matrix.config == 'explore') && matrix.group != '14Explore'
uses: cypress-io/github-action@v6
with:
install-command: npx cypress install --force
start: ${{ env.START_CMD }}
wait-on: 'http://localhost:9200, http://localhost:5601'
command: yarn cypress:run-without-security --browser ${{ env.CYPRESS_BROWSER }} --spec ${{ env.DASHBOARDS_SPEC }}
- name: Run OSD Cypress tests with Prometheus (part of Explore group 14)
if: matrix.test_location == 'source' && matrix.group == '14Explore'
uses: cypress-io/github-action@v6
with:
install-command: npx cypress install --force
start: ${{ env.START_CMD }}
wait-on: 'http://localhost:9200, http://localhost:5601, http://localhost:9090/-/healthy'
command: yarn cypress:run-without-security --browser ${{ env.CYPRESS_BROWSER }} --spec ${{ env.DASHBOARDS_SPEC }}
env:
PROMETHEUS_CONNECTION_URL: 'http://localhost:9090'
- name: Run OSD Cypress tests without query enhancements
if: matrix.test_location == 'source' && matrix.config == 'dashboard'
uses: cypress-io/github-action@v6
with:
install-command: npx cypress install --force
start: ${{ env.OPENSEARCH_SNAPSHOT_CMD }}, ${{ env.START_CMD }}
wait-on: 'http://localhost:9200, http://localhost:5601'
command: yarn cypress:run-without-security --browser ${{ env.CYPRESS_BROWSER }} --spec ${{ env.DASHBOARDS_SPEC }}
- name: Compress FT repo artifacts
if: always() && matrix.test_location == 'ftr'
run: |
mkdir -p ftr-artifacts
for dir in screenshots videos results; do
if [ -d "${{ env.FTR_PATH }}/cypress/$dir" ]; then
cp -r "${{ env.FTR_PATH }}/cypress/$dir" ftr-artifacts/
fi
done
tar -czf ftr-cypress-artifacts-${{ matrix.group }}.tar.gz -C ftr-artifacts .
shell: bash
- name: Upload FT repo artifacts
if: always() && matrix.test_location == 'ftr'
uses: actions/upload-artifact@v4
with:
name: ftr-cypress-artifacts-${{ matrix.group }}
path: ftr-cypress-artifacts-${{ matrix.group }}.tar.gz
retention-days: 1
# Upload JUnit XML results separately (uncompressed) so AI agents and humans
# can read failures directly via `gh run download -n ftr-cypress-junit-<group>`
# without extracting the tar.gz first.
- name: Upload FT repo Cypress JUnit results
if: always() && matrix.test_location == 'ftr'
uses: actions/upload-artifact@v4
with:
name: ftr-cypress-junit-${{ matrix.group }}
path: ${{ env.FTR_PATH }}/cypress/results/**/*.xml
retention-days: 7
if-no-files-found: ignore
overwrite: true
- name: Compress OSD repo artifacts
if: always() && matrix.test_location == 'source'
run: |
mkdir -p osd-artifacts
for dir in screenshots videos results; do
if [ -d "cypress/$dir" ]; then
cp -r "cypress/$dir" osd-artifacts/
fi
done
tar -czf osd-cypress-artifacts-${{ matrix.group }}.tar.gz -C osd-artifacts .
shell: bash
- name: Upload OSD repo artifacts
if: always() && matrix.test_location == 'source'
uses: actions/upload-artifact@v4
with:
name: osd-cypress-artifacts-${{ matrix.group }}
path: osd-cypress-artifacts-${{ matrix.group }}.tar.gz
retention-days: 1
overwrite: true
# Upload JUnit XML results separately (uncompressed) so AI agents and humans
# can read failures directly via `gh run download -n cypress-junit-<group>`
# without extracting the tar.gz first.
- name: Upload Cypress JUnit results
if: always() && matrix.test_location == 'source'
uses: actions/upload-artifact@v4
with:
name: cypress-junit-${{ matrix.group }}
path: cypress/results/**/*.xml
retention-days: 7
if-no-files-found: ignore
overwrite: true
# add-comment:
# needs: [cypress-tests]
# if: ${{ always() && github.event_name == 'workflow_dispatch' && inputs.pr_number != '' }}
# permissions:
# pull-requests: write
# runs-on: ubuntu-latest
# steps:
# - name: Find Comment
# uses: peter-evans/find-comment@v2
# id: fc
# with:
# issue-number: ${{ inputs.pr_number }}
# comment-author: 'github-actions[bot]'
# body-includes: '${{ env.COMMENT_TAG }}'
# - name: Add comment on the PR
# uses: peter-evans/create-or-update-comment@v3
# with:
# comment-id: ${{ steps.fc.outputs.comment-id }}
# issue-number: ${{ inputs.pr_number }}
# body: |
# ### ${{ env.COMMENT_TAG }}
# #### ${{ needs.cypress-tests.result == 'success' && env.COMMENT_SUCCESS_MSG || env.COMMENT_FAILURE_MSG }}
# #### Inputs:
# ```
# Test repo: '${{ env.TEST_REPO }}'
# Test branch: '${{ env.TEST_BRANCH }}'
# Test spec:
# '${{ env.SPEC }}'
# ```
# #### Link to results:
# ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
# edit-mode: replace