Repository navigation
feat: add package-manager environment configuration #65
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: GitLab E2E | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| workflow_run: | |
| workflows: [GitLab E2E request] | |
| types: [completed] | |
| merge_group: | |
| workflow_dispatch: | |
| inputs: | |
| setup_ref: | |
| description: "Enter an exact setup-vp commit SHA or release tag. If empty, the workflow uses this commit." | |
| required: false | |
| default: "" | |
| suite: | |
| description: "Select the GitLab test suite." | |
| 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 | |
| if: >- | |
| github.event_name != 'workflow_run' || | |
| (github.event.workflow_run.event == 'pull_request' && | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.path == '.github/workflows/e2e-request.yml' && | |
| github.event.workflow_run.head_repository.full_name != github.repository) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 35 | |
| # Keep this privileged job API-only: no PR checkout, artifacts, or caches. | |
| steps: | |
| - name: Resolve test parameters | |
| id: parameters | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| EVENT_REF: ${{ github.ref }} | |
| EVENT_REF_NAME: ${{ github.ref_name }} | |
| REQUEST_EVENT: ${{ github.event.workflow_run.event }} | |
| REQUEST_CONCLUSION: ${{ github.event.workflow_run.conclusion }} | |
| REQUEST_PATH: ${{ github.event.workflow_run.path }} | |
| REQUEST_TITLE: ${{ github.event.workflow_run.display_title }} | |
| REQUEST_ACTOR: ${{ github.event.workflow_run.actor.login }} | |
| REQUEST_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| REQUEST_HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_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 | |
| skip_reason="" | |
| resolve_fork_request() { | |
| should_run=false | |
| skip_reason='Only a successful run-e2e label request for a fork PR can approve a GitLab E2E run.' | |
| local request_pattern='^PR #([1-9][0-9]*): labeled run-e2e at ([0-9a-f]{40})$' | |
| if [ "$REQUEST_EVENT" != "pull_request" ] || [ "$REQUEST_CONCLUSION" != "success" ] || | |
| [ "$REQUEST_PATH" != ".github/workflows/e2e-request.yml" ] || | |
| [ "$REQUEST_HEAD_REPOSITORY" = "$GITHUB_REPOSITORY" ] || | |
| ! [[ "$REQUEST_TITLE" =~ $request_pattern ]]; then | |
| return | |
| fi | |
| local pr_number="${BASH_REMATCH[1]}" | |
| if [ "${BASH_REMATCH[2]}" != "$REQUEST_HEAD_SHA" ]; then | |
| echo "::error::The request title does not match the workflow run's head SHA." | |
| exit 1 | |
| fi | |
| # Check the original labeler's access, even on reruns. | |
| # GitHub maps the maintain role to write. | |
| local permission | |
| permission="$(gh api "repos/${GITHUB_REPOSITORY}/collaborators/${REQUEST_ACTOR}/permission" --jq '.permission')" | |
| case "$permission" in | |
| admin | write) ;; | |
| *) | |
| echo "::error::Adding run-e2e requires repository write access to approve a test run." | |
| exit 1 | |
| ;; | |
| esac | |
| # Compare Git blobs to reject altered request triggers or run names. | |
| local workflow_url="repos/${GITHUB_REPOSITORY}/contents/${REQUEST_PATH}" | |
| local trusted_blob request_blob | |
| trusted_blob="$(gh api "${workflow_url}?ref=${GITHUB_SHA}" --jq '.sha')" | |
| if ! request_blob="$(gh api "${workflow_url}?ref=${REQUEST_HEAD_SHA}" --jq '.sha')" || | |
| [ "$request_blob" != "$trusted_blob" ]; then | |
| echo "::error::The fork must include e2e-request.yml unchanged from main. Update the branch, then remove and re-add run-e2e." | |
| exit 1 | |
| fi | |
| # Fork runs can have an empty workflow_run.pull_requests array. | |
| # Resolve the PR from the verified title and cross-check its head. | |
| local pull_request | |
| pull_request="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${pr_number}")" | |
| if ! jq -e --arg sha "$REQUEST_HEAD_SHA" --arg head_repo "$REQUEST_HEAD_REPOSITORY" --arg repo "$GITHUB_REPOSITORY" \ | |
| '.state == "open" and .head.sha == $sha and .head.repo.full_name == $head_repo and | |
| .base.repo.full_name == $repo and .base.ref == "main" and any(.labels[]; .name == "run-e2e")' \ | |
| <<< "$pull_request" > /dev/null; then | |
| skip_reason='This approval is stale or does not match the PR: check its head, base, and run-e2e label. Review the current commit, then remove and re-add run-e2e to test it.' | |
| return | |
| fi | |
| should_run=true | |
| setup_vp_ref="$REQUEST_HEAD_SHA" | |
| suite=full | |
| } | |
| if [ "$EVENT_NAME" = "pull_request" ]; then | |
| if [ "$PR_HEAD_REPOSITORY" != "$GITHUB_REPOSITORY" ]; then | |
| should_run=false | |
| skip_reason='A maintainer with write access can review this fork PR and add the run-e2e label to test its current commit. New commits require removing and re-adding the label. The merge queue also tests the reviewed merge commit.' | |
| 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_run" ]; then | |
| resolve_fork_request | |
| 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}" | |
| 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" ]; 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 "$skip_reason" | |
| { | |
| echo "### GitLab E2E" | |
| echo | |
| echo "$skip_reason" | |
| } >> "$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::This repository does not have the GITLAB_TRIGGER_TOKEN secret." | |
| 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 "The workflow could not read the GitLab pipeline status. It will try again." | |
| 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 |