From a4376e2ce8d45f690702d9deb1e3e1951ea6b7f7 Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 20 Aug 2026 16:20:35 +0800 Subject: [PATCH 1/6] ci: add GitLab end-to-end testing --- .github/workflows/gitlab-e2e.yml | 197 +++++++++++++++++++++++++++++++ README.md | 6 +- 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/gitlab-e2e.yml diff --git a/.github/workflows/gitlab-e2e.yml b/.github/workflows/gitlab-e2e.yml new file mode 100644 index 0000000..20accb4 --- /dev/null +++ b/.github/workflows/gitlab-e2e.yml @@ -0,0 +1,197 @@ +name: GitLab E2E + +on: + push: + branches: [main] + tags: ["v*"] + pull_request: + branches: [main] + merge_group: + schedule: + - cron: "23 3 * * 0" + workflow_dispatch: + inputs: + setup_ref: + description: "Exact setup-vp commit SHA or release tag. Defaults to this workflow commit." + required: false + default: "" + suite: + description: "GitLab test coverage to run." + type: choice + options: [full, required] + default: full + vite_plus_version: + description: "Vite+ version or dist-tag to install." + required: false + default: latest + +permissions: + contents: read + pull-requests: read + +jobs: + gitlab-e2e: + name: GitLab E2E + runs-on: ubuntu-latest + timeout-minutes: 35 + steps: + - name: Resolve test parameters + id: parameters + env: + EVENT_NAME: ${{ github.event_name }} + EVENT_REF: ${{ github.ref }} + EVENT_REF_NAME: ${{ github.ref_name }} + PR_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PR_NUMBER: ${{ github.event.pull_request.number }} + MANUAL_SETUP_REF: ${{ inputs.setup_ref }} + MANUAL_SUITE: ${{ inputs.suite }} + MANUAL_VITE_PLUS_VERSION: ${{ inputs.vite_plus_version }} + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + should_run=true + setup_vp_ref="$GITHUB_SHA" + suite=required + vite_plus_version=latest + + if [ "$EVENT_NAME" = "pull_request" ]; then + if [ "$PR_HEAD_REPOSITORY" != "$GITHUB_REPOSITORY" ]; then + should_run=false + echo "Fork pull requests are tested after they enter the merge queue or through a maintainer-approved manual run." + else + setup_vp_ref="$PR_HEAD_SHA" + while IFS= read -r changed_path; do + case "$changed_path" in + gitlab/* | src/gitlab/* | src/ci/* | dist/gitlab/* | .github/workflows/gitlab-e2e.yml | vite.config.ts | package.json | pnpm-lock.yaml | pnpm-workspace.yaml) + suite=full + break + ;; + esac + done < <(gh api --paginate "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '.[].filename') + fi + elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then + setup_vp_ref="${MANUAL_SETUP_REF:-$GITHUB_SHA}" + suite="${MANUAL_SUITE:-full}" + vite_plus_version="${MANUAL_VITE_PLUS_VERSION:-latest}" + elif [ "$EVENT_NAME" = "push" ] && [[ "$EVENT_REF" == refs/tags/* ]]; then + setup_vp_ref="$EVENT_REF_NAME" + suite=full + elif [ "$EVENT_NAME" = "push" ] || [ "$EVENT_NAME" = "schedule" ]; then + suite=full + fi + + { + echo "should_run=$should_run" + echo "setup_vp_ref=$setup_vp_ref" + echo "suite=$suite" + echo "vite_plus_version=$vite_plus_version" + } >> "$GITHUB_OUTPUT" + + if [ "$should_run" = "false" ]; then + { + echo "### GitLab E2E" + echo + echo "Skipped for an untrusted fork pull request. The merge queue tests the reviewed merge commit." + } >> "$GITHUB_STEP_SUMMARY" + fi + + - name: Trigger GitLab pipeline + if: steps.parameters.outputs.should_run == 'true' + id: trigger + env: + GITLAB_PROJECT_ID: "85578524" + GITLAB_TRIGGER_TOKEN: ${{ secrets.GITLAB_TRIGGER_TOKEN }} + SETUP_VP_REF: ${{ steps.parameters.outputs.setup_vp_ref }} + TEST_SUITE: ${{ steps.parameters.outputs.suite }} + VITE_PLUS_VERSION: ${{ steps.parameters.outputs.vite_plus_version }} + run: | + set -euo pipefail + + if [ -z "$GITLAB_TRIGGER_TOKEN" ]; then + echo "::error::The GITLAB_TRIGGER_TOKEN repository secret is not configured." + exit 1 + fi + + response="$(curl --silent --show-error --fail-with-body \ + --request POST \ + --form-string "token=$GITLAB_TRIGGER_TOKEN" \ + --form-string "ref=main" \ + --form-string "inputs[setup_vp_ref]=$SETUP_VP_REF" \ + --form-string "inputs[suite]=$TEST_SUITE" \ + --form-string "inputs[vite_plus_version]=$VITE_PLUS_VERSION" \ + "https://gitlab.com/api/v4/projects/${GITLAB_PROJECT_ID}/trigger/pipeline")" + + pipeline_id="$(jq -er '.id' <<< "$response")" + pipeline_url="$(jq -er '.web_url' <<< "$response")" + echo "Triggered GitLab pipeline: $pipeline_url" + + { + echo "pipeline_id=$pipeline_id" + echo "pipeline_url=$pipeline_url" + } >> "$GITHUB_OUTPUT" + + { + echo "### GitLab E2E" + echo + echo "- Pipeline: [$pipeline_id]($pipeline_url)" + echo "- setup-vp ref: \`$SETUP_VP_REF\`" + echo "- Suite: \`$TEST_SUITE\`" + echo "- Vite+ version: \`$VITE_PLUS_VERSION\`" + } >> "$GITHUB_STEP_SUMMARY" + + - name: Wait for GitLab pipeline + if: steps.parameters.outputs.should_run == 'true' + env: + GITLAB_PROJECT_ID: "85578524" + GITLAB_PIPELINE_ID: ${{ steps.trigger.outputs.pipeline_id }} + GITLAB_PIPELINE_URL: ${{ steps.trigger.outputs.pipeline_url }} + run: | + set -euo pipefail + + api_url="https://gitlab.com/api/v4/projects/${GITLAB_PROJECT_ID}/pipelines/${GITLAB_PIPELINE_ID}" + deadline=$((SECONDS + 1800)) + previous_status="" + final_status="timed_out" + + while [ "$SECONDS" -lt "$deadline" ]; do + if payload="$(curl --silent --show-error --fail --retry 3 --retry-delay 2 "$api_url")"; then + status="$(jq -er '.status' <<< "$payload")" + if [ "$status" != "$previous_status" ]; then + echo "GitLab pipeline status: $status" + previous_status="$status" + fi + + case "$status" in + success) + final_status=success + break + ;; + failed | canceled | skipped | manual) + final_status="$status" + break + ;; + esac + else + echo "Could not read the GitLab pipeline status; retrying." + fi + sleep 10 + done + + { + echo "- Result: \`$final_status\`" + } >> "$GITHUB_STEP_SUMMARY" + + if [ "$final_status" = "success" ]; then + echo "GitLab pipeline passed: $GITLAB_PIPELINE_URL" + exit 0 + fi + + echo "GitLab pipeline did not pass: $GITLAB_PIPELINE_URL" + jobs_url="https://gitlab.com/api/v4/projects/${GITLAB_PROJECT_ID}/pipelines/${GITLAB_PIPELINE_ID}/jobs?per_page=100" + if jobs="$(curl --silent --show-error --fail --retry 3 --retry-delay 2 "$jobs_url")"; then + jq -r 'sort_by(.name)[] | "\(.status)\t\(.name)\t\(.web_url)"' <<< "$jobs" + fi + echo "::error::GitLab pipeline finished with status $final_status." + exit 1 diff --git a/README.md b/README.md index c2e1c21..0e51e2d 100644 --- a/README.md +++ b/README.md @@ -384,6 +384,8 @@ setup-vp also provides a GitLab CI/CD remote template hosted from this GitHub re See [GitLab integration notes](rfcs/gitlab-integration.md) for the design background, constraints, and follow-up work. +Every setup-vp pull request, merge, and release is exercised by the dedicated [GitLab end-to-end test project](https://gitlab.com/fengmk2/setup-vp-gitlab-test). The test pipeline loads the template, bootstrap, and compiled runtime from the exact setup-vp commit or release tag under test. + ### Basic GitLab Usage Use an exact release tag in the `include:remote` URL, and pin `setup-ref` to the same tag so the bootstrap and compiled runtime are downloaded from the same version as the included template: @@ -668,7 +670,9 @@ To cut a release: git status --short # must be empty ``` -3. Create the new annotated version tag and push it. For example: +3. Confirm that the full GitLab E2E workflow passed for the release commit on `main`. + +4. Create the new annotated version tag and push it. For example: ```bash git tag -a v1.17.0 -m "v1.17.0" From 7d647607b0636bf69615cd789adcb73a07a8097d Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 20 Aug 2026 16:28:43 +0800 Subject: [PATCH 2/6] fix: support Alpine runtime temp files --- gitlab/bootstrap.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gitlab/bootstrap.sh b/gitlab/bootstrap.sh index 82fd2c5..f574d4f 100644 --- a/gitlab/bootstrap.sh +++ b/gitlab/bootstrap.sh @@ -133,8 +133,9 @@ elif [[ "$SETUP_VP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; th setup_vp_pinned_ref="v${SETUP_VP_VERSION}" fi setup_vp_install_tmp="$(mktemp "${TMPDIR:-/tmp}/setup-vp-install.XXXXXX")" -setup_vp_runtime_tmp="$(mktemp "${TMPDIR:-/tmp}/setup-vp-gitlab-runtime.XXXXXX.mjs")" -trap 'rm -f "$setup_vp_install_tmp" "$setup_vp_runtime_tmp"' EXIT +setup_vp_runtime_dir="$(mktemp -d "${TMPDIR:-/tmp}/setup-vp-gitlab-runtime.XXXXXX")" +setup_vp_runtime_tmp="${setup_vp_runtime_dir}/index.mjs" +trap 'rm -f "$setup_vp_install_tmp" "$setup_vp_runtime_tmp"; rmdir "$setup_vp_runtime_dir" 2>/dev/null || true' EXIT setup_vp_install_viteplus export PATH="$HOME/.vite-plus/bin:$PATH" From 40ed742411c1e758184a3b9e7049b48bb3e086a1 Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 20 Aug 2026 16:56:06 +0800 Subject: [PATCH 3/6] ci: simplify GitLab end-to-end workflow --- .github/workflows/gitlab-e2e.yml | 16 +++++++--------- README.md | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gitlab-e2e.yml b/.github/workflows/gitlab-e2e.yml index 20accb4..f607eb3 100644 --- a/.github/workflows/gitlab-e2e.yml +++ b/.github/workflows/gitlab-e2e.yml @@ -7,16 +7,14 @@ on: pull_request: branches: [main] merge_group: - schedule: - - cron: "23 3 * * 0" workflow_dispatch: inputs: setup_ref: - description: "Exact setup-vp commit SHA or release tag. Defaults to this workflow commit." + description: "Enter an exact setup-vp commit SHA or release tag. If empty, the workflow uses this commit." required: false default: "" suite: - description: "GitLab test coverage to run." + description: "Select the GitLab test suite." type: choice options: [full, required] default: full @@ -59,7 +57,7 @@ jobs: if [ "$EVENT_NAME" = "pull_request" ]; then if [ "$PR_HEAD_REPOSITORY" != "$GITHUB_REPOSITORY" ]; then should_run=false - echo "Fork pull requests are tested after they enter the merge queue or through a maintainer-approved manual run." + echo "The workflow skips fork pull requests. The merge queue or a maintainer can test these changes." else setup_vp_ref="$PR_HEAD_SHA" while IFS= read -r changed_path; do @@ -78,7 +76,7 @@ jobs: elif [ "$EVENT_NAME" = "push" ] && [[ "$EVENT_REF" == refs/tags/* ]]; then setup_vp_ref="$EVENT_REF_NAME" suite=full - elif [ "$EVENT_NAME" = "push" ] || [ "$EVENT_NAME" = "schedule" ]; then + elif [ "$EVENT_NAME" = "push" ]; then suite=full fi @@ -93,7 +91,7 @@ jobs: { echo "### GitLab E2E" echo - echo "Skipped for an untrusted fork pull request. The merge queue tests the reviewed merge commit." + echo "The workflow skipped this fork pull request. The merge queue tests the reviewed merge commit." } >> "$GITHUB_STEP_SUMMARY" fi @@ -110,7 +108,7 @@ jobs: set -euo pipefail if [ -z "$GITLAB_TRIGGER_TOKEN" ]; then - echo "::error::The GITLAB_TRIGGER_TOKEN repository secret is not configured." + echo "::error::This repository does not have the GITLAB_TRIGGER_TOKEN secret." exit 1 fi @@ -174,7 +172,7 @@ jobs: ;; esac else - echo "Could not read the GitLab pipeline status; retrying." + echo "The workflow could not read the GitLab pipeline status. It will try again." fi sleep 10 done diff --git a/README.md b/README.md index 0e51e2d..7f5ecc7 100644 --- a/README.md +++ b/README.md @@ -384,7 +384,7 @@ setup-vp also provides a GitLab CI/CD remote template hosted from this GitHub re See [GitLab integration notes](rfcs/gitlab-integration.md) for the design background, constraints, and follow-up work. -Every setup-vp pull request, merge, and release is exercised by the dedicated [GitLab end-to-end test project](https://gitlab.com/fengmk2/setup-vp-gitlab-test). The test pipeline loads the template, bootstrap, and compiled runtime from the exact setup-vp commit or release tag under test. +The dedicated [GitLab end-to-end test project](https://gitlab.com/fengmk2/setup-vp-gitlab-test) tests each setup-vp pull request, merge, and release. The pipeline loads the template, bootstrap script, and compiled runtime from the exact setup-vp commit or release tag that it tests. ### Basic GitLab Usage @@ -670,7 +670,7 @@ To cut a release: git status --short # must be empty ``` -3. Confirm that the full GitLab E2E workflow passed for the release commit on `main`. +3. Confirm that the release commit on `main` passes the full GitLab E2E workflow. 4. Create the new annotated version tag and push it. For example: From b2f141704e1f09b45948ec2044477bb84f975fd5 Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 20 Aug 2026 19:40:27 +0800 Subject: [PATCH 4/6] test: preserve action identity for preview builds --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 39d30bc..b9f35eb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -71,8 +71,10 @@ jobs: echo "Resolved preview build: ${version}" echo "version=${version}" >> "$GITHUB_OUTPUT" + # The self-repository reference gives the action its repository identity. + # The preview installer uses that identity for legacy path compatibility. - name: Setup Vite+ - uses: ./ + uses: $/. with: version: ${{ steps.preview.outputs.version }} run-install: false From f432aa425b03f44714e7771b3215eddef61e25b9 Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 20 Aug 2026 19:50:55 +0800 Subject: [PATCH 5/6] test: run preview build on macOS --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b9f35eb..aa76e48 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,7 +49,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} # The version assertion below must see the bridge-resolved build. Pin # VP_PR_VERSION to "" so a manual pr_version dispatch can't override it. From cf0b527892b4e27a8099ab4166ba6ba75577d461 Mon Sep 17 00:00:00 2001 From: MK Date: Thu, 20 Aug 2026 19:57:05 +0800 Subject: [PATCH 6/6] ci: run full GitLab suite in merge queue --- .github/workflows/gitlab-e2e.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/gitlab-e2e.yml b/.github/workflows/gitlab-e2e.yml index f607eb3..57b4ad7 100644 --- a/.github/workflows/gitlab-e2e.yml +++ b/.github/workflows/gitlab-e2e.yml @@ -69,6 +69,8 @@ jobs: esac done < <(gh api --paginate "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '.[].filename') fi + elif [ "$EVENT_NAME" = "merge_group" ]; then + suite=full elif [ "$EVENT_NAME" = "workflow_dispatch" ]; then setup_vp_ref="${MANUAL_SETUP_REF:-$GITHUB_SHA}" suite="${MANUAL_SUITE:-full}"