diff --git a/e2e/scripts/Dockerfile b/e2e/scripts/Dockerfile index 58fbf6b3..bf307772 100644 --- a/e2e/scripts/Dockerfile +++ b/e2e/scripts/Dockerfile @@ -3,6 +3,8 @@ ARG COMPOSER_VERSION FROM docker.io/library/golang:1.26.2-alpine3.23@sha256:f85330846cde1e57ca9ec309382da3b8e6ae3ab943d2739500e08c86393a21b1 AS build WORKDIR /app +ENV GOEXPERIMENT=jsonv2 + COPY go.mod go.sum ./ RUN go mod download && go mod verify diff --git a/e2e/scripts/main_test.go b/e2e/scripts/main_test.go index 4befe9b0..4722d26c 100644 --- a/e2e/scripts/main_test.go +++ b/e2e/scripts/main_test.go @@ -3,6 +3,7 @@ package main import ( + "encoding/json/v2" "fmt" "os" "strings" @@ -17,7 +18,34 @@ func TestScripts(t *testing.T) { if srvURL == "" { t.Fatal("WPSECADV_SERVER_URL environment variable is not set") } - t.Logf("server URL: %s", srvURL) + t.Logf("server URL: %q", srvURL) + + caFile := os.Getenv("TESTSCRIPT_COMPOSER_CAFILE") + t.Logf("ca file: %q", caFile) + + type repo struct { + Type string `json:"type"` + URL string `json:"url"` + Options struct { + SSL struct { + CAFile string `json:"cafile,omitzero"` + } `json:"ssl,omitzero"` + } `json:"options,omitzero"` + } + + r := repo{ + Type: "composer", + URL: srvURL, + } + if caFile != "" { + r.Options.SSL.CAFile = caFile + } + + rb, err := json.Marshal(r) + if err != nil { + t.Fatalf("json.Marshal error: %v", err) + } + t.Logf("repo: %s", rb) testscript.Run(t, testscript.Params{ Dir: "testdata", @@ -27,7 +55,7 @@ func TestScripts(t *testing.T) { "COMPOSER_NO_AUDIT=true", "COMPOSER_NO_SECURITY_BLOCKING=true", "COMPOSER_ROOT_VERSION=0.0.1", - "WPSECADV_SERVER_URL="+srvURL, + "REPO="+string(rb), ) dir := os.Getenv("TESTSCRIPT_COMPOSER_CACHE_DIR") diff --git a/e2e/scripts/testdata/any_vendor_twentyfifteen.txtar b/e2e/scripts/testdata/any_vendor_twentyfifteen.txtar index 57c4d303..091f647f 100644 --- a/e2e/scripts/testdata/any_vendor_twentyfifteen.txtar +++ b/e2e/scripts/testdata/any_vendor_twentyfifteen.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2015-3429 diff --git a/e2e/scripts/testdata/any_vendor_woocommerce.txtar b/e2e/scripts/testdata/any_vendor_woocommerce.txtar index bc7bf3c2..4c9cdf1b 100644 --- a/e2e/scripts/testdata/any_vendor_woocommerce.txtar +++ b/e2e/scripts/testdata/any_vendor_woocommerce.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2025-15033 diff --git a/e2e/scripts/testdata/bedrock_append.txtar b/e2e/scripts/testdata/bedrock_append.txtar index 2d80ff7b..9cc85866 100644 --- a/e2e/scripts/testdata/bedrock_append.txtar +++ b/e2e/scripts/testdata/bedrock_append.txtar @@ -4,7 +4,7 @@ exec composer create-project --quiet --no-install roots/bedrock bedrock cd bedrock exec composer config --quiet secure-http false -exec composer repo --append add wpsecadv composer $WPSECADV_SERVER_URL +exec composer repo --append add wpsecadv $REPO exec composer require --quiet --no-install wp-plugin/woocommerce:10.0.0 diff --git a/e2e/scripts/testdata/bedrock_prepend.txtar b/e2e/scripts/testdata/bedrock_prepend.txtar index 60f96d15..696d18be 100644 --- a/e2e/scripts/testdata/bedrock_prepend.txtar +++ b/e2e/scripts/testdata/bedrock_prepend.txtar @@ -2,8 +2,8 @@ exec composer create-project --quiet --no-install roots/bedrock bedrock cd bedrock exec composer config --quiet secure-http false -[composer:2.9] exec composer repo add wpsecadv composer $WPSECADV_SERVER_URL -[!composer:2.9] exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +[composer:2.9] exec composer repo add wpsecadv ${REPO} +[!composer:2.9] exec composer config --quiet repositories.wpsecadv ${REPO} exec composer require --quiet --no-install wp-plugin/woocommerce:10.0.0 diff --git a/e2e/scripts/testdata/johnpbloch_wordpress_core.txtar b/e2e/scripts/testdata/johnpbloch_wordpress_core.txtar index d51801ba..c50b1fee 100644 --- a/e2e/scripts/testdata/johnpbloch_wordpress_core.txtar +++ b/e2e/scripts/testdata/johnpbloch_wordpress_core.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2017-14990 diff --git a/e2e/scripts/testdata/multiple_core.txtar b/e2e/scripts/testdata/multiple_core.txtar index 88388e35..f068542e 100644 --- a/e2e/scripts/testdata/multiple_core.txtar +++ b/e2e/scripts/testdata/multiple_core.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout -count=2 '"cve": "CVE-2025-58674"' diff --git a/e2e/scripts/testdata/notexist_cases.txtar b/e2e/scripts/testdata/notexist_cases.txtar index 2e087d91..e7dd55d6 100644 --- a/e2e/scripts/testdata/notexist_cases.txtar +++ b/e2e/scripts/testdata/notexist_cases.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet exec composer audit --format=json cmp stdout stdout.golden diff --git a/e2e/scripts/testdata/roots_wordpress_full.txtar b/e2e/scripts/testdata/roots_wordpress_full.txtar index f4068428..f2365344 100644 --- a/e2e/scripts/testdata/roots_wordpress_full.txtar +++ b/e2e/scripts/testdata/roots_wordpress_full.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2017-14990 diff --git a/e2e/scripts/testdata/roots_wordpress_no_content.txtar b/e2e/scripts/testdata/roots_wordpress_no_content.txtar index 420a6372..13621360 100644 --- a/e2e/scripts/testdata/roots_wordpress_no_content.txtar +++ b/e2e/scripts/testdata/roots_wordpress_no_content.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2017-14990 diff --git a/e2e/scripts/testdata/wp_core_wordpress.txtar b/e2e/scripts/testdata/wp_core_wordpress.txtar index 592829e6..e3ebb9fe 100644 --- a/e2e/scripts/testdata/wp_core_wordpress.txtar +++ b/e2e/scripts/testdata/wp_core_wordpress.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2017-14990 diff --git a/e2e/scripts/testdata/wp_core_wordpress_no_content.txtar b/e2e/scripts/testdata/wp_core_wordpress_no_content.txtar index 78e6f1c3..0a7513cd 100644 --- a/e2e/scripts/testdata/wp_core_wordpress_no_content.txtar +++ b/e2e/scripts/testdata/wp_core_wordpress_no_content.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2017-14990 diff --git a/e2e/scripts/testdata/wpackagist_plugin_woocommerce.txtar b/e2e/scripts/testdata/wpackagist_plugin_woocommerce.txtar index d968692d..f0679cf2 100644 --- a/e2e/scripts/testdata/wpackagist_plugin_woocommerce.txtar +++ b/e2e/scripts/testdata/wpackagist_plugin_woocommerce.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2025-15033 diff --git a/e2e/scripts/testdata/wpackagist_theme_twentyfifteen.txtar b/e2e/scripts/testdata/wpackagist_theme_twentyfifteen.txtar index 974b5fcf..440ef954 100644 --- a/e2e/scripts/testdata/wpackagist_theme_twentyfifteen.txtar +++ b/e2e/scripts/testdata/wpackagist_theme_twentyfifteen.txtar @@ -1,4 +1,4 @@ -exec composer config --quiet repositories.wpsecadv composer $WPSECADV_SERVER_URL +exec composer config --quiet repositories.wpsecadv ${REPO} exec composer update --quiet ! exec composer audit --format=json stdout CVE-2015-3429 diff --git a/mise.toml b/mise.toml index 2c4b76d7..b331b1a5 100644 --- a/mise.toml +++ b/mise.toml @@ -1,30 +1,31 @@ +[tools] +golangci-lint = "2.12" # Must be kept in sync with .github/workflows/lint.yml +"npm:portless" = "latest" +"npm:serve" = "latest" + [env] GOEXPERIMENT = "jsonv2" DOCKER = "docker" -[tools] -# Must be kept in sync with .github/workflows/lint.yml -golangci-lint = "2.12" - [tasks.upgrade] run = [ - 'mise upgrade --bump --local', - 'go get -u -t -tags e2econtainer,e2escripts ./...', - 'go mod tidy', + 'mise upgrade --bump --local', + 'go get -u -t -tags e2econtainer,e2escripts ./...', + 'go mod tidy', ] [tasks.serve] -env.PORT = { value="{{ get_env(name='PORT', default='8080') }}" } -depends = [{ task = "port:check", args = ["{{ get_env(name='PORT', default='8080') }}"] }] -run = 'go run ./cmd/serve' +run = 'portless run -- go run ./cmd/serve' [tasks.image] -env.PORT = { value="{{ get_env(name='PORT', default='8080') }}" } -depends = [ - { task = "port:check", args = ["{{ get_env(name='PORT', default='8080') }}"] }, - { task = "image:build" }, -] -run = '${DOCKER} run --rm -p {{ env.PORT }}:8080 wpsecadv-dev' +depends = [{ task = "image:build" }] +run = ''' +#!/usr/bin/env bash +set -e +app_port=($RANDOM + 65535 - 32767) + +portless run --app-port "${app_port}" -- "${DOCKER}" run --rm -p "${app_port}:8080" wpsecadv-dev +''' [tasks."image:build"] run = ''' @@ -65,34 +66,43 @@ go test -tags=e2econtainer -count=1 -shuffle=on ./e2e/container/... $@ ''' [tasks."test:e2e:local"] -env.PORT = { value="{{ get_env(name='E2E_PORT', default='8081') }}" } -depends = [{ task = "port:check", args = ["{{ get_env(name='E2E_PORT', default='8081') }}"] }] -depends_post = [{ task = "port:terminate", args = ["{{ get_env(name='E2E_PORT', default='8081') }}"] }] run = ''' #!/usr/bin/env bash set -e export TESTSCRIPT_COMPOSER_CACHE_DIR="$(composer global config cache-dir --absolute --quiet)" -export WPSECADV_SERVER_URL="http://localhost:${PORT}" +export TESTSCRIPT_COMPOSER_CAFILE="$HOME/.portless/ca.pem" + +name="wpsecadv-e2e-local" -echo "==> Starting server on '"${WPSECADV_SERVER_URL}"' in the background..." -go run ./cmd/serve > /dev/null 2>&1 & +echo "==> Starting server in the background..." +portless run --name "${name}" -- go run ./cmd/serve > /dev/null 2>&1 & +pid=$! -echo "==> Waiting for server ready..." -curl --silent --out-null -X GET --retry 10 --retry-connrefused --retry-delay 1 "${WPSECADV_SERVER_URL}" +cleanup () { + echo "==> Cleaning up..." + echo "Terminating the server (pid: '"${pid}"')..." + kill -9 "${pid}" || true +} +trap 'cleanup' EXIT + +export WPSECADV_SERVER_URL=$(portless get "${name}") + +echo "==> Waiting for server '"${WPSECADV_SERVER_URL}/packages.json"' ready..." +curl --silent --out-null -X GET --fail --retry 10 --retry-all-errors --retry-connrefused --retry-delay 1 "${WPSECADV_SERVER_URL}/packages.json" echo "==> Running e2e tests with system composer. This could take a while..." go test -tags=e2escripts -count=1 -shuffle=on ./e2e/scripts/... $@ ''' [tasks."test:e2e:prod"] -env.WPSECADV_SERVER_URL = { value="{{ get_env(name='WPSECADV_SERVER_URL', default='https://repo-wpsecadv.typist.tech') }}" } +env.WPSECADV_SERVER_URL = { value = "{{ get_env(name='WPSECADV_SERVER_URL', default='https://repo-wpsecadv.typist.tech') }}" } run = ''' #!/usr/bin/env bash set -e -echo "==> Waiting for server '"${WPSECADV_SERVER_URL}"' ready..." -curl --silent --out-null -X GET --retry 10 --retry-connrefused --retry-delay 1 "${WPSECADV_SERVER_URL}" +echo "==> Waiting for server '"${WPSECADV_SERVER_URL}/packages.json"' ready..." +curl --silent --out-null -X GET --fail --retry 10 --retry-all-errors --retry-connrefused --retry-delay 1 "${WPSECADV_SERVER_URL}/packages.json" echo "==> Running e2e tests with system composer. This could take a while..." go test -tags=e2escripts -count=1 -shuffle=on ./e2e/scripts/... $@ @@ -105,7 +115,10 @@ go test -tags=e2escripts -count=1 -shuffle=on ./e2e/scripts/... $@ #################################### [tasks.lint] -run = 'golangci-lint run' +run = [ + 'go mod tidy -diff', + 'golangci-lint run', +] [tasks.fmt] run = 'golangci-lint fmt' @@ -122,9 +135,6 @@ run = 'go generate ./...' [tasks."gen:data:fixture"] env.FEED_FIXTURE = { required = true } -env.PORT = { value="{{ get_env(name='FIXTURE_PORT', default='8082') }}" } -depends = [{ task = "port:check", args = ["{{ get_env(name='FIXTURE_PORT', default='8082') }}"] }] -depends_post = [{ task = "port:terminate", args = ["{{ get_env(name='FIXTURE_PORT', default='8082') }}"] }] run = ''' #!/usr/bin/env bash set -e @@ -132,13 +142,24 @@ set -e export WORDFENCE_INTELLIGENCE_API_KEY="dummy" export FEED_FIXTURE_DIR=$(dirname "${FEED_FIXTURE}") export FEED_FIXTURE_BASENAME=$(basename "${FEED_FIXTURE}") -export WORDFENCE_FEED_URL="http://localhost:${PORT}/${FEED_FIXTURE_BASENAME}" -echo "==> Starting fixture server for '${FEED_FIXTURE}' on port ${PORT}..." -npx --yes serve "${FEED_FIXTURE_DIR}" -p "${PORT}" > /dev/null 2>&1 & +name="wpsecadv-gen-data-fixture" + +echo "==> Starting server in the background..." +portless run --name "${name}" -- serve "${FEED_FIXTURE_DIR}" > /dev/null 2>&1 & +pid=$! + +cleanup () { + echo "==> Cleaning up..." + echo "Terminating the server (pid: '"${pid}"')..." + kill -9 "${pid}" || true +} +trap 'cleanup' EXIT + +export WORDFENCE_FEED_URL="$(portless get "${name}")/${FEED_FIXTURE_BASENAME}" echo "==> Waiting for server '"${WORDFENCE_FEED_URL}"' ready..." -curl --silent --out-null -X GET --retry 10 --retry-connrefused --retry-delay 1 "${WORDFENCE_FEED_URL}" +curl --silent --out-null -X GET --fail --retry 10 --retry-all-errors --retry-connrefused --retry-delay 1 "${WORDFENCE_FEED_URL}" echo "==> Generating data from fixture..." go generate ./internal/data $@ @@ -152,9 +173,9 @@ depends = ["clean:*"] [tasks."clean:data"] run = [ - 'rm -rf internal/data/assets', - 'rm -rf internal/data/assets_gen.go', - 'rm -rf internal/data/assets_gen_test.go', + 'rm -rf internal/data/assets', + 'rm -rf internal/data/assets_gen.go', + 'rm -rf internal/data/assets_gen_test.go', ] [tasks."clean:packagist"] @@ -162,58 +183,3 @@ run = 'rm -rf internal/packagist/core_gen.go' [tasks."clean:test"] run = 'rm -rf _artifacts' - -#################################### -# -# Utility -# -#################################### - -[tasks."port:check"] -hide = true -usage = ''' -arg "" -''' -run = ''' -#!/usr/bin/env bash -set -e - -echo "==> Checking whether port '{{ usage.port }}' is being used..." -pid=$(lsof -t -i ":{{ usage.port }}") || true - -if [[ ! -z "${pid}" ]]; then - echo "Process '"${pid}"' is using port '{{ usage.port }}'" - echo "To terminate that process, run:" - echo "" - echo " mise run port:terminate {{ usage.port }}" - echo "" - echo "To forcefully kill that process, run:" - echo "" - echo " kill -9 "${pid}"" - echo "" - exit 1 -fi - -echo "No process is using port '{{ usage.port }}'." -''' - -[tasks."port:terminate"] -hide = true -usage = ''' -arg "" -''' -run = ''' -#!/usr/bin/env bash -set -e - -echo "==> Checking whether port '{{ usage.port }}' is being used..." -pid=$(lsof -t -i ":{{ usage.port }}") || true - -if [[ -z "${pid}" ]]; then - echo "No process is using port '{{ usage.port }}'." - exit 0 -fi - -echo "==> Terminating the server (pid: '"${pid}"') using port '{{ usage.port }}'..." -kill -15 "${pid}" -'''