Skip to content

Commit

Permalink
feat: trigger Github actions from CircleCI (#1959)
Browse files Browse the repository at this point in the history
This triggers Github Actions from CircleCi, so we can continue to use
CircleCI as the workflow orchestrator, but run x86 macOS jobs on Github.

---------

Co-authored-by: jonathanrainer <jonathan.rainer@apollographql.com>
  • Loading branch information
nmoutschen and jonathanrainer authored Jul 10, 2024
1 parent 94580ec commit b050603
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 9 deletions.
28 changes: 24 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ workflows:
rust_channel: [stable]
command: [test]

- xtask:
name: Run studio integration tests on GitHub (<< matrix.rust_channel >> rust on << matrix.platform >>)
context:
- github-orb
matrix:
parameters:
platform: [amd_ubuntu]
rust_channel: [stable]
command: [github-actions]
options:
- |
--workflow-name 'tests-mac-x86.yml' --branch "<< pipeline.git.branch >>" --commit-id "<< pipeline.git.revision >>" --inputs '{"composition-versions": "[\"2.8.2\"]", "router-versions": "[\"1.50.0\"]"}'
- xtask:
name: Run supergraph-demo tests (<< matrix.rust_channel >> rust on << matrix.platform >>)
matrix:
Expand Down Expand Up @@ -247,7 +260,7 @@ jobs:
type: executor
command:
type: enum
enum: [lint, unit-test, integration-test, test, package, security-checks]
enum: [lint, unit-test, integration-test, test, package, security-checks, github-actions]
options:
type: string
default: ""
Expand Down Expand Up @@ -508,14 +521,21 @@ commands:
parameters:
command:
type: enum
enum: [lint, integration-test, unit-test, test, package, security-checks]
enum: [lint, integration-test, unit-test, test, package, security-checks, github-actions]
options:
type: string
platform:
type: executor
steps:
- run:
command: cargo xtask << parameters.command >> << parameters.options >>
command: |
export GITHUB_ACTIONS_TOKEN="$(echo "$GH_BOT_KEY_B64" | base64 -d)"
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_ACTIONS_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/user
cargo xtask << parameters.command >> << parameters.options >>
- unless:
condition:
Expand Down Expand Up @@ -663,4 +683,4 @@ commands:
steps:
- run:
name: Publish to npm (beta)
command: cd << parameters.npm_dir >> && npm publish --tag beta << parameters.options >>
command: cd << parameters.npm_dir >> && npm publish --tag beta << parameters.options >>
2 changes: 1 addition & 1 deletion .github/workflows/tests-mac-x86.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
matrix:
composition-version: ${{ fromJSON(inputs.composition-versions) }}
# x86-64 runner
runs-on: macos-13
runs-on: macos-14-large
env:
TEST_COMPOSITION_VERSION: "=${{ matrix.composition-version }}"
ROVER_BINARY: ../../artifact/rover
Expand Down
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion xtask/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ tokio-stream = { workspace = true }
uuid = { workspace = true, features = ["v4"] }
which = { workspace = true }
zip = { workspace = true }
octocrab = "0.38.0"

[target.'cfg(not(windows))'.dependencies]
lychee-lib = { version = "0.15", features = ["vendored-openssl"] }

[dev-dependencies]
mockito = "1.4.0"
rstest = { workspace = true }
speculoos = { workspace = true }
speculoos = { workspace = true }
131 changes: 131 additions & 0 deletions xtask/src/commands/github_action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use std::time::Duration;

use anyhow::{anyhow, Result};
use clap::Parser;
use octocrab::{models::RunId, Octocrab, OctocrabBuilder};
use serde_json::json;

const WORKFLOW_GET_ID_TIMEOUT: Duration = Duration::from_secs(30);
const WORKFLOW_RUN_TIMEOUT: Duration = Duration::from_secs(600);
const WORKFLOW_WAIT_TIME: Duration = Duration::from_secs(2);

#[derive(Debug, Parser)]
pub struct GithubActions {
/// The GitHub workflow name
#[arg(long = "workflow-name", env = "WORKFLOW_NAME")]
pub(crate) workflow_name: String,

/// GitHub organization name
#[arg(long = "organization", default_value = "apollographql")]
pub(crate) organization: String,

/// GitHub repository name
#[arg(long = "repository", default_value = "rover")]
pub(crate) repository: String,

/// The repository branch to use
#[arg(long = "branch")]
pub(crate) branch: String,

/// The commit ID for this run
#[arg(long = "commit-id")]
pub(crate) commit_id: String,

/// A JSON document to use as inputs for GitHub Actions
#[arg(long = "inputs")]
pub(crate) inputs: String,
}

impl GithubActions {
pub async fn run(&self) -> Result<()> {
let token = std::env::var("GITHUB_ACTIONS_TOKEN")
.map_err(|_err| anyhow!("$GITHUB_ACTIONS_TOKEN is not set or is not valid UTF-8."))?;
let octocrab = OctocrabBuilder::new()
.personal_token(token.clone())
.build()?;

// Find information about the current user
let user = octocrab.current().user().await?.login;

// Trigger GitHub workflow by sending a workflow dispatch event
// See <https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event>
let inputs: serde_json::Value = serde_json::from_str(&self.inputs)?;
let res = octocrab
._post(
format!(
"https://api.github.com/repos/{}/{}/actions/workflows/{}/dispatches",
self.organization, self.repository, self.workflow_name
),
Some(&json!({
"ref": self.branch,
"inputs": inputs,
})),
)
.await?;

if !res.status().is_success() {
return Err(anyhow!(
"failed to start workflow, got status code {}",
res.status()
));
}

// Find the corresponding workflow run ID
let fut = async {
loop {
match self.get_run_id(&octocrab, &user).await {
Ok(run_id) => return run_id,
Err(_err) => {
tokio::time::sleep(WORKFLOW_WAIT_TIME).await;
}
}
}
};
let run_id = tokio::time::timeout(WORKFLOW_GET_ID_TIMEOUT, fut).await?;

crate::info!("monitoring run {}", run_id);

match self.check_run(&octocrab, run_id).await {
Ok(()) => crate::info!("run {} completed successfully", run_id),
Err(_err) => crate::info!("run {} failed or did not complete in time", run_id),
}

Ok(())
}

async fn get_run_id(&self, octocrab: &Octocrab, login: &str) -> Result<RunId> {
Ok(octocrab
.workflows(&self.organization, &self.repository)
.list_runs(&self.workflow_name)
.branch(&self.branch)
.event("workflow_dispatch")
.actor(login)
.send()
.await?
.into_iter()
.find(|run| run.head_commit.id == self.commit_id)
.ok_or_else(|| anyhow!("could not find a matching run on GitHub"))?
.id)
}

async fn check_run(&self, octocrab: &Octocrab, run_id: RunId) -> Result<()> {
let fut = async {
loop {
let run = octocrab
.workflows(&self.organization, &self.repository)
.get(run_id)
.await?;

match run.status.as_str() {
"completed" => return Ok(()),
"failure" => return Err(anyhow!("GitHub workflow run failed")),
_ => {
tokio::time::sleep(WORKFLOW_WAIT_TIME).await;
}
}
}
};

tokio::time::timeout(WORKFLOW_RUN_TIMEOUT, fut).await?
}
}
2 changes: 2 additions & 0 deletions xtask/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub(crate) use dist::Dist;
pub(crate) use docs::Docs;
pub(crate) use github_action::GithubActions;
pub(crate) use integration_test::IntegrationTest;
pub(crate) use lint::Lint;
pub(crate) use package::Package;
Expand All @@ -11,6 +12,7 @@ pub(crate) use unit_test::UnitTest;

pub(crate) mod dist;
pub(crate) mod docs;
pub(crate) mod github_action;
pub(crate) mod integration_test;
pub(crate) mod lint;
pub(crate) mod package;
Expand Down
6 changes: 6 additions & 0 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub enum Command {
/// Run supergraph-demo with a local Rover build
IntegrationTest(commands::IntegrationTest),

/// Trigger Github actions and wait for their completion
GithubActions(commands::GithubActions),

/// Run a basic smoke test for rover dev
Smoke(commands::Smoke),
}
Expand All @@ -67,6 +70,9 @@ impl Xtask {
Command::Prep(command) => command.run(),
Command::Package(command) => command.run(),
Command::SecurityChecks(command) => command.run(),
Command::GithubActions(command) => {
tokio::runtime::Runtime::new()?.block_on(command.run())
}
Command::Smoke(command) => tokio::runtime::Runtime::new()?.block_on(command.run()),
}?;
eprintln!("{}", style("Success!").green().bold());
Expand Down

0 comments on commit b050603

Please sign in to comment.