diff --git a/.github/actions/report-fork-status/action.yml b/.github/actions/report-fork-status/action.yml deleted file mode 100644 index 37cbe39..0000000 --- a/.github/actions/report-fork-status/action.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Report fork PR integration test status -description: Post a GitHub commit status for a single job back to a fork PR head SHA - -inputs: - pr_ref: - description: 'SHA of the fork PR head commit' - required: true - name: - description: 'Status context name (job name)' - required: true - -runs: - using: composite - steps: - - name: Post commit status - shell: bash - env: - GH_TOKEN: ${{ github.token }} - run: | - case "${{ job.status }}" in - success) state="success" ;; - cancelled|timed_out) state="error" ;; - skipped) exit 0 ;; - *) state="failure" ;; - esac - echo "report-fork-status: name/context='${{ inputs.name }}' pr_ref=${{ inputs.pr_ref }} state=$state" - gh api --method POST "repos/${{ github.repository }}/statuses/${{ inputs.pr_ref }}" \ - -f state="$state" \ - -f context="${{ inputs.name }}" \ - -f target_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - -f description="${{ job.status }}" diff --git a/.github/workflows/alioss-integration.yml b/.github/workflows/alioss-integration.yml index 6cfea95..da8e619 100644 --- a/.github/workflows/alioss-integration.yml +++ b/.github/workflows/alioss-integration.yml @@ -2,36 +2,38 @@ name: Alioss Integration Tests on: workflow_dispatch: - inputs: - pr_ref: - description: 'SHA of the PR head commit (for fork PRs)' - required: false - default: '' - pull_request: + workflow_call: + pull_request_target: push: branches: - main - workflow_call: concurrency: group: alioss-integration cancel-in-progress: false jobs: - alioss-general-integration-tests: - name: Alioss General Integration Tests + gate: + name: Approval gate (fork PRs only) runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + github.event_name == 'pull_request_target' && + github.event.pull_request.head.repo.full_name != github.repository + environment: fork-pr-integration-test + steps: + - run: echo "Fork PR approved, proceeding with integration tests" + + alioss-general-integration-tests: + name: Alioss General Integration Tests + runs-on: ubuntu-latest + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') steps: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up Go uses: actions/setup-go@v7 with: @@ -56,9 +58,3 @@ jobs: export access_key_id="${{ secrets.ALI_ACCESS_KEY_ID }}" export access_key_secret="${{ secrets.ALI_ACCESS_KEY_SECRET }}" ./.github/scripts/alioss/teardown.sh - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: Alioss General Integration Tests diff --git a/.github/workflows/azurebs-integration.yml b/.github/workflows/azurebs-integration.yml index d571f2f..9aa3a31 100644 --- a/.github/workflows/azurebs-integration.yml +++ b/.github/workflows/azurebs-integration.yml @@ -2,36 +2,38 @@ name: Azurebs Integration Tests on: workflow_dispatch: - inputs: - pr_ref: - description: 'SHA of the PR head commit (for fork PRs)' - required: false - default: '' - pull_request: + workflow_call: + pull_request_target: push: branches: - main - workflow_call: concurrency: group: azurebs-integration cancel-in-progress: false jobs: - azurecloud-environment-integration-tests: - name: AzureCloud Environment Integration Tests + gate: + name: Approval gate (fork PRs only) runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + github.event_name == 'pull_request_target' && + github.event.pull_request.head.repo.full_name != github.repository + environment: fork-pr-integration-test + steps: + - run: echo "Fork PR approved, proceeding with integration tests" + + azurecloud-environment-integration-tests: + name: AzureCloud Environment Integration Tests + runs-on: ubuntu-latest + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') steps: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up Go uses: actions/setup-go@v7 with: @@ -54,9 +56,3 @@ jobs: export azure_storage_account="${{ secrets.AZURE_STORAGE_ACCOUNT }}" export azure_storage_key="${{ secrets.AZURE_STORAGE_KEY }}" ./.github/scripts/azurebs/teardown.sh - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: AzureCloud Environment Integration Tests diff --git a/.github/workflows/dav-integration.yml b/.github/workflows/dav-integration.yml index 2553d02..50ed31c 100644 --- a/.github/workflows/dav-integration.yml +++ b/.github/workflows/dav-integration.yml @@ -2,36 +2,38 @@ name: DAV Integration Tests on: workflow_dispatch: - inputs: - pr_ref: - description: 'SHA of the PR head commit (for fork PRs)' - required: false - default: '' - pull_request: + workflow_call: + pull_request_target: push: branches: - main - workflow_call: concurrency: group: dav-integration cancel-in-progress: false jobs: + gate: + name: Approval gate (fork PRs only) + runs-on: ubuntu-latest + if: > + github.event_name == 'pull_request_target' && + github.event.pull_request.head.repo.full_name != github.repository + environment: fork-pr-integration-test + steps: + - run: echo "Fork PR approved, proceeding with integration tests" + dav-integration: name: DAV Integration Tests runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) - if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') steps: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up Go uses: actions/setup-go@v7 @@ -43,10 +45,3 @@ jobs: - name: Run DAV Integration Tests run: ginkgo -r dav/integration/ - - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: DAV Integration Tests diff --git a/.github/workflows/fork-integration-trigger.yml b/.github/workflows/fork-integration-trigger.yml deleted file mode 100644 index 5bfc994..0000000 --- a/.github/workflows/fork-integration-trigger.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Trigger integration tests for fork PRs - -on: - issue_comment: - types: [created] - -permissions: - pull-requests: write - actions: write - -env: - GH_TOKEN: ${{ github.token }} - -jobs: - trigger: - name: Trigger integration tests - runs-on: ubuntu-latest - if: | - github.event.issue.pull_request != null && - contains(github.event.comment.body, '/run-integration') - steps: - - name: Check commenter has write permission - run: | - permission=$(gh api repos/$GITHUB_REPOSITORY/collaborators/${{ github.actor }}/permission --jq '.permission') - if [[ "$permission" != "write" && "$permission" != "admin" ]]; then - echo "${{ github.actor }} does not have write permission (got: $permission)" - exit 1 - fi - - - name: Get PR head SHA and check for fork - id: pr - run: | - pr=$(gh pr view ${{ github.event.issue.number }} --repo "$GITHUB_REPOSITORY" --json headRefOid,isCrossRepository) - read -r ref is_fork < <(echo "$pr" | jq -r '[.headRefOid, (.isCrossRepository | tostring)] | @tsv') - if [[ "$is_fork" == "false" ]]; then - echo "This command is only needed for fork PRs. Integration tests run automatically for PRs from this repository." - exit 1 - fi - echo "ref=$ref" >> $GITHUB_OUTPUT - - - name: Add reaction to comment - run: | - gh api --method POST \ - repos/$GITHUB_REPOSITORY/issues/comments/${{ github.event.comment.id }}/reactions \ - -f content=rocket - - - name: Trigger integration tests - run: | - # run all integration test workflows in context of main branch, passing the PR head SHA as an input - for workflow in s3-integration.yml gcs-integration.yml alioss-integration.yml azurebs-integration.yml dav-integration.yml; do - gh workflow run "$workflow" --repo "$GITHUB_REPOSITORY" --ref ${{ github.event.repository.default_branch }} -f pr_ref=${{ steps.pr.outputs.ref }} & - done - wait diff --git a/.github/workflows/gcs-integration.yml b/.github/workflows/gcs-integration.yml index e4dcdb8..f942aad 100644 --- a/.github/workflows/gcs-integration.yml +++ b/.github/workflows/gcs-integration.yml @@ -2,36 +2,38 @@ name: GCS Integration Tests on: workflow_dispatch: - inputs: - pr_ref: - description: 'SHA of the PR head commit (for fork PRs)' - required: false - default: '' - pull_request: + workflow_call: + pull_request_target: push: branches: - "main" - workflow_call: concurrency: group: gcs-integration cancel-in-progress: false jobs: - gcs-integration-fast-tests: - name: GCS Integation Fast Tests + gate: + name: Approval gate (fork PRs only) runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + github.event_name == 'pull_request_target' && + github.event.pull_request.head.repo.full_name != github.repository + environment: fork-pr-integration-test + steps: + - run: echo "Fork PR approved, proceeding with integration tests" + + gcs-integration-fast-tests: + name: GCS Integation Fast Tests + runs-on: ubuntu-latest + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') steps: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up Go uses: actions/setup-go@v7 with: @@ -55,27 +57,18 @@ jobs: echo "${{ secrets.GCP_SERVICE_ACCOUNT_BASE64 }}" | base64 -d > /tmp/gcp-key.json export google_json_key_data="$(cat /tmp/gcp-key.json)" ./.github/scripts/gcs/teardown.sh - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: GCS Integation Fast Tests gcs-integration-all-tests: - name: GCS Integation All Tests + name: GCS Integation All Tests runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) - if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') steps: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up Go uses: actions/setup-go@v7 with: @@ -98,9 +91,3 @@ jobs: echo "${{ secrets.GCP_SERVICE_ACCOUNT_BASE64 }}" | base64 -d > /tmp/gcp-key.json export google_json_key_data="$(cat /tmp/gcp-key.json)" ./.github/scripts/gcs/teardown.sh - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: GCS Integation All Tests diff --git a/.github/workflows/s3-integration.yml b/.github/workflows/s3-integration.yml index 72d1952..5be0132 100644 --- a/.github/workflows/s3-integration.yml +++ b/.github/workflows/s3-integration.yml @@ -2,31 +2,32 @@ name: S3 Integration Tests on: workflow_dispatch: - inputs: - pr_ref: - description: 'SHA of the PR head commit (for fork PRs)' - required: false - default: '' - pull_request: + workflow_call: + pull_request_target: push: branches: - main - workflow_call: concurrency: group: s3-integration cancel-in-progress: false jobs: + gate: + name: Approval gate (fork PRs only) + runs-on: ubuntu-latest + if: > + github.event_name == 'pull_request_target' && + github.event.pull_request.head.repo.full_name != github.repository + environment: fork-pr-integration-test + steps: + - run: echo "Fork PR approved, proceeding with integration tests" + aws-s3-us-integration: name: AWS S3 US Integration runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) - if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') env: REGION_NAME: us-east-1 STACK_NAME: s3cli-iam @@ -35,7 +36,8 @@ jobs: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up test environment uses: ./.github/actions/go-test-bootstrap @@ -47,7 +49,7 @@ jobs: secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} region_name: ${{ env.REGION_NAME }} stack_name: ${{ env.STACK_NAME }} - + - name: Test Static Credentials uses: ./.github/actions/s3-integration-run with: @@ -89,22 +91,11 @@ jobs: region_name: ${{ env.REGION_NAME }} stack_name: ${{ env.STACK_NAME }} - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: AWS S3 US Integration - aws-s3-regional-integration: name: AWS S3 ${{ matrix.name }} Integration runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) - if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') strategy: fail-fast: false matrix: @@ -131,7 +122,8 @@ jobs: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up test environment uses: ./.github/actions/go-test-bootstrap @@ -164,27 +156,17 @@ jobs: region_name: ${{ matrix.region_name }} stack_name: ${{ matrix.stack_name }} - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: AWS S3 ${{ matrix.name }} Integration - s3-compatible-integration: name: S3 Compatible Integration runs-on: ubuntu-latest - # Skip fork PRs; run for all other triggers (push, dispatch, workflow_call, schedule, etc.) - if: > - github.event_name != 'pull_request' || - github.event.pull_request.head.repo.full_name == github.repository - permissions: - statuses: write + needs: [gate] + if: always() && (needs.gate.result == 'success' || needs.gate.result == 'skipped') steps: - name: Checkout code uses: actions/checkout@v7 with: - ref: ${{ inputs.pr_ref || github.sha }} + ref: ${{ github.event.pull_request.head.sha || github.sha }} + allow-unsafe-pr-checkout: true - name: Set up test environment uses: ./.github/actions/go-test-bootstrap @@ -198,11 +180,3 @@ jobs: export s3_endpoint_port=443 export label_filter='s3-compatible' ./.github/scripts/s3/run-integration-s3-compat.sh - - - name: Report fork PR status - if: always() && inputs.pr_ref != '' - uses: ./.github/actions/report-fork-status - with: - pr_ref: ${{ inputs.pr_ref }} - name: S3 Compatible Integration - diff --git a/README.md b/README.md index 2df73d0..792084a 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Follow these steps to make a contribution to the project: ginkgo --race --skip-package=integration --cover -v -r ./... ``` - If you added or modified integration tests, to run them locally, follow the instructions in the provider-specific README (see [Providers](#providers) section) -- **Note:** Integration tests require access to cloud provider credentials and don't run on PRs from forks. Maintainers can trigger the integration tests. +- **Note:** Integration tests require access to cloud provider credentials. For fork PRs, a maintainer must approve the integration test run before they execute (see [Integration tests for fork PRs](#integration-tests-for-fork-prs)). - Push changes to your fork ``` bash git add . @@ -124,10 +124,10 @@ Follow these steps to make a contribution to the project: ### Integration tests for fork PRs -After reviewing a PR, maintainers can run integration tests for fork PRs by adding a comment `/run-integration` to the PR. +Integration tests run automatically for PRs from within this repository. For fork PRs, each push triggers the integration test workflows, but they pause at an approval gate before executing. > [!WARNING] -> @maintainers: Review the PR carefully before running the integration tests to avoid leaking of credentials. +> @maintainers: Review the PR diff carefully before approving the integration test run to avoid leaking credentials. Approve via the **"Review deployments"** button that appears on the PR's Checks tab. ## Dependency Updates