Skip to content

PHP client library for consuming the Buildkite API

License

Notifications You must be signed in to change notification settings

bbaga/buildkite-php

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

49 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PHP client library for consuming the Buildkite API

Installation

composer require bbaga/buildkite-php

Usage

Setting up the API objects

\Psr\Http\Client\ClientInterface implementation is available in the bbaga/buildkite-php-guzzle-client package.

Rest API

use bbaga\BuildkiteApi\Api\RestApi;

/** @var \Psr\Http\Client\ClientInterface $client */
$client = new MyHttpClient(); 

$api = new RestApi($client, 'MY_BUILDKITE_API_TOKEN');

GraphQL API

use bbaga\BuildkiteApi\Api\GraphQLApi;

/** @var \Psr\Http\Client\ClientInterface $client */
$client = new MyHttpClient(); 

$api = new GraphQLApi($client, 'MY_BUILDKITE_API_TOKEN');

Interacting with Buildkite's GraphQL API

use bbaga\BuildkiteApi\Api\GraphQLApi;
use bbaga\BuildkiteApi\Api\GuzzleClient;

$query = '
    query example($slug: ID!, $first: Int){
        viewer { user { name } }
        
        organization(slug: $slug) {
            pipelines(first: $first) {
                edges {
                    node {
                        id
                        slug
                    }
                }
            }
        } 
    }';

$variables = json_encode(['slug' => 'my-org', 'first' => 5]);

$client = new GuzzleClient();
$api = new GraphQLApi($client, 'MY_BUILDKITE_API_TOKEN');

$api->getResponseBody($api->post($query, $variables));

Interacting with Buildkite's REST API

Example of traversing through resources

use bbaga\BuildkiteApi\Api\GuzzleClient;
use bbaga\BuildkiteApi\Api\Rest\Fluent;
use bbaga\BuildkiteApi\Api\RestApi;

$client = new GuzzleClient();
$api = new RestApi($client, 'MY_BUILDKITE_API_TOKEN');

/** Getting all the organizations that are visible with the TOKEN */
/** @var Fluent\Organization[] $organizations */
$organizations = (new Fluent\Organizations($api))->get();

/** @var Fluent\Organization $organization */
$organization = $organizations[0];

/** @var Fluent\Pipeline $pipelines */
$pipelines = $organization->getPipelines();

/** @var Fluent\Pipeline $pipeline */
$pipeline = $pipelines[0];

/** @var Fluent\Build[] $builds */
$builds = $pipeline->getBuilds();

/** @var Fluent\Build $build */
$build = $builds[0];

/** @var Fluent\Job[] $jobs */
$jobs = $build->getJobs();

/** @var Fluent\Emoji[] $emojis */
$emojis = $organizations[0]->getEmojis();

/** @var Fluent\Agent[] $emojis */
$agents = $organizations[0]->getAgents();

Accessing resources without traversing

Fetching data for a specific build without traversing through the hierarchy.

use bbaga\BuildkiteApi\Api\GuzzleClient;
use bbaga\BuildkiteApi\Api\Rest\Fluent;
use bbaga\BuildkiteApi\Api\RestApi;

$client = new GuzzleClient();
$api = new RestApi($client, 'MY_BUILDKITE_API_TOKEN');

/**
 * Builds are identified by the follwoing three values 
 */
$organizationSlug = 'my-org';
$pipelineSlug = 'my-pipeline';
$buildNumber = 23;

$organization = new Fluent\Organization($api, ['slug' => $organizationSlug]);
$pipeline = new Fluent\Pipeline($api, $organization, ['slug' => $pipelineSlug]);
$build = new Fluent\Build($api, $organization, ['number' => $buildNumber, 'pipeline' => $pipeline]);

$build->fetch()->getJobs();

Creating a new pipeline

use bbaga\BuildkiteApi\Api\GuzzleClient;
use bbaga\BuildkiteApi\Api\Rest\Fluent;
use bbaga\BuildkiteApi\Api\RestApi;

$client = new GuzzleClient();
$api = new RestApi($client, 'MY_BUILDKITE_API_TOKEN');

$organization = new Fluent\Organization($api, ['slug' => 'my-org']);
$pipeline = $organization->createPipeline(
    [
        'name' => 'my-pipeline',
        'repository' => '[email protected]:some/repo.git',
        'steps' => [
            [
                'type' => 'script',
                'name' => 'upload artifact',
                'command' => 'echo "Hello" > artifact.txt \
                 && buildkite-agent artifact upload artifact.txt \
                 && cat artifact.txt | buildkite-agent annotate --style "success" --context "junit"',
            ],
            [
                'type' => 'manual',
                'name' => 'Needs to be unblocked',
                'command' => 'echo "Unblocked!"',
            ],
        ]
    ]
);

/**
 * Pipeline is ready, we can kick off the first build
 */
$buildSettings = [
    'commit' => 'HEAD',
    'branch' => 'master',
    'message' => 'Testing all the things :rocket:',
];

$pipeline->createBuild($buildSettings);

Direct API calls

Organizations API

Organizations related methods are exposed via $api->organization()

Detailed documentation for the Organizations API is available here

List the organizations

$api->organization()->list();

Get a specific organization

$api->organization()->get('my-organization');

Pipelines API

Pipelines related methods are exposed via $api->pipeline()

Detailed documentation for the Pipelines API is available here

List pipelines in an organizations

$api->pipeline()->list('my-organizations');

Get a specific pipeline

$api->pipeline()->get('my-organization', 'my-pipeline');

Create a pipeline

$pipelineData = [
    'name' => 'My Pipeline',
    'repository' => '[email protected]:acme-inc/my-pipeline.git',
    'steps' => [
        [
            'type' => 'script',
            'name' => 'Build :package:',
            'command' => 'script/release.sh',
        ],
    ],
];

$api->pipeline()->create('my-organization', $pipelineData);

Update a pipeline

$pipelineData = [
    'repository' => '[email protected]:acme-inc/new-repo.git',
];

$api->pipeline()->update('my-organization', 'my-pipelines', $pipelineData);

Delete a pipelne

$api->pipeline()->delete('my-organization', 'my-pipeline');

Builds API

Builds related methods are exposed via $api->build()

Detailed documentation for the Builds API is available here

List all builds across all the organizations

$api->build()->listAll($queryParameters);

Get a specific build

$buildNumber = 1;
$api->build()->get('my-organization', 'my-pipeline', $buildNumber);

Get builds in an organization

$api->build()->getByOrganization('my-organization', $queryParameters);

Get builds for a pipeline

$api->build()->getByPipeline('my-organization', 'my-pipeline', $queryParameters);

Create a new build

$buildSettings = [
    'commit' => 'abcd0b72a1e580e90712cdd9eb26d3fb41cd09c8',
    'branch' => 'master',
    'message' => 'Testing all the things :rocket:',
    'author' => [
        'name' => 'Keith Pitt',
        'email' => '[email protected]',
    ],
    'env' => [
        'MY_ENV_VAR' => 'some_value',
    ],
    'meta_data' => [
        'some build data' => 'value',
        'other build data' => true,
    ],
];

$api->build()->create('my-organization', 'my-pipeline', $buildSettings);

Cancel a running build

$buildNumber = 12;
$api->build()->cancel('my-organization', 'my-pipeline', $buildNumber);

Restarting a build

$buildNumber = 12;
$api->build()->rebuild('my-organization', 'my-pipeline', $buildNumber);

Jobs API

Jobs related methods are exposed via $api->job()

Detailed documentation for the Jobs API is available here

Retry a job

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';

$api->job()->retry('my-organization', 'my-pipeline', $buildNumber, $jobId);

Unblock a job

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';

$api->job()->unblock('my-organization', 'my-pipeline', $buildNumber, $jobId);

Get logs for a job

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';

$api->job()->getLogOutput('my-organization', 'my-pipeline', $buildNumber, $jobId);

Delete logs of a job

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';

$api->job()->deleteLogOutput('my-organization', 'my-pipeline', $buildNumber, $jobId);

Get the environment variables from a job

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';

$api->job()->getEnvironmentVariables('my-organization', 'my-pipeline', $buildNumber, $jobId);

Artifacts API

Jobs related methods are exposed via $api->artifact()

Detailed documentation for the Artifacts API is available here

Get artifacts uploaded from a build

$buildNumber = 12;
$api->artifact()->getByBuild('my-organization', 'my-pipeline', $buildNumber);

Get artifacts uploaded from a job

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';

$api->artifact()->getByJob('my-organization', 'my-pipeline', $buildNumber, $jobId);

Get a specific artifact

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';
$artifactId = '567038da5f03724b02a1cbf07a12fbcedfg';

$api->artifact()->get(
    'my-organization',
    'my-pipeline',
    $buildNumber,
    $jobId,
    $artifactId
);

Delete a specific artifact

$buildNumber = 12;
$jobId = '0738da5f-0372-4b02-a1cb-f07a12fbcdcd';
$artifactId = '567038da5f03724b02a1cbf07a12fbcedfg';

$api->artifact()->delete(
    'my-organization',
    'my-pipeline',
    $buildNumber,
    $jobId,
    $artifactId
);

Agents API

Agents related methods are exposed via $api->agent()

Detailed documentation for the Agents API is available here

List agents for an organization

$api->agent()->list('my-organization');

Get a specific agent

$agentId = '1d633306-de28-4944-ad84-fde0d50a6c9e';
$api->agent()->list('my-organization', $agentId);

Stop an agent

$agentId = '1d633306-de28-4944-ad84-fde0d50a6c9e';
$api->agent()->list('my-organization', $agentId);

Annotations API

Annotations related methods are exposed via $api->annotation()

Detailed documentation for the Annotations API is available here

Get annotations uploaded by a build

$buildNumber = 12;
$api->annotation()->list('my-organization', 'my-pipeline', $buildNumber);

Users API

Users related methods are exposed via $api->user()

Detailed documentation for the Users API is available here

Get current user

$api->user()->whoami();

Emojis API

Emojis related methods are exposed via $api->emoji()

Detailed documentation for the Users API is available here

List available emojis

$api->emoji()->list('my-organization');

Contribution

Testing

make test

Integration testing

A Buildkite account and a running agent is required for integration testing and the following environment variables must be set.

  • BK_TEST_TOKEN
  • BK_TEST_ORG
  • BK_TEST_PREFIX
  • GITHUB_REF
  • GITHUB_REPOSITORY

These can be set in the phpunit.xml by making a copy of phpunit.xml.dist and extending it with the following snippet

    <php>
        <env name="BK_TEST_TOKEN" value="my-buildkite-api-token"/>
        <env name="BK_TEST_ORG" value="my-organization-slug"/>
        <env name="BK_TEST_PREFIX" value="something-uniqe"/>
        <env name="GITHUB_REF" value="refs/heads/master"/>
        <env name="GITHUB_REPOSITORY" value="your-name/buildkite-php"/>
    </php>

Once the environment variables are set the test suite can be started

make integration