Run pipeline from protected branch

Hey there :wave:

I am creating a pipeline for a public repo that I’d like to trigger pull requests from 3rd party forks. The option below is nice and allows me to trigger builds from any 3rd-party fork.

Coming from Jenkins and GitHub actions, I assumed there would be a way to use the .buildkite/ config of a protected branch, or ideally the base/target branch on the upstream repo. With GitHub actions, any changes to pull_request_target and repository_dispatch on a 3rd-party PR will be ignored until merged. Similarly with Jenkins, the source of truth for the Jenkinsfile comes from the main/master branch, not sure if this is configurable.

With that said I’d like a way to enforce what is run on buildkite and prevent anyone from opening a PR and changing the .buildkite/ configuration files and having full access, but allow this for owners of the repo. I could see a way to use the user branch naming prefix to control this from the yml pipeline config in the buildkite UI but ideally there would be a way to limit this from the .buildkite/ directory files or a pipeline setting.

I am currently triggering my pipeline via .buildkite/pipeline.sh that generates and uploads my full pipeline.

What is the best way to do this at a pipeline level? Thanks :pray:

I’ve been experimenting with this approach recently:

---
steps:
- block: ':hourglass: Waiting for Grapl Engineer...'
  prompt: |
    Does this external contribution look safe to run?
    If so, please unblock it!
    If not, please cancel this pipeline run altogether.
  if: build.pull_request.repository.fork
- label: ':pipeline:'
  command: buildkite-agent pipeline upload .buildkite/pipeline.verify.yml
  agents:
    queue: pipeline-uploaders

That is set up in the Buildkite UI, inaccessible to anybody outside our operations team. That gives you a chance to have somebody take a look at the change to see if somebody tried to do anything sneaky. If it looks OK, you can un-block it; if it’s fishy, you can cancel it.

1 Like

Yeah that would work but would require approval for everyone, including repo owners. Maybe this combined with a check for files in .buidkite/ would be adequate security with maximum flexibility.

Yeah, this works for us because everyone at my company works directly on the main repository and doesn’t use forks. If you all have an “everybody uses forks” policy, this won’t be what you want. :slightly_frowning_face:

You could maybe set up the "check for files in .buildkite/" logic you mentioned in a script that you include on all your build agents, and then use that in a preliminary, pre-upload step in a UI-defined pipeline. Packaging it up in a plugin would be another, more flexible, approach to take.

1 Like

Yeah we use the fork-and-branch git workflow.

It’d be nice if there was a way to specify a ref for the pipeline upload similar to GitHub actions reusable workflows with the {owner}/{repo}@{ref} syntax…

# GitHub action syntax -- not buildkite!
jobs:
  call-workflow-1-in-local-repo:
    uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89
  call-workflow-2-in-local-repo:
    uses: ./.github/workflows/workflow-2.yml
  call-workflow-in-another-repo:
    uses: octo-org/another-repo/.github/workflows/workflow.yml@v1

Ref: Workflow syntax for GitHub Actions - GitHub Docs

Interesting idea… might be worth dropping a post in the Features category!

1 Like

Yeah but even though the pipeline upload is using protected source, how would the uploaded steps use the protected .buildkite/ source for running each job? Surely this has come up before for others :sweat_smile:. Thanks for the ideas!

Not sure how far it will go but I started the conversation! Run pipelines based on protected ref

Hey @nickofthyme welcome to the community! :wave:

@cwmaier-grapl’s suggestion of using a hook or packaging up a script in a plugin to run some checks would be one way of handling the behaviour you are looking for. I think though, the feature request you created is an excellent suggestion, and I’ve passed it along to our product team to review it :slight_smile:

1 Like

Yeah working on a plugin now to check user membership, etc to determine when to block the pipeline, thanks for the comment!

Just for the sake of closing this thread.

This is my first pass at a plugin GitHub - nickofthyme/pull-request-protector-buildkite-plugin: Blocks 3rd-party pull requests based on user checks and files changed. Example use would be something like…

steps:
  - label: "Check user"
    key: auth-check
    command: |
      # must have a command or step will fail but not required for this plugin
      echo "PR_PROTECTOR_BLOCKED: $$PR_PROTECTOR_BLOCKED" # use to run script based on result of conditions
    plugins:
      - nickofthyme/pull-request-protector#v0.1.0-alpha.12:
          verified: true # requires repo:read access
          collaborator: true # requires repo read access
          member: true # requires org:read access
          users: [nickofthyme]
          teams: ['my-team-slug'] # requires org:read access
          files: ['.buildkite/**', 'scripts/**/*.sh'] # files to trigger guard checks
          block_step: # The resulting block step if checks fail
            prompt: 'Pipeline is blocked for given user'
  - label: ":pipeline: Pipeline upload"
    depends_on: auth-check # must depend on auth-check step
    command: .buildkite/pipelines/pull_request/pipeline.sh

FYI: other teams at my company created a simple service to relay the webhook and do all these checks from there. This service could also pickup on PR comments and validate that user before triggering the build of 3rd-party pull requests.

Thank you @nickofthyme for working on plugin and sharing the details.

1 Like