Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

test: [M3-8072] - Cloud changes for ad-hoc test pipeline #11088

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a969f31
Delete 'region-1' Docker Compose service, deprecate 'e2e', 'e2e_heimd…
Oct 8, 2024
7db76b8
Remove entrypoint for test runner in Dockerfile
Oct 8, 2024
4dec8d3
Improve docs, make `yarn` the default entrypoint
Oct 8, 2024
d0db96a
Merge branch 'develop' into M3-8072-cloud-configurable-testing-pipeline
Oct 10, 2024
f8a98e0
WIP add temporary console.log
Oct 10, 2024
c8c3702
Remove temporary logging call
Oct 10, 2024
b600561
Allow Cypress Slack notification title to be customized
Oct 10, 2024
34d0c7b
Allow arbitrary extra information to be displayed in Slack/GitHub not…
Oct 10, 2024
6b46173
Improve formatting wrt PR titles and run IDs
Oct 11, 2024
19a2284
Temporarily force Cypress tests to fail at process level
Oct 11, 2024
d0814b6
Only show up to six failures in a Slack notification
Oct 11, 2024
0fcde2c
Slightly improve truncation note
Oct 11, 2024
05e5a7b
Fix missing space
Oct 11, 2024
dd60b2d
Allow JUnit summary when there are no JUnit files in given path
Oct 11, 2024
756295c
Pass extra info to metadata object
Oct 11, 2024
a4e7800
Restore package scripts
Oct 11, 2024
ff41443
Improve PR title formatting
Oct 11, 2024
94c0d80
Pass pipeline title CLI arg to formatter
Oct 11, 2024
d5ec24d
Make `extra` metadata field optional
Oct 11, 2024
1341dc1
Merge branch 'develop' into M3-8072-cloud-configurable-testing-pipeline
Oct 16, 2024
87f4242
Move LaunchDarkly URL matchers to constants file
Oct 16, 2024
b39fe0c
Allow feature flags to be overridden via CY_TEST_FEATURE_FLAGS enviro…
Oct 16, 2024
40b9bb5
Pass CY_TEST_FEATURE_FLAGS to Docker containers
Oct 16, 2024
cdb6d07
Merge branch 'develop' into M3-8072-cloud-configurable-testing-pipeline
Oct 17, 2024
2cfc7ec
Temporarily force test failure while debugging Slack notification logic
Oct 17, 2024
887be40
Remove forced test failure
Oct 17, 2024
b003b5e
Comment clean up
Oct 21, 2024
a6f1782
Add changesets
Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 46 additions & 17 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ x-e2e-env:
# Cloud Manager-specific test configuration.
CY_TEST_SUITE: ${CY_TEST_SUITE}
CY_TEST_REGION: ${CY_TEST_REGION}
CY_TEST_FEATURE_FLAGS: ${CY_TEST_FEATURE_FLAGS}
CY_TEST_TAGS: ${CY_TEST_TAGS}
CY_TEST_DISABLE_RETRIES: ${CY_TEST_DISABLE_RETRIES}

Expand Down Expand Up @@ -80,14 +81,9 @@ x-e2e-runners:
context: .
dockerfile: ./packages/manager/Dockerfile
target: e2e
depends_on:
web:
condition: service_healthy
env_file: ./packages/manager/.env
volumes: *default-volumes
# TODO Stop using entrypoint, use CMD instead.
# (Or just make `yarn` the entrypoint, but either way stop forcing `cy:e2e`).
entrypoint: ['yarn', 'cy:e2e']
entrypoint: 'yarn'

services:
# Serves a local instance of Cloud Manager for Cypress to use for its tests.
Expand All @@ -110,13 +106,56 @@ services:
timeout: 10s
retries: 10

# Cypress test runner service to run tests against a remotely-served Cloud instance.
#
# This is useful when testing against a standard Cloud Manager environment,
# like Production at cloud.linode.com, but can also be used to run tests against
# pre-Prod environments, PR preview links, and more.
cypress_remote:
<<: *default-runner
environment:
<<: *default-env
MANAGER_OAUTH: ${MANAGER_OAUTH}

# Cypress test runner service to run tests against a locally-served Cloud instance.
#
# This is useful when testing against a customized or in-development build of
# Cloud Manager.
cypress_local:
<<: *default-runner
environment:
<<: *default-env
MANAGER_OAUTH: ${MANAGER_OAUTH}
depends_on:
web:
condition: service_healthy

# Cypress component test runner service.
#
# Unlike other Cloud Manager Cypress tests, these tests can be run without
# requiring a Cloud Manager environment.
cypress_component:
<<: *default-runner
environment:
CY_TEST_DISABLE_RETRIES: ${CY_TEST_DISABLE_RETRIES}
CY_TEST_JUNIT_REPORT: ${CY_TEST_JUNIT_REPORT}


# --> ! DEPRECATION NOTICE ! <--
# The services below this line are deprecated, and will be deleted soon.
# Don't build any pipelines or write any scripts that depend on these.
# Instead, opt to use `cypress_local` in places where you would've used `e2e`,
# use `cypress_remote` in places where you would've used `e2e_heimdall`, and
# use `cypress_component` in places where you would've used `component`.

# Generic end-to-end test runner for Cloud's primary testing pipeline.
# Configured to run against a local Cloud instance.
e2e:
<<: *default-runner
environment:
<<: *default-env
MANAGER_OAUTH: ${MANAGER_OAUTH}
entrypoint: ['yarn', 'cy:e2e']

# Component test runner.
# Does not require any Cloud Manager environment to run.
Expand All @@ -136,14 +175,4 @@ services:
environment:
<<: *default-env
MANAGER_OAUTH: ${MANAGER_OAUTH}

region-1:
build:
context: .
dockerfile: ./packages/manager/Dockerfile
target: e2e
env_file: ./packages/manager/.env
volumes: *default-volumes
environment:
<<: *default-env
MANAGER_OAUTH: ${MANAGER_OAUTH_1}
entrypoint: ['yarn', 'cy:e2e']
11 changes: 6 additions & 5 deletions docs/development-guide/08-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,13 @@ Environment variables related to the general operation of the Cloud Manager Cypr
| `CY_TEST_SUITE` | Name of the Cloud Manager UI test suite to run. Possible values are `core`, `region`, or `synthetic`. | `region` | Unset; defaults to `core` suite |
| `CY_TEST_TAGS` | Query identifying tests that should run by specifying allowed and disallowed tags. | `method:e2e` | Unset; all tests run by default |

###### Regions
These environment variables are used by Cloud Manager's UI tests to override region selection behavior. This can be useful for testing Cloud Manager functionality against a specific region.
###### Overriding Behavior
These environment variables can be used to override some behaviors of Cloud Manager's UI tests. This can be useful when testing Cloud Manager for nonstandard or work-in-progress functionality.

| Environment Variable | Description | Example | Default |
|----------------------|-------------------------------------------------|-----------|---------------------------------------|
| `CY_TEST_REGION` | ID of region to test (as used by Linode APIv4). | `us-east` | Unset; regions are selected at random |
| Environment Variable | Description | Example | Default |
|-------------------------|-------------------------------------------------|-----------|--------------------------------------------|
| `CY_TEST_REGION` | ID of region to test (as used by Linode APIv4). | `us-east` | Unset; regions are selected at random |
| `CY_TEST_FEATURE_FLAGS` | JSON string containing feature flag data | `{}` | Unset; feature flag data is not overridden |

###### Run Splitting
These environment variables facilitate splitting the Cypress run between multiple runners without the use of any third party services. This can be useful for improving Cypress test performance in some circumstances. For additional performance gains, an optional test weights file can be specified using `CY_TEST_SPLIT_RUN_WEIGHTS` (see `CY_TEST_GENWEIGHTS` to generate test weights).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tech Stories
---

Replace 'e2e', 'e2e_heimdall', and 'component' Docker Compose services with 'cypress_local', 'cypress_remote', and 'cypress_component' ([#11088](https://github.com/linode/manager/pull/11088))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11088-tests-1729535093463.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Allow overriding feature flags via CY_TEST_FEATURE_FLAGS environment variable ([#11088](https://github.com/linode/manager/pull/11088))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11088-tests-1729535165205.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Allow pipeline Slack notifications to be customized ([#11088](https://github.com/linode/manager/pull/11088))
5 changes: 5 additions & 0 deletions packages/manager/.changeset/pr-11088-tests-1729535197632.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tests
---

Show PR title in Slack CI notifications ([#11088](https://github.com/linode/manager/pull/11088))
1 change: 0 additions & 1 deletion packages/manager/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,3 @@ ENV CI=1
ENV NO_COLOR=1
ENV HOME=/home/node/
ENV CYPRESS_CACHE_FOLDER=/home/node/.cache/Cypress
ENTRYPOINT yarn cy:ci
2 changes: 2 additions & 0 deletions packages/manager/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { enableJunitReport } from './cypress/support/plugins/junit-report';
import { generateTestWeights } from './cypress/support/plugins/generate-weights';
import { logTestTagInfo } from './cypress/support/plugins/test-tagging-info';
import cypressViteConfig from './cypress/vite.config';
import { featureFlagOverrides } from './cypress/support/plugins/feature-flag-override';

/**
* Exports a Cypress configuration object.
Expand Down Expand Up @@ -91,6 +92,7 @@ export default defineConfig({
fetchAccount,
fetchLinodeRegions,
regionOverrideCheck,
featureFlagOverrides,
logTestTagInfo,
splitCypressRun,
enableJunitReport(),
Expand Down
11 changes: 11 additions & 0 deletions packages/manager/cypress/support/constants/feature-flags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @file Constants related to Cypress's handling of LaunchDarkly feature flags.
*/

// LaunchDarkly URL pattern for feature flag retrieval.
export const launchDarklyUrlPattern =
'https://app.launchdarkly.com/sdk/evalx/*/contexts/*';

// LaunchDarkly URL pattern for feature flag / event streaming.
export const launchDarklyClientstreamPattern =
'https://clientstream.launchdarkly.com/eval/*/*';
2 changes: 2 additions & 0 deletions packages/manager/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ chai.use(function (chai, utils) {

// Test setup.
import { deleteInternalHeader } from './setup/delete-internal-header';
import { mockFeatureFlagRequests } from './setup/mock-feature-flags-request';
import { mockFeatureFlagClientstream } from './setup/feature-flag-clientstream';
import { mockAccountRequest } from './setup/mock-account-request';
import { trackApiRequests } from './setup/request-tracking';

trackApiRequests();
mockAccountRequest();
mockFeatureFlagRequests();
mockFeatureFlagClientstream();
deleteInternalHeader();
12 changes: 4 additions & 8 deletions packages/manager/cypress/support/intercepts/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@
*/

import { getResponseDataFromMockData } from 'support/util/feature-flags';
import {
launchDarklyUrlPattern,
launchDarklyClientstreamPattern,
} from 'support/constants/feature-flags';

import type { FeatureFlagMockData } from 'support/util/feature-flags';

// LaunchDarkly URL pattern for feature flag retrieval.
const launchDarklyUrlPattern =
'https://app.launchdarkly.com/sdk/evalx/*/contexts/*';

// LaunchDarkly URL pattern for feature flag / event streaming.
const launchDarklyClientstreamPattern =
'https://clientstream.launchdarkly.com/eval/*/*';

/**
* Intercepts GET request to feature flag clientstream URL and mocks the response.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { CypressPlugin } from './plugin';

/**
* Handles setup related to Launch Darkly feature flag overrides.
*
* Checks if the user has passed overrides via the `CY_TEST_FEATURE_FLAGS` env,
* and validates its value if so by attempting to parse it as JSON. If that
* succeeds, the parsed override object is exposed to Cypress via the
* `featureFlagOverrides` config.
*/
export const featureFlagOverrides: CypressPlugin = (_on, config) => {
const featureFlagOverridesJson = config.env?.['CY_TEST_FEATURE_FLAGS'];

let featureFlagOverrides = undefined;
if (featureFlagOverridesJson) {
const notice =
'Feature flag overrides are enabled with the following JSON payload:';
const jsonWarning =
'Be aware that malformed or invalid feature flag data can trigger crashes and other unexpected behavior.';

console.info(`${notice}\n\n${featureFlagOverridesJson}\n\n${jsonWarning}`);

try {
featureFlagOverrides = JSON.parse(featureFlagOverridesJson);
} catch (e) {
throw new Error(
`Unable to parse feature flag JSON:\n\n${featureFlagOverridesJson}\n\nPlease double check your 'CY_TEST_FEATURE_FLAGS' value and try again.`
);
}
}

return {
...config,
env: {
...config.env,
featureFlagOverrides,
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @file Intercepts and mocks Launch Darkly feature flag requests with override data if specified.
*/

import { launchDarklyUrlPattern } from 'support/constants/feature-flags';

/**
* If feature flag overrides have been specified, intercept every LaunchDarkly
* feature flag request and modify the response to contain the override data.
*
* This override happens before other intercepts and mocks (e.g. via `mockGetFeatureFlags`
* and `mockAppendFeatureFlags`), so mocks set up by those functions will take
* priority in the event that both modify the same feature flag value.
*/
export const mockFeatureFlagRequests = () => {
const featureFlagOverrides = Cypress.env('featureFlagOverrides');

if (featureFlagOverrides) {
beforeEach(() => {
cy.intercept(
{
middleware: true,
url: launchDarklyUrlPattern,
},
(req) => {
req.on('before:response', (res) => {
const overriddenFeatureFlagData = {
...res.body,
...featureFlagOverrides,
};
res.body = overriddenFeatureFlagData;
});
}
);
});
}
};
3 changes: 3 additions & 0 deletions scripts/junit-summary/formatters/github-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const githubFormatter: Formatter = (

const breakdown = `:x: ${runInfo.failing} Failing | :green_heart: ${runInfo.passing} Passing | :arrow_right_hook: ${runInfo.skipped} Skipped | :clock1: ${secondsToTimeString(runInfo.time)}\n\n`;

const extra = metadata.extra ? `${metadata.extra}\n\n` : null;

const failedTestSummary = (() => {
const heading = `### Details`;
const failedTestHeader = `<table><thead><tr><th colspan="3">Failing Tests</th></tr><tr><th></th><th>Spec</th><th>Test</th></tr></thead><tbody>`;
Expand Down Expand Up @@ -82,6 +84,7 @@ export const githubFormatter: Formatter = (
headline,
'',
breakdown,
extra,
runInfo.failing > 0 ? failedTestSummary : null,
runInfo.failing > 0 ? rerunNote : null,
]
Expand Down
Loading
Loading