Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ replay_pid*

# Intellij
.idea

# macOS Finder metadata
.DS_Store
212 changes: 206 additions & 6 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,213 @@ default:
stages:
- test

test_script:
test_java_script:
image: adoptopenjdk/openjdk11:latest
stage: test
cache: []
script:
- LANGUAGES="java" SERVICE="my-service" API_KEY="dummy" JAVA_INSTRUMENTED_BUILD_SYSTEM="all" source <(cat script.sh)
- export LOG_FILE=java-output.log
- export TRACER_INIT_LOG="CI Visibility settings"
- java -version 2>&1 | tee $LOG_FILE
- 'grep -q "$TRACER_INIT_LOG" $LOG_FILE || { echo "Error: Output does not contain tracer initialisation log: $TRACER_INIT_LOG"; exit 1; }'
- |
bash <<'BASH'
set -euo pipefail
LANGUAGES="java" SERVICE="my-service" API_KEY="dummy" JAVA_INSTRUMENTED_BUILD_SYSTEM="all" source <(cat script.sh)
Comment on lines +15 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove nounset when sourcing script.sh in CI jobs

Running the wrapper under set -u causes these jobs to fail before any assertions, because script.sh reads optional vars like SITE/DD_SITE and GO_MODULE_DIR using direct expansions ("$VAR") and exits with unbound variable when they are unset. In this commit both test_java_script and .go_smoke_test enable set -euo pipefail and then source the script, so the pipeline aborts immediately (for example: /dev/fd/63: line 25: SITE: unbound variable) instead of exercising installer behavior.

Useful? React with 👍 / 👎.

export LOG_FILE="java-output.log"
export TRACER_INIT_LOG="CI Visibility settings"
java -version 2>&1 | tee "$LOG_FILE"
grep -q "$TRACER_INIT_LOG" "$LOG_FILE" || { echo "Error: Output does not contain tracer initialisation log: $TRACER_INIT_LOG"; exit 1; }
BASH

.go_smoke_test:
stage: test
cache: []
before_script:
- |
if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then
apt-get update
apt-get install -y curl
fi
go version
script:
- |
bash <<'BASH'
set -euo pipefail

fail() {
echo "Error: $1" >&2
exit 1
}

# Create a minimal Go module in the requested directory so the wrapper can
# exercise the live installer against representative repository layouts.
create_go_module() {
local module_dir="$1"
local module_name="$2"
local module_go="$3"

mkdir -p "$module_dir"
printf 'module %s\n\ngo %s\n' "${module_name}" "${module_go}" > "${module_dir}/go.mod"
printf '%s\n' \
'package smoke' \
'' \
'import "testing"' \
'' \
'func TestSmoke(t *testing.T) {}' > "${module_dir}/smoke_test.go"
}

case "${PROJECT_LAYOUT}" in
root)
create_go_module "." "example.com/test-optimization-gitlab-script-smoke" "${PROJECT_GO}"
;;
single_nested)
create_go_module "services/payments" "example.com/test-optimization-gitlab-script-smoke/payments" "${PROJECT_GO}"
;;
multiple_modules)
create_go_module "services/payments" "example.com/test-optimization-gitlab-script-smoke/payments" "${PROJECT_GO}"
create_go_module "services/refunds" "example.com/test-optimization-gitlab-script-smoke/refunds" "${SECOND_PROJECT_GO}"
;;
*)
fail "Unsupported PROJECT_LAYOUT: ${PROJECT_LAYOUT}"
;;
esac

stdout_file="instrumentation.stdout"
stderr_file="instrumentation.stderr"

set +e
if [ -n "${GO_MODULE_DIR:-}" ]; then
LANGUAGES="go" SERVICE="my-service" API_KEY="dummy" GO_MODULE_DIR="${GO_MODULE_DIR}" source <(cat script.sh) >"${stdout_file}" 2>"${stderr_file}"
else
LANGUAGES="go" SERVICE="my-service" API_KEY="dummy" source <(cat script.sh) >"${stdout_file}" 2>"${stderr_file}"
fi
action_exit=$?
set -e

cat "${stdout_file}"
if [ -s "${stderr_file}" ]; then
cat "${stderr_file}" >&2
fi

if [ "${EXPECT_ACTION_FAILURE}" = "true" ]; then
[ "${action_exit}" -ne 0 ] || fail "Expected the wrapper to fail."
grep -Fq "${EXPECTED_FAILURE_MESSAGE}" "${stderr_file}" || fail "Missing expected failure message: ${EXPECTED_FAILURE_MESSAGE}"
exit 0
fi

[ "${action_exit}" -eq 0 ] || fail "Expected the wrapper to succeed."

if [ -n "${EXPECTED_SKIP_MESSAGE:-}" ]; then
[ -z "${GOFLAGS:-}" ] || fail "GOFLAGS should stay unset when Go instrumentation is skipped."
[ -z "${DD_TRACER_VERSION_GO:-}" ] || fail "DD_TRACER_VERSION_GO should stay unset when Go instrumentation is skipped."
grep -Fq "${EXPECTED_SKIP_MESSAGE}" "${stderr_file}" || fail "Missing expected skip message: ${EXPECTED_SKIP_MESSAGE}"
exit 0
fi

[ -n "${GOFLAGS:-}" ] || fail "GOFLAGS was not set."
[ -n "${DD_TRACER_VERSION_GO:-}" ] || fail "DD_TRACER_VERSION_GO was not set."
echo "${GOFLAGS}" | grep -Fq "orchestrion toolexec" || fail "GOFLAGS does not include orchestrion."
[ -f "${TEST_WORKDIR}/orchestrion.tool.go" ] || fail "orchestrion.tool.go was not created in ${TEST_WORKDIR}."

if [ "${RUN_GO_TESTS}" = "true" ]; then
(
cd "${TEST_WORKDIR}"
DD_TRACE_DEBUG="true" go test -v ./...
)
fi
BASH

test_go_root_go124_success:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: root
PROJECT_GO: "1.24.0"
RUN_GO_TESTS: "true"
TEST_WORKDIR: "."
EXPECT_ACTION_FAILURE: "false"

test_go_root_go125_success:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: root
PROJECT_GO: "1.25.0"
RUN_GO_TESTS: "true"
TEST_WORKDIR: "."
EXPECT_ACTION_FAILURE: "false"

test_go_root_go122_skip:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: root
PROJECT_GO: "1.22.0"
RUN_GO_TESTS: "false"
TEST_WORKDIR: "."
EXPECT_ACTION_FAILURE: "false"
EXPECTED_SKIP_MESSAGE: "The project Go version (1.22.0) is lower than the minimum Go version required by dd-trace-go"

test_go_runner_below_minimum_skip:
extends: .go_smoke_test
image: golang:1.23.12
variables:
PROJECT_LAYOUT: root
PROJECT_GO: "1.24.0"
RUN_GO_TESTS: "false"
TEST_WORKDIR: "."
EXPECT_ACTION_FAILURE: "false"
EXPECTED_SKIP_MESSAGE: "The installed Go version (1.23.12) is lower than the minimum Go version required by dd-trace-go"

test_go_single_nested_go124_auto_detect:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: single_nested
PROJECT_GO: "1.24.0"
RUN_GO_TESTS: "true"
TEST_WORKDIR: "services/payments"
EXPECT_ACTION_FAILURE: "false"

test_go_single_nested_go125_auto_detect:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: single_nested
PROJECT_GO: "1.25.0"
RUN_GO_TESTS: "true"
TEST_WORKDIR: "services/payments"
EXPECT_ACTION_FAILURE: "false"

test_go_multiple_modules_without_override_skip:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: multiple_modules
PROJECT_GO: "1.24.0"
SECOND_PROJECT_GO: "1.25.0"
RUN_GO_TESTS: "false"
TEST_WORKDIR: "."
EXPECT_ACTION_FAILURE: "false"
EXPECTED_SKIP_MESSAGE: "Set DD_CIVISIBILITY_GO_MODULE_DIR to the Go module root if this repository contains multiple Go modules."

test_go_multiple_modules_with_override_success:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: multiple_modules
PROJECT_GO: "1.25.0"
SECOND_PROJECT_GO: "1.24.0"
GO_MODULE_DIR: "./services/payments"
RUN_GO_TESTS: "true"
TEST_WORKDIR: "services/payments"
EXPECT_ACTION_FAILURE: "false"

test_go_missing_override_directory_skip:
extends: .go_smoke_test
image: golang:1.26.1
variables:
PROJECT_LAYOUT: root
PROJECT_GO: "1.24.0"
GO_MODULE_DIR: "./services/does-not-exist"
RUN_GO_TESTS: "false"
TEST_WORKDIR: "."
EXPECT_ACTION_FAILURE: "false"
EXPECTED_SKIP_MESSAGE: "Error: DD_CIVISIBILITY_GO_MODULE_DIR points to a directory that does not exist: ./services/does-not-exist"
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The script takes in the following environment variables:
| PYTHON_TRACER_VERSION | The version of Datadog Python tracer to use. Defaults to the latest release. | false | |
| RUBY_TRACER_VERSION | The version of datadog-ci gem to use. Defaults to the latest release. | false | |
| GO_TRACER_VERSION | The version of Orchestrion automatic compile-time instrumentation of Go code (https://github.com/datadog/orchestrion) to use. Defaults to the latest release. | false | |
| GO_MODULE_DIR | Path to the Go module root directory to instrument. Use this when the repository contains multiple Go modules or the Go module is not in the repository root. | false | |
| JAVA_INSTRUMENTED_BUILD_SYSTEM | If provided, only the specified build systems will be instrumented (allowed values are `gradle`,`maven`,`sbt`,`ant`,`all`). `all` is a special value that instruments every Java process. If this property is not provided, all known build systems will be instrumented (Gradle, Maven, SBT, Ant). | false | |

### Additional configuration
Expand All @@ -63,6 +64,24 @@ test_node:
- npm run test
```

### Go multi-module repositories

If your repository contains multiple Go modules, or the Go module you want to instrument is not at the repository root, set `GO_MODULE_DIR` to the module root directory that contains the target `go.mod` file:

```yaml
test_go:
image: golang:1.25.0
script:
- |
LANGUAGES="go" SITE="datadoghq.com" API_KEY="YOUR_API_KEY_SECRET" GO_MODULE_DIR="./services/payments" \
SRC=$(curl -fsSL https://github.com/DataDog/test-optimization-gitlab-script/releases/download/v1.2.6/script.sh); \
echo "$SRC" | sha256sum | grep -q '^5df7aea8a13e259c66109ecf7f88fef8ffe22369abc7425bf435b4bbfefb0376' && \
source <(echo "$SRC") || \
echo "ERROR: SHA256 mismatch. Datadog Test Optimization autoinstrumentation not enabled." >&2
- cd services/payments
- go test ./...
```

## Limitations

### Tracing vitest tests
Expand Down
11 changes: 9 additions & 2 deletions script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,22 @@ if [ -n "$GO_TRACER_VERSION" ]; then
export DD_SET_TRACER_VERSION_GO=${GO_TRACER_VERSION}
fi

# $GO_MODULE_DIR or $DD_CIVISIBILITY_GO_MODULE_DIR are optional
if [ -n "$GO_MODULE_DIR" ]; then
export DD_CIVISIBILITY_GO_MODULE_DIR=${GO_MODULE_DIR}
fi

# $JAVA_INSTRUMENTED_BUILD_SYSTEM or $DD_INSTRUMENTATION_BUILD_SYSTEM_JAVA are optional
if [ -n "$JAVA_INSTRUMENTED_BUILD_SYSTEM" ]; then
export DD_INSTRUMENTATION_BUILD_SYSTEM_JAVA=${JAVA_INSTRUMENTED_BUILD_SYSTEM}
fi

export DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER="gitlab"

installation_script_url="https://install.datadoghq.com/scripts/install_test_visibility_v11.sh"
installation_script_checksum="fc64c45fd4b45b4b01773c58a3a116bef212dc4095508a6e27e19e50e901bd55"
# Keep the installer URL and checksum pinned together so the wrapper executes a
# deterministic upstream payload.
installation_script_url="https://install.datadoghq.com/scripts/install_test_visibility_v12.sh"
installation_script_checksum="91b6c7bb2c28ef5604c2a2b233da7d931a9b3b5d20b7872254ebb0e689e62f4a"
script_filepath="install_test_visibility.sh"

if command -v curl >/dev/null 2>&1; then
Expand Down