Skip to content

Commit

Permalink
feat: make it work (#2)
Browse files Browse the repository at this point in the history
This PR takes the basic implementation of this app (which I made while I
was still allowed to push to main) and iterates on it in tandem with the
work in grafbase/grafbase#2090 (see that PR for
context)

I've also added some CI that'll build releases. Once this is merged I'll
update the grafbase repo to use the binaries instead of building on
every CI run.
  • Loading branch information
obmarg authored Sep 5, 2024
1 parent 2a17577 commit dd879b1
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 90 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Create release

on:
push:
tags:
- "v*"

jobs:
create-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Create Release
uses: taiki-e/create-gh-release-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

upload-artifacts:
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest

runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Upload binaries
uses: taiki-e/upload-rust-binary-action@v1
with:
bin: what-rust-changed
token: ${{ secrets.GITHUB_TOKEN }}
36 changes: 36 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Build

on:
push:
branches: [main]
pull_request:
branches: [main]

env:
COLUMNS: 250
CARGO_INCREMENTAL: 0
RUSTFLAGS: "-W rust-2021-compatibility -D warnings"
RUST_BACKTRACE: short
NEXTEST_PROFILE: ci
CI: 1

jobs:
build-rust:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: dtolnay/[email protected]
with:
components: rustfmt

- uses: Swatinem/rust-cache@v2

- name: Check formatting
shell: bash
run: cargo fmt --check

- name: Build
shell: bash
run: cargo build
59 changes: 56 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ determinator = "0.12"
guppy = "0.17"
itertools = "0.13"
serde = "1"
serde_json = "1"
serde_json = "1"
toml = "0.8"
29 changes: 29 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::fs::read_to_string;

pub fn load() -> Config {
do_load().unwrap_or_default()
}

fn do_load() -> Option<Config> {
let path = std::env::var("WHAT_RUST_CHANGED_CONFIG").ok()?;

eprintln!("Loading config from {path}");

let data = read_to_string(path).expect("to be able to read named config file");

toml::from_str(&data).expect("invalid config format")
}

#[derive(serde::Serialize, serde::Deserialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct Config {
/// Packages that shouldn't automatically be included in test runs
pub ignore_test_packages: Vec<String>,

/// Packages that require docker for their tests and should be put
/// into a separate section of the output
pub docker_test_packages: Vec<String>,

#[serde(flatten)]
pub determinator_rules: determinator::rules::DeterminatorRules,
}
62 changes: 62 additions & 0 deletions src/guppy_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use guppy::graph::{BuildTarget, BuildTargetKind};

pub trait PackageMetadataExt {
fn has_test_targets(&self) -> bool;
fn binary_targets(&self) -> Vec<BuildTarget<'_>>;
}

impl PackageMetadataExt for guppy::graph::PackageMetadata<'_> {
fn has_test_targets(&self) -> bool {
let package_root_path = self
.manifest_path()
.parent()
.expect("all packages to have manifests with one parent");

self.build_targets()
.filter(|target| {
matches!(
target.kind(),
BuildTargetKind::Binary | BuildTargetKind::LibraryOrExample(_)
)
})
.any(|target| {
let relative_path = target
.path()
.strip_prefix(package_root_path)
.expect("targets to live inside package");

let Some(root_folder) = relative_path.components().next() else {
return false;
};

let root_folder = root_folder.as_str();

// Unfortunately doesn't seem to be any way to tell whether something rooted in
// src actually has tests or not, so best to just assume they do
root_folder == "tests" || root_folder == "src"
})
}

fn binary_targets(&self) -> Vec<BuildTarget<'_>> {
let package_root_path = self
.manifest_path()
.parent()
.expect("all packages to have manifests with one parent");

self.build_targets()
.filter(|target| matches!(target.kind(), BuildTargetKind::Binary))
.filter(|target| {
let relative_path = target
.path()
.strip_prefix(package_root_path)
.expect("targets to live inside package");

let Some(root_folder) = relative_path.components().next() else {
return false;
};

root_folder.as_str() == "src" && relative_path.file_name() == Some("main.rs")
})
.collect()
}
}
Loading

0 comments on commit dd879b1

Please sign in to comment.