Skip to content
105 changes: 105 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,111 @@ jobs:
rm -rf .git
yarn datadog-ci version

e2e-test-windows:
strategy:
matrix:
version: [20, 22, 24]

name: End-to-end test the package (Windows)
runs-on: windows-latest
needs: build-and-test
env:
FORCE_COLOR: 1

steps:
- uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
# Only checkout the files we need from the `DataDog/datadog-ci` repo.
# See https://github.com/actions/checkout#fetch-only-a-single-file
sparse-checkout: bin/check-junit-upload.js
sparse-checkout-cone-mode: false
- name: Install node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ matrix.version }}
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: artifacts-${{ matrix.version }}
path: artifacts/
# Force all dependencies to be installed from the artifacts
- name: Create e2e project (Windows)
run: |
echo '{
"name": "datadog-ci-e2e-tests",
"resolutions": {
"@datadog/datadog-ci-base": "file:./artifacts/@datadog-datadog-ci-base-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-deployment": "file:./artifacts/@datadog-datadog-ci-plugin-deployment-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-dora": "file:./artifacts/@datadog-datadog-ci-plugin-dora-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-gate": "file:./artifacts/@datadog-datadog-ci-plugin-gate-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-sarif": "file:./artifacts/@datadog-datadog-ci-plugin-sarif-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-sbom": "file:./artifacts/@datadog-datadog-ci-plugin-sbom-${{ matrix.version }}.tgz"
},
"dependencies": {
"@datadog/datadog-ci": "./artifacts/@datadog-datadog-ci-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-base": "./artifacts/@datadog-datadog-ci-base-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-aas": "./artifacts/@datadog-datadog-ci-plugin-aas-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-cloud-run": "./artifacts/@datadog-datadog-ci-plugin-cloud-run-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-container-app": "./artifacts/@datadog-datadog-ci-plugin-container-app-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-lambda": "./artifacts/@datadog-datadog-ci-plugin-lambda-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-stepfunctions": "./artifacts/@datadog-datadog-ci-plugin-stepfunctions-${{ matrix.version }}.tgz",
"@datadog/datadog-ci-plugin-synthetics": "./artifacts/@datadog-datadog-ci-plugin-synthetics-${{ matrix.version }}.tgz"
}
}' > package.json

yarn set version stable
yarn install --no-immutable
- name: Run synthetics test
run: yarn datadog-ci synthetics run-tests --config artifacts/e2e/global.config.json
env:
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY_E2E }}
DATADOG_APP_KEY: ${{ secrets.DATADOG_APP_KEY_E2E }}
- name: Run sourcemaps upload test
run: yarn datadog-ci sourcemaps upload artifacts/e2e/sourcemaps/ --release-version=e2e --service=e2e-tests --minified-path-prefix=https://e2e-tests.datadoghq.com/static/
env:
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY_E2E }}
DATADOG_APP_KEY: ${{ secrets.DATADOG_APP_KEY_E2E }}
- name: Run junit upload test (measures)
run: yarn datadog-ci junit upload --service=datadog-ci-e2e-tests-junit **/junit-reports/**/*.xml --measures testmeasure1:20 --report-measures sessionmeasure1:40
env:
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }}
- name: Check that test data can be queried (measures)
run: |
yarn add @datadog/datadog-api-client
yarn node bin/check-junit-upload.js
env:
EXTRA_TEST_QUERY_FILTER: "@testmeasure1:20"
EXTRA_SESSION_QUERY_FILTER: "@sessionmeasure1:40"
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }}
DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }}
DD_SERVICE: datadog-ci-e2e-tests-junit
- name: Run junit upload test (measures), passing glob as literal string
run: yarn datadog-ci junit upload --service=datadog-ci-e2e-tests-junit '**/junit-reports/**' --measures testmeasure2:60 --report-measures sessionmeasure2:80
env:
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }}
- name: Check that test data can be queried (measures)
run: |
yarn add @datadog/datadog-api-client
yarn node bin/check-junit-upload.js
env:
EXTRA_TEST_QUERY_FILTER: "@testmeasure2:60"
EXTRA_SESSION_QUERY_FILTER: "@sessionmeasure2:80"
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }}
DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }}
DD_SERVICE: datadog-ci-e2e-tests-junit
- name: Run sarif upload test
run: yarn datadog-ci sarif upload --service=datadog-ci-e2e-tests-sarif artifacts/e2e/sarif-reports
env:
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }}
- name: Run sbom upload test
run: yarn datadog-ci sbom upload --service=datadog-ci-e2e-tests-sbom --env test artifacts/e2e/sbom-reports/sbom.json
env:
DD_API_KEY: ${{ secrets.DD_API_KEY_CI_VISIBILITY }}
DD_APP_KEY: ${{ secrets.DD_APP_KEY_CI_VISIBILITY }}
- name: Check that version can be run without git repository
run: |
Remove-Item -Recurse -Force .git
yarn datadog-ci version

# We only test with a single plugin and a single Node.js version.
test-plugin-auto-install-during-npx:
name: Test plugin auto-install during npx
Expand Down
6 changes: 6 additions & 0 deletions bin/lint-packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,12 @@ TO_APPLY.push(matchAndReplace('.github/workflows/ci.yml')`
echo '${e2eProjectPackageJson}' > package.json
`)

TO_APPLY.push(matchAndReplace('.github/workflows/ci.yml')`
- name: Create e2e project (Windows)
run: |
echo '${e2eProjectPackageJson}' > package.json
`)

TO_APPLY.push(matchAndReplace('.github/workflows/ci.yml')`
- name: Run AAS command with auto-install (NPX)
run: |
Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
"package:clean-dist": "cd $INIT_CWD && rimraf --glob 'dist/**/__tests__'",
"package:lint": "eslint --cache --quiet $INIT_CWD/src/**/*.ts",
"publish:all": "yarn loop-packages --topological --verbose npm publish",
"test": "jest --colors",
"test:debug": "node --inspect-brk node_modules/jest/bin/jest --runInBand",
"test:dsyms": "jest packages/datadog-ci/src/commands/dsyms --colors",
"test:helpers": "jest packages/datadog-ci/src/helpers --colors",
"test:serverless": "jest --colors packages/base/src/helpers/serverless packages/plugin-aas packages/plugin-container-app packages/plugin-lambda packages/plugin-cloud-run packages/plugin-stepfunctions",
"test:windows": "jest --config ./jest.config-windows.mjs --colors",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest --colors",
"test:debug": "node --experimental-vm-modules --inspect-brk node_modules/jest/bin/jest --colors --runInBand",
"test:dsyms": "yarn test packages/datadog-ci/src/commands/dsyms",
"test:helpers": "yarn test packages/datadog-ci/src/helpers",
"test:serverless": "yarn test packages/base/src/helpers/serverless packages/plugin-aas packages/plugin-container-app packages/plugin-lambda packages/plugin-cloud-run packages/plugin-stepfunctions",
"test:windows": "yarn test --config ./jest.config-windows.mjs",
"tsc:build": "tsc --build --verbose",
"version:all": "yarn loop-packages version ${0} --immediate"
},
Expand Down
14 changes: 13 additions & 1 deletion packages/base/src/helpers/__tests__/plugin.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import {SyntheticsRunTestsCommand} from '../../commands/synthetics/run-tests'

import {isStandaloneBinary} from '../is-standalone-binary'
import {messageBox} from '../message-box'
import * as pluginModule from '../plugin'
import {checkPlugin, getTempPath, installPlugin, listAllPlugins} from '../plugin'
import {checkPlugin, getTempPath, installPlugin, listAllPlugins, executePluginCommand} from '../plugin'

import {createCommand} from './testing-tools'

jest.mock('node:child_process')
jest.mock('../is-standalone-binary')
Expand Down Expand Up @@ -57,6 +61,14 @@ describe('checkPlugin', () => {
})
})

describe('executePluginCommand', () => {
test('executes plugin command successfully', async () => {
const command = createCommand(SyntheticsRunTestsCommand)
const result = await executePluginCommand(command)
expect(result).toBe(0)
})
})

describe('installPlugin', () => {
test('installs plugin successfully', async () => {
const mockInstallPackage = jest.fn().mockResolvedValue({
Expand Down
1 change: 1 addition & 0 deletions packages/base/src/helpers/__tests__/testing-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export const createCommand = <T extends Command>(
// Create a new instance of commandClass and pass in the parameters
const command = new commandClass()
command.context = {...createMockContext(), ...context} as BaseContext
command.path = (command.constructor as CommandClass).paths?.[0] ?? []

resolveCommandOptionsDefaults(command)

Expand Down
18 changes: 11 additions & 7 deletions packages/base/src/helpers/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {exec} from 'node:child_process'
import path from 'node:path'
import url from 'node:url'
import {inspect} from 'node:util'

import chalk from 'chalk'
Expand Down Expand Up @@ -276,16 +277,17 @@ const importPluginSubmodule = async (scope: string, command: string): Promise<Pl

const submoduleName = `@datadog/datadog-ci-plugin-${scope}/commands/${command}`
debug('Resolving submodule:', submoduleName)
let resolvedPath = submoduleName
let submodulePath = submoduleName
try {
resolvedPath = require.resolve(submoduleName)
debug(`Resolved to: ${resolvedPath}`)
const resolvedPath = require.resolve(submoduleName)
const absolutePath = url.pathToFileURL(resolvedPath).href
submodulePath = absolutePath
} catch (error) {
debug(`Could not require.resolve() the ${submoduleName} submodule: ${error}`)
}
debug('Importing submodule:', resolvedPath)
debug('Importing submodule:', submodulePath)

return (await import(resolvedPath)) as PluginSubModule
return (await import(submodulePath)) as PluginSubModule
}

export const scopeToPackageName = (scope: string): string => {
Expand Down Expand Up @@ -327,12 +329,14 @@ const getPackagesToInstall = (scope: string) => {

const importPlugin = async (scope: string, command?: string): Promise<PluginPackageJson | PluginSubModule> => {
if (scope.match(/^@datadog\/datadog-ci-plugin-[a-z-]+$/)) {
// Use `require()` instead of `await import()` to avoid a `ERR_IMPORT_ATTRIBUTE_MISSING` error.
// Use `require()` instead of `await import()` to avoid `ERR_IMPORT_ATTRIBUTE_MISSING` due to missing `{with: {type: 'json'}}`.
// This is only supported with `--module` set to `esnext`, `node16`, or `nodenext`.
return extractPackageJson(require(`${scope}/package.json`))
}

if (!command) {
// Use `require()` instead of `await import()` to avoid a `ERR_IMPORT_ATTRIBUTE_MISSING` error.
// Use `require()` instead of `await import()` to avoid `ERR_IMPORT_ATTRIBUTE_MISSING` due to missing `{with: {type: 'json'}}`.
// This is only supported with `--module` set to `esnext`, `node16`, or `nodenext`.
return extractPackageJson(require(`@datadog/datadog-ci-plugin-${scope}/package.json`))
}

Expand Down