Skip to content

Commit

Permalink
feat: check-downstream-compiles crate (#71)
Browse files Browse the repository at this point in the history
* feat: Add check-downstream-compiles crate

* ci: Use `check-downstream-compiles` crate

* ci: Add basic CI
  • Loading branch information
samuelburnham committed Aug 12, 2024
1 parent e5bc621 commit cdac576
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 94 deletions.
99 changes: 8 additions & 91 deletions .github/actions/check-downstream-compiles/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,107 +14,24 @@ inputs:
description: 'Path to upstream repo'
required: true
type: string
# Patch with an HTTPS or SSH URL. Defaults to HTTPS
patch-ssh:
description: 'Patch with HTTPS or SSH'
required: false
default: false
type: boolean
# Comma-separated list of crates to patch further down the dependency chain
more-paths:
description: 'Paths to further downstream'
# `[patch.<patch-type>]`, defaults to HTTPS URL from upstream caller repo
patch-type:
description: 'Patch with HTTPS, SSH, or crates.io'
required: false
default: 'https'
type: string

runs:
using: "composite"
steps:
# Assumes at least one dependency in the current workspace is used by the downstream crate
- name: Patch Cargo.toml
- name: Patch Cargo.toml files in the downstream repo with all uses of the upstream-repo
shell: bash
working-directory: ${{ github.workspace }}/${{ inputs.downstream-path }}
working-directory: ${{ github.workspace }}/ci-workflows/crates/check-downstream-compiles
run: |
if [[ "${{ inputs.patch-ssh }}" == "true" ]]; then
URL=ssh://[email protected]/${{ github.repository }}
else
URL=https://github.com/${{ github.repository }}
fi
# Get a list of all upstream dependencies used by the downstream crate workspace
# This is done by checking for each instance of `git = <upstream_url>` in any of the downstream `Cargo.toml` files
DEPENDENCIES=$(grep -rsh "git = \"$URL" --include="Cargo.toml" .)
# Extract the dependency names and check for package renames, removing duplicates
DEP_NAMES=$(echo "$DEPENDENCIES" | awk '/package =/{for (i=1; i<=NF; i++) if ($i == "package") {name=$(i+2); print substr(name, 2, length(name)-2);} found=1} !/package =/{print $1}' | sort -u)
shopt -s nullglob
# Collect the `(path, package)` pairs for most subcrates in the upstream directory, regardless of whether they are workspace members
# Patch paths are absolute so they can be used in any Cargo.toml
SUBCRATES=$(find ${{ github.workspace }}/${{ inputs.upstream-path }} \( -type d \( -name target -o -name examples -o -name tests -o -name cli \) -prune \) -o -name Cargo.toml -exec awk '/^\[package\]/{flag=1} flag && /name\s*=/ {gsub(/"/, "", $3); package=$3} /^\[[^p]/ && flag {exit} END{if(package != "") print FILENAME, package}' {} \; | sed 's|/Cargo.toml | |g')
shopt -u nullglob
# Store the subcrates in associative array for retrieval when patching `Cargo.toml`
declare -A subcrates
while IFS= read -r line; do
pair=($line)
subcrates[${pair[1]}]=${pair[0]}
done <<< "$SUBCRATES"
# Get list of Git patches for each dependency used downstream
for crate in $DEP_NAMES; do
crate_path="${subcrates[$crate]}"
echo "$crate = { path = \"$crate_path\" }" | tee -a patches.txt
done
ESCAPED_URL=$(printf '%s\n' "$URL" | sed 's/[\/&]/\\&/g')
# Write patches to all Cargo.toml files in the directory
for file in $(find . -name Cargo.toml -not -path "./target/*"); do
# Add the `[patch]` section if it doesn't exist already, as duplicates aren't allowed
if ! grep -q "\[patch.'$URL'\]" $file; then
printf "\n\n[patch.'$URL']\n" >> $file
# If `[patch]` does exist, remove any duplicate keys before inserting patches
else
for crate in $DEP_NAMES; do
sed -i "/\[patch.'$ESCAPED_URL'\]/,/^$/ { /^$crate.*$/d }" $file
done
fi
# Append all patches after the `[patch.'ssh']` line
sed -i "/\[patch.'$ESCAPED_URL'\]/r patches.txt" $file
done
# If more crates were specified, patch them too
if [[ ! -z "${{ inputs.more-paths }}" ]]; then
for path in "${{ inputs.more-paths }}"; do
for file in $(find $path -name Cargo.toml -not -path "./target/*"); do
# Add the `[patch]` section if it doesn't exist already, as duplicates aren't allowed
if ! grep -q "\[patch.'$URL'\]" $file; then
printf "\n\n[patch.'$URL']\n" >> $file
# If `[patch]` does exist, remove any duplicate keys before inserting patches
else
for crate in $DEP_NAMES; do
sed -i "/\[patch.'$ESCAPED_URL'\]/,/^$/ { /^$crate.*$/d }" $file
done
fi
# Append all patches after the `[patch.'ssh']` line
sed -i "/\[patch.'$ESCAPED_URL'\]/r patches.txt" $file
done
done
fi
cargo run -- --upstream ${{ github.workspace }}/${{ inputs.upstream-path }} --downstream ${{ github.workspace }}/${{ inputs.downstream-path }} --repo ${{ github.repository }} --patch-type ${{ inputs.patch-type }}
- name: Check downstream types don't break spectacularly
shell: bash
working-directory: ${{ github.workspace }}/${{ inputs.downstream-path }}
run: |
cargo check --workspace --tests --benches --examples
- name: Check more downstream types don't break spectacularly
if: ${{ inputs.more-paths != '' }}
shell: bash
working-directory: ${{ github.workspace }}
run: |
for path in "${{ inputs.more-paths }}"; do
cd $path
cargo check --workspace --tests --benches --examples
cd ${{ github.workspace }}
done
cargo check --workspace --all-targets
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: CI Tests

on:
push:
branches: main
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
test:
name: CI Test Suite
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
repository: argumentcomputer/ci-workflows
- uses: ./.github/actions/ci-env
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@nextest
- name: Run tests
run: cargo nextest run
working-directory: ${{ github.workspace }}/crates/check-downstream-compiles

clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
repository: argumentcomputer/ci-workflows
- uses: ./.github/actions/ci-env
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Check Rustfmt Code Style
run: cargo fmt --all --check
working-directory: ${{ github.workspace }}/crates/check-downstream-compiles
- name: check *everything* compiles
run: cargo check --all-targets --all-features --all --examples --tests --benches
working-directory: ${{ github.workspace }}/crates/check-downstream-compiles
# See '.cargo/config' for list of enabled/disabled clippy lints
- name: Check clippy warnings
run: cargo xclippy -D warnings
working-directory: ${{ github.workspace }}/crates/check-downstream-compiles
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
target/
Cargo.lock
**/target/
**/Cargo.lock
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# ci-workflows
GitHub Actions workflows and templates for use in Lurk repos
GitHub Actions workflows and templates for use in Argument repos
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
50 changes: 50 additions & 0 deletions crates/check-downstream-compiles/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[alias]
# Collection of project wide clippy lints. This is done via an alias because
# clippy doesn't currently allow for specifiying project-wide lints in a
# configuration file. This is a similar workaround to the ones presented here:
# <https://github.com/EmbarkStudios/rust-ecosystem/issues/59>
xclippy = [
"clippy", "--workspace", "--all-targets", "--all-features", "--",
"-Wclippy::all",
"-Wclippy::cast_lossless",
"-Wclippy::checked_conversions",
"-Wclippy::dbg_macro",
"-Wclippy::disallowed_methods",
"-Wclippy::derive_partial_eq_without_eq",
"-Wclippy::enum_glob_use",
"-Wclippy::explicit_into_iter_loop",
"-Wclippy::fallible_impl_from",
"-Wclippy::filter_map_next",
"-Wclippy::flat_map_option",
"-Wclippy::from_iter_instead_of_collect",
"-Wclippy::implicit_clone",
"-Wclippy::inefficient_to_string",
"-Wclippy::invalid_upcast_comparisons",
"-Wclippy::large_stack_arrays",
"-Wclippy::large_types_passed_by_value",
"-Wclippy::macro_use_imports",
"-Wclippy::manual_assert",
"-Wclippy::manual_ok_or",
"-Wclippy::map_flatten",
"-Wclippy::map_unwrap_or",
"-Wclippy::match_same_arms",
"-Wclippy::match_wild_err_arm",
"-Wclippy::missing_const_for_fn",
"-Wclippy::needless_borrow",
"-Wclippy::needless_continue",
"-Wclippy::needless_for_each",
"-Wclippy::needless_pass_by_value",
"-Wclippy::option_option",
"-Wclippy::same_functions_in_if_condition",
"-Wclippy::single_match_else",
"-Wclippy::trait_duplication_in_bounds",
"-Wclippy::unnecessary_wraps",
"-Wclippy::unnested_or_patterns",
"-Wnonstandard_style",
"-Wrust_2018_idioms",
"-Wtrivial_numeric_casts",
"-Wunused_lifetimes",
"-Wunreachable_pub",
"-Wtrivial_numeric_casts",
"-Wunused_qualifications",
]
10 changes: 10 additions & 0 deletions crates/check-downstream-compiles/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "check-downstream-compiles"
version = "0.1.0"
edition = "2021"

[dependencies]
camino = "1.1.7"
clap = { version = "4.5.13", features = ["derive"] }
toml_edit = "0.22.20"
walkdir = "2.5.0"
Loading

0 comments on commit cdac576

Please sign in to comment.