Skip to content
Open
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
90 changes: 81 additions & 9 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,57 @@ on:
- "test/testdata/**"

jobs:
# New Job: Checks permissions for PRs and outputs the result.
check-permissions:
name: Check PR author permissions
# This job only runs for pull_request_target events.
if: github.event_name == 'pull_request_target'
runs-on: ubuntu-latest
outputs:
granted: ${{ steps.permission_check.outputs.result }}
steps:
- name: Check user permissions
id: permission_check
uses: actions/github-script@v7
with:
result-encoding: string # Capture the script's return value as an output
script: |
const actor = context.payload.pull_request.user.login;

// Allow dependabot and other bots unconditionally.
if (actor.endsWith('[bot]')) {
core.info(`User @${actor} is a bot, allowing.`);
return 'true';
}

try {
const response = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: actor,
});

const permission = response.data.permission;
if (permission === 'admin' || permission === 'write') {
core.info(`βœ… User @${actor} has '${permission}' permission. Proceeding.`);
return 'true';
} else {
core.warning(`User @${actor} has '${permission}' permission. 'write' or 'admin' is required. Skipping E2E tests.`);
return 'false';
}
} catch (error) {
core.warning(`Could not verify permission for @${actor}. They might not be a collaborator. Error: ${error.message}`);
return 'false';
}

# Modified Job: Now depends on the check-permissions job.
e2e-tests:
# Run on schedule, unconditional workflow_dispatch,
# or pull_request_target if the actor has write/admin permissions.
needs: [check-permissions] # It depends on the result of the check.
# The job runs on schedule/dispatch, or on PRs if the check-permissions job granted access.
if: >
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request_target' && contains(fromJSON('["zakisk", "infernus01", "savitaashture", "chmouel", "vdemeester", "enarha", "aThorp96", "waveywaves", "mathur07", "dependabot[bot]"]'), github.event.pull_request.user.login))
(github.event_name == 'pull_request_target' && needs.check-permissions.outputs.granted == 'true')
concurrency:
group: ${{ github.workflow }}-${{ matrix.provider }}-${{ github.event.pull_request.number || github.ref_name }}
cancel-in-progress: true
Expand Down Expand Up @@ -68,10 +112,41 @@ jobs:
TEST_BITBUCKET_SERVER_USER: pipelines
TEST_BITBUCKET_SERVER_E2E_REPOSITORY: PAC/pac-e2e-tests
steps:
- name: Check user permissions (detailed)
id: check_perms
uses: actions/github-script@v7
with:
script: |
const actor = context.actor;
const { owner, repo } = context.repo;

try {
const response = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: actor,
});

const userPermission = response.data.permission;

if (userPermission === 'admin') {
core.info(`βœ… Permission check successful. User @${actor} is an ADMIN.`);
} else if (userPermission === 'write') {
core.info(`βœ… Permission check successful. User @${actor} has WRITE permission.`);
} else {
core.setFailed(`❌ Permission check failed. User @${actor} has '${userPermission}' permission, but 'write' or 'admin' is required to proceed.`);
}

} catch (error) {
core.setFailed(`Could not verify permission for @${actor}. They might not be a collaborator. Error: ${error.message}`);
}

- uses: actions/checkout@v5
with:
ref: ${{ inputs.target_ref || github.event.pull_request.head.sha || github.sha }}

# The permission check step has been moved to the `check-permissions` job.

- uses: actions/setup-go@v5
with:
go-version-file: "go.mod"
Expand All @@ -93,8 +168,8 @@ jobs:
nohup gosmee client --saveDir /tmp/gosmee-replay ${{ secrets.PYSMEE_URL }} "http://${CONTROLLER_DOMAIN_URL}" &

- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
uses: mxschmitt/action-tmate@v3
with:
detached: true
limit-access-to-actor: true
Expand All @@ -121,11 +196,8 @@ jobs:
run: |
./hack/gh-workflow-ci.sh create_second_github_app_controller_on_ghe

# Adjusted step-level conditions based on the new job-level logic
- name: Run E2E Tests
# This step runs for schedule, PR target (if job started), or workflow_dispatch (if job started)
# Remove the old label check which is no longer relevant for triggering.
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request_target' }}
# The job-level `if` condition already handles this, so the step can run unconditionally
env:
TEST_PROVIDER: ${{ matrix.provider }}
TEST_BITBUCKET_CLOUD_TOKEN: ${{ secrets.BITBUCKET_CLOUD_TOKEN }}
Expand All @@ -142,7 +214,6 @@ jobs:
./hack/gh-workflow-ci.sh run_e2e_tests

- name: Run E2E Tests on nightly
# This step still runs specifically for schedule or workflow_dispatch
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
env:
NIGHTLY_E2E_TEST: "true"
Expand Down Expand Up @@ -188,3 +259,4 @@ jobs:
notify_when: "failure"
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

6 changes: 6 additions & 0 deletions pkg/pipelineascode/pipelineascode.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ func NewPacs(event *info.Event, vcx provider.Interface, run *params.Run, pacInfo
}
}

// Run is the main orchestration entrypoint for processing a single incoming event.
// It matches the event to repository rules, creates or updates Tekton PipelineRuns,
// manages concurrency (including pending/queued state), emits provider statuses,
// and finally patches PipelineRuns with execution order information when applicable.
// The call blocks until all asynchronous operations launched for this event complete.
// Context is used to propagate deadlines/cancellation to downstream clients.
func (p *PacRun) Run(ctx context.Context) error {
matchedPRs, repo, err := p.matchRepoPR(ctx)
if repo != nil && p.event.TriggerTarget == triggertype.PullRequestClosed {
Expand Down
Loading