Skip to content

Releases: obi1kenobi/trustfall

trustfall-v0.8.0

08 Nov 18:32
7d58d0e
Compare
Choose a tag to compare

A maintenance release with bugfixes and small quality-of-life improvements that are technically breaking, if you depended on the details of error message types:

  • Fix for incorrect type coercion / filtering inside @optional that didn't exist: #692, #697
  • Breaking changes to the representation of exposed Rust error types: #621
  • Lots of small improvements to the quality of diagnostic messages for various kinds of incorrect queries.

All Merged PRs

Read more

trustfall-v0.7.1

17 Nov 21:35
6114244
Compare
Choose a tag to compare

A major new update to the Adapter API in order to allow more flexibility when creating and composing adapters: #481

It requires tweaks to adapter implementations to make property and edge resolvers include the V: AsVertex<Self::Vertex> + 'a generic parameter. In practice, this change should be possible to do with only find-and-replace, since other helper functions like accessor_property!() or resolve_property_with() had their APIs updated to dereference via AsVertex as well. For example: https://github.com/obi1kenobi/trustfall-rustdoc-adapter/pull/305/files#diff-f6f5d3d9607240984eb0cbf4ebcf94307990abe1c5a2092756f48ef35798348f

Other Highlights

  • Query evaluation optimization: stop evaluating @fold early if it has no outputs and its count is never observed by the query: #423
  • Expand the adapter optimizations API with the ability to check which properties are used within a vertex: #449
  • accessor_property!() now has a form that allows specifying additional arguments for the function being called: #513
  • Support repeatable on @filter directives by upgrading to a newer parser version.
  • Substantial expansion of the queryable surface area SchemaAdapter supports.
  • Changed representation of FieldValue to make it cheaper to clone, which our APIs will now do a bit more freely.

All Merged Commits

  • Fix publish trustfall_derive job name. by @obi1kenobi in #412
  • Add as_arc_str() and as_arc_slice() methods on FieldValue. by @obi1kenobi in #414
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #416
  • Weekly cargo update of primary dependencies by @obi1kenobi in #417
  • Run doctests in CI and fix failures. by @obi1kenobi in #419
  • add schema starting edge to schemaadapter by @u9g in #413
  • Add docs properties to VertexType, Property, Edge metaschema types. by @obi1kenobi in #422
  • Add new test queries by @u9g in #421
  • Add negative filter tests by @u9g in #425
  • Add a test for no-output folds with @tag on count by @u9g in #427
  • Allow querying docs on edge parameters. by @obi1kenobi in #428
  • Add impossible filter and dominated filter tests by @u9g in #429
  • Add a test for ignoring necessary filters by @u9g in #431
  • add min_fold_count_limit optimization by @u9g in #423
  • Throw error for tag directive on edge by @u9g in #432
  • Add tag on fold test by @u9g in #433
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #436
  • Weekly cargo update of primary dependencies by @obi1kenobi in #437
  • Only use Rust matchers in lint jobs. by @obi1kenobi in #439
  • Don't run clippy on dependencies. by @obi1kenobi in #440
  • Adding information about the scripts for generating test data on readme by @era in #443
  • Convert to pnpm to fix autocompletions by @u9g in #442
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #446
  • Weekly cargo update of primary dependencies by @obi1kenobi in #447
  • Allow any script to be executed anywhere inside the repo by @era in #444
  • Fix false assumption of vertex_type being singleton by @u9g in #445
  • Add an iterator over all the required properties of a Vertex by @era in #449
  • Pin serde to <1.0.172. by @obi1kenobi in #452
  • Weekly cargo update of primary dependencies by @obi1kenobi in #454
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #453
  • Upgrade to latest async-graphql-{parser,value} and Add repeatable to all @filter's by @u9g in #458
  • Suppress new clippy lints. by @obi1kenobi in #460
  • Do not allow users to apply fold, recurse and transform directives to properties by @era in #457
  • Use serde 1.0.185, skipping past the version with a precompiled binary. by @obi1kenobi in #459
  • Add better filter error message for string instead of array. by @u9g in #461
  • Add more tests and rename existing test by @u9g in #462
  • Add error for filter where value argument is just ["$"] or ["%"] by @u9g in #463
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #464
  • Weekly cargo update of primary dependencies by @obi1kenobi in #465
  • Remove reference from statically_required_property's FieldValue by @u9g in #466
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #468
  • Weekly cargo update of primary dependencies by @obi1kenobi in #467
  • Weekly cargo update of primary dependencies by @obi1kenobi in #469
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #470
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #471
  • Weekly cargo update of primary dependencies by @obi1kenobi in #472
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #474
  • Weekly cargo update of primary dependencies by @obi1kenobi in #475
  • Bump all crates to 1.70 MSRV. by @obi1kenobi in #476
  • Weekly cargo update of primary dependencies by @obi1kenobi in #478
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #477
  • Add Python 3.12 to test matrix. by @obi1kenobi in #479
  • Add Python package classifier for Python 3.12 support. by @obi1kenobi in #480
  • Fix new clippy lint. by @obi1kenobi in #484
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #483
  • Weekly cargo update of primary dependencies by @obi1kenobi in #482
  • Move to our own Type type for everything that's exposed in trustfall_core by @u9g in #435
  • Upgrade to actions/checkout@v4 in GitHub Actions. by @obi1kenobi in #486
  • Upgrade to the actions-rust-lang/setup-rust-toolchain action. by @obi1kenobi in #485
  • Build Python wheels for 3.12 on all operating systems. by @obi1kenobi in #487
  • Upgrade to node 20 for JS linting. by @obi1kenobi in #488
  • Remove once_cell dependency from most of the repo's crates. by @obi1kenobi in #489
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #491
  • Weekly cargo update of primary dependencies by @obi1kenobi in #492
  • Add FUNDING.yml file. by @obi1kenobi in #493
  • Use sccache to speed up test runs. by @obi1kenobi in #494
  • Upgrade pytrustfall to pyo3 v0.20. by @obi1kenobi in #496
  • Update pnpm by @u9g in #497
  • Generate a __typename handler branch in stubgen. by @obi1kenobi in #500
  • Allow adapters to process types that deref to their vertex type. by @obi1kenobi in #481
  • Add better autocomplete patch to playground by @u9g in #498
  • Use GitHub permalinks for Adapter docs. by @obi1kenobi in #501
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #502
  • Weekly cargo update of primary dependencies by @obi1kenobi in #503
  • Re-enable playground "accept suggestion" on enter key. Fix HN adapter bu...
Read more

trustfall-v0.6.1

28 Aug 15:50
bd46fda
Compare
Choose a tag to compare

A maintenance release, upgrading trustfall_derive to syn v2 in an attempt to speed up compilation for our dependents by avoiding the use of multiple major versions of a large crate.

All Merged PRs

Full Changelog: trustfall-v0.6.0...trustfall-v0.6.1

trustfall_stubgen-v0.3.0

25 Jul 20:18
de91110
Compare
Choose a tag to compare

What's Changed

  • Feature: Generate adapter test case using Trustfall's check_adapter_invariants() (#389)
  • Feature: Generate improved edge-handling code in trustfall_stubgen (#352)

All Merged PRs

  • Fix dependency updater GitHub Action. by @obi1kenobi in #340
  • Allow TryIntoStruct to unpack EdgeParameters as well. by @obi1kenobi in #350
  • Only declare module tree once in trustfall_stubgen. by @obi1kenobi in #351
  • Generate more edge-handling code in trustfall_stubgen. by @obi1kenobi in #352
  • Tweak stubgen so it doesn't generate linty code. by @obi1kenobi in #353
  • Remove unnecessary lint suppressions. by @obi1kenobi in #355
  • Trigger the CI workflow manually when auto-updating dependencies. by @obi1kenobi in #358
  • Add actions: write permission to auto-updater workflow. by @obi1kenobi in #360
  • Open dependency-updating PRs with a custom access token. by @obi1kenobi in #361
  • Weekly cargo update of primary dependencies by @obi1kenobi in #362
  • Auto-update the fuzzing dependencies via an Actions workflow. by @obi1kenobi in #363
  • Use the default GITHUB_TOKEN to auto-merge PRs. by @obi1kenobi in #364
  • Better names for the automated workflow's jobs. by @obi1kenobi in #366
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #365
  • Bail out if no Cargo.lock changes are needed. by @obi1kenobi in #367
  • Print bail-out messages to stdout when updating dependencies. by @obi1kenobi in #368
  • Weekly cargo update of primary dependencies by @obi1kenobi in #370
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #369
  • add InvalidSchemaError::DuplicateFieldDefinition by @u9g in #373
  • Implement InvalidSchemaError::DuplicateTypeOrInterfaceDefinition by @u9g in #374
  • Add optimization to VertexType entrypoint in schema adapter by @u9g in #339
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #376
  • Weekly cargo update of primary dependencies by @obi1kenobi in #377
  • Update rustdoc playground schema. by @obi1kenobi in #378
  • Get rid of unnecessary clone in schema adapter by @u9g in #379
  • Update rustdoc adapter version in playground. by @obi1kenobi in #380
  • Add more example queries to rustdoc playground. by @obi1kenobi in #381
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #382
  • Weekly cargo update of primary dependencies by @obi1kenobi in #383
  • Query both Rust and crates.io crates in rustdoc playground. by @obi1kenobi in #386
  • Fix new clippy lints. by @obi1kenobi in #385
  • Enable the cli feature in trustfall_stubgen by default. by @obi1kenobi in #388
  • Check that adapters implement declared properties, edges, and coercions. by @obi1kenobi in #384
  • Generate invariant-enforcing tests in stubgen adapters. by @obi1kenobi in #389
  • Output __typename in "items with allowed lints" example rustdoc query. by @obi1kenobi in #391
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #395
  • Weekly cargo update of primary dependencies by @obi1kenobi in #394
  • Allow querying for edge parameter default values. by @obi1kenobi in #396
  • Check adapter edge implementation for edges with default values. by @obi1kenobi in #397
  • Remove ron from dependencies and move to dev-dependencies. by @obi1kenobi in #398
  • Remove chrono from dependencies. Removes datetime value variant. by @obi1kenobi in #399
  • Include vertex Debug output in helper panic message. by @obi1kenobi in #401
  • Make FieldValue cheaper to clone by Arc-ing internally. by @obi1kenobi in #400
  • Replace various uses of vec! with arrays by @nvzqz in #402
  • Make test_field_value_into nicer to work with by @nvzqz in #403
  • Format with max small heuristics by @nvzqz in #404
  • Release Trustfall v0.6 and associated crates. by @obi1kenobi in #405

Full Changelog: trustfall_stubgen-v0.2.2...trustfall_stubgen-v0.3.0

trustfall-v0.6.0

25 Jul 19:46
de91110
Compare
Choose a tag to compare

What's Changed

  • Breaking: the FieldValue::DateTime variant has been removed since it used the unmaintained chrono library (#399)
  • Breaking: FieldValue::String and FieldValue::List now use Arc internally, making FieldValue cheap to clone (#400)
  • Feature: Automatic checker for ensuring Adapter implementations implement their schema and uphold invariants (#384)
  • Feature: TryIntoStruct can now also unpack EdgeParameters (#343)
  • Feature: when querying schemas using SchemaAdapter, it's now possible to query edge parameters' default values (#396)

Feature Highlight: Automatic tests for Adapter implementations (#384)

The new check_adapter_invariants() function is a self-contained adapter tester that can ensure you didn't forget to implement any components of your adapter's schema. Using it is as simple as:

pub use trustfall::provider::check_adapter_invariants;

#[test]
fn ensure_adapter_satisfies_invariants() {
    let adapter = todo!("get an `impl Adapter` type");
    let schema = todo!("get a `&Schema` for our adapter");
    check_adapter_invariants(schema, adapter);
}

In addition to catching incomplete schema implementation errors, it also catches violations of other Trustfall adapter invariants, such as context reordering or accidentally dropped data.

For more information, check out its docs: https://github.com/obi1kenobi/trustfall/blob/trustfall-v0.6.0/trustfall_core/src/interpreter/helpers/correctness.rs#L15-L78

Upgrading from Trustfall v0.5.x

The breaking changes should be immaterial to almost all users. Most use cases should be able to upgrade to Trustfall v0.6 without any changes to their own code.

All Merged PRs

  • Update stubgen dependency on trustfall. by @obi1kenobi in #330
  • Add bin target for trustfall_stubgen and ensure deterministic stubs. by @obi1kenobi in #331
  • Add CODEOWNERS and repo settings file. by @obi1kenobi in #332
  • Fix repo settings file. by @obi1kenobi in #333
  • Improve docs and README for trustfall_stubgen. by @obi1kenobi in #334
  • Add GitHub Actions workflow for automatically bumping dependencies. by @obi1kenobi in #335
  • Rename A-frontend and add A-playground label. by @obi1kenobi in #336
  • Improve docs for SchemaAdapter. by @obi1kenobi in #337
  • Minor docs fixes for formatting and consistency. by @obi1kenobi in #338
  • Fix dependency updater GitHub Action. by @obi1kenobi in #340
  • Allow TryIntoStruct to unpack EdgeParameters as well. by @obi1kenobi in #350
  • Only declare module tree once in trustfall_stubgen. by @obi1kenobi in #351
  • Generate more edge-handling code in trustfall_stubgen. by @obi1kenobi in #352
  • Tweak stubgen so it doesn't generate linty code. by @obi1kenobi in #353
  • Remove unnecessary lint suppressions. by @obi1kenobi in #355
  • Trigger the CI workflow manually when auto-updating dependencies. by @obi1kenobi in #358
  • Add actions: write permission to auto-updater workflow. by @obi1kenobi in #360
  • Open dependency-updating PRs with a custom access token. by @obi1kenobi in #361
  • Weekly cargo update of primary dependencies by @obi1kenobi in #362
  • Auto-update the fuzzing dependencies via an Actions workflow. by @obi1kenobi in #363
  • Use the default GITHUB_TOKEN to auto-merge PRs. by @obi1kenobi in #364
  • Better names for the automated workflow's jobs. by @obi1kenobi in #366
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #365
  • Bail out if no Cargo.lock changes are needed. by @obi1kenobi in #367
  • Print bail-out messages to stdout when updating dependencies. by @obi1kenobi in #368
  • Weekly cargo update of primary dependencies by @obi1kenobi in #370
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #369
  • add InvalidSchemaError::DuplicateFieldDefinition by @u9g in #373
  • Implement InvalidSchemaError::DuplicateTypeOrInterfaceDefinition by @u9g in #374
  • Add optimization to VertexType entrypoint in schema adapter by @u9g in #339
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #376
  • Weekly cargo update of primary dependencies by @obi1kenobi in #377
  • Update rustdoc playground schema. by @obi1kenobi in #378
  • Get rid of unnecessary clone in schema adapter by @u9g in #379
  • Update rustdoc adapter version in playground. by @obi1kenobi in #380
  • Add more example queries to rustdoc playground. by @obi1kenobi in #381
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #382
  • Weekly cargo update of primary dependencies by @obi1kenobi in #383
  • Query both Rust and crates.io crates in rustdoc playground. by @obi1kenobi in #386
  • Fix new clippy lints. by @obi1kenobi in #385
  • Enable the cli feature in trustfall_stubgen by default. by @obi1kenobi in #388
  • Check that adapters implement declared properties, edges, and coercions. by @obi1kenobi in #384
  • Generate invariant-enforcing tests in stubgen adapters. by @obi1kenobi in #389
  • Output __typename in "items with allowed lints" example rustdoc query. by @obi1kenobi in #391
  • Weekly cargo update of fuzzing dependencies by @obi1kenobi in #395
  • Weekly cargo update of primary dependencies by @obi1kenobi in #394
  • Allow querying for edge parameter default values. by @obi1kenobi in #396
  • Check adapter edge implementation for edges with default values. by @obi1kenobi in #397
  • Remove ron from dependencies and move to dev-dependencies. by @obi1kenobi in #398
  • Remove chrono from dependencies. Removes datetime value variant. by @obi1kenobi in #399
  • Include vertex Debug output in helper panic message. by @obi1kenobi in #401
  • Make FieldValue cheaper to clone by Arc-ing internally. by @obi1kenobi in #400
  • Replace various uses of vec! with arrays by @nvzqz in #402
  • Make test_field_value_into nicer to work with by @nvzqz in #403
  • Format with max small heuristics by @nvzqz in #404
  • Release Trustfall v0.6 and associated crates. by @obi1kenobi in #405

Full Changelog: trustfall-v0.5.1...trustfall-v0.6.0

trustfall_stubgen-v0.2.1

30 Jun 20:02
aaac853
Compare
Choose a tag to compare

New crate: trustfall_stubgen

Given a Trustfall schema, autogenerate a high-quality Rust adapter stub fully wired up with all types, properties, and edges referenced in the schema.

First, install this crate's CLI with: cargo install --locked trustfall_stubgen --features cli

Then generate Trustfall adapter stubs for your schema with:

trustfall_stubgen --schema <your_schema.graphql> --target <output_directory>

Under the hood this directly calls the generate_rust_stub() function from this crate. This crate can also be used as a library, so you can call that function directly from your own code without going through the CLI.

The generated Trustfall adapter stub has the following structure:

file name purpose
adapter/mod.rs connects everything together
adapter/schema.graphql contains the schema for the adapter
adapter/adapter.rs contains the adapter implementation
adapter/vertex.rs contains the vertex type definition
adapter/entrypoints.rs contains the entry points where all queries must start
adapter/properties.rs contains the property implementations
adapter/edges.rs contains the edge implementations

See an example of a generated adapter stub from this crate's test suite.

Trustfall v0.5.1

30 Jun 18:53
e415f78
Compare
Choose a tag to compare

What's Changed

Added a SchemaAdapter that allows running Trustfall queries against Trustfall schemas, like so:

{
    VertexType {
        name @output

        edge {
            edge_name: name @output

            parameter_: parameter @fold {
                name @output
            }
        }
    }
}

For a given schema, running this query returns all edges on all vertex types, together with a list of the parameters those edges take.

All Merged PRs

  • Replace lazy_static with once_cell by @nvzqz in #298
  • trustfall_core: Optimize serde_type_serializer by @nvzqz in #297
  • Use v2 resolver in virtual workspace to avoid implicit v1 default. by @obi1kenobi in #299
  • Refactor materializeWebsite in browser_based_querying by @u9g in #300
  • Use trustfall-rustdoc-adapter to power rustdoc Trustfall playground. by @obi1kenobi in #306
  • Add --all-targets flag to cargo test command. by @obi1kenobi in #307
  • Update all dependencies. by @obi1kenobi in #308
  • Add supertrait edge to rustdoc schema. by @obi1kenobi in #309
  • Add adapter for querying Trustfall schemas. by @obi1kenobi in #312
  • Replace HRTBs with DeserializeOwned by @nvzqz in #313
  • Simplify definitions and impls of Vertex-containing types by @nvzqz in #314
  • Add FieldValue::as_f64() conversion method. by @obi1kenobi in #315
  • Add two new rustdoc example queries. by @obi1kenobi in #319
  • Minor fixes to test infrastructure. by @obi1kenobi in #320
  • Set MSRV and other workspace-wide keys. by @obi1kenobi in #321
  • Improve schema error messages with undefined or cyclic type definitions. by @obi1kenobi in #322
  • Update repo dependencies. by @obi1kenobi in #323
  • Crate for generating adapter stubs given a schema. by @obi1kenobi in #324
  • Publish trustfall_stubgen and run its tests only at publish time. by @obi1kenobi in #325
  • Add version to trustfall_stubgen requirement for trustfall. by @obi1kenobi in #326
  • Support publishing new crates with our pipeline. by @obi1kenobi in #327
  • Minor typo fixes in publishing code. by @obi1kenobi in #328
  • Publish new trustfall and trustfall_core to expose SchemaAdapter. by @obi1kenobi in #329

New Contributors

Full Changelog: trustfall-v0.5.0...trustfall-v0.5.1

Trustfall v0.5.0

30 May 04:04
94c6243
Compare
Choose a tag to compare

What's Changed

  • Breaking: execute_query() now takes Arc<impl Adapter> instead of Rc<impl Adapter> for consistency with other APIs and easier use in web servers: #286
  • New resolve_coercion_using_schema() helper method to simplify implementing adapters' resolve_coercion() method.
  • TryIntoStruct trait for ergonomic result parsing into a struct, for example:
use trustfall::TryIntoStruct;

// Define a struct whose field names and types match
// those returned by a query, and derive `serde::Deserialize` on it.
#[derive(Debug, PartialEq, Eq, serde::Deserialize)]
struct Output {
    number: i64,
    text: String,
}

// Elsewhere, we run a query that outputs a `number` integer
// and a `text` string field.
let query = r#"
{
    Query {
        number @output
        text @output
    }
}
"#;
let results: Vec<_> = execute_query(schema, adapter, query, variables)
    .expect("bad query arguments")
    .map(|v| v.try_into_struct().expect("struct definition did not match query result shape"))
    .collect();

// The `try_into_struct()` call turned the query results into `Output` structs.
assert_eq!(
    vec![
        Output {
            number: 42,
            text: "the answer to everything".to_string(),
        },
    ],
    results,
);

Migrating from Trustfall v0.4

Wrap your adapters in Arc instead of Rc before calling execute_query().

All Merged PRs

  • Add TryIntoStruct trait for ergonomic result parsing into a struct. by @obi1kenobi in #275
  • FilterTypeError should display the inner error's message. by @obi1kenobi in #278
  • Update npm and Rust dependency versions. by @obi1kenobi in #279
  • Actually put url property on all webpage objects by @u9g in #280
  • Move test-related bin functionality out of trustfall_core. by @obi1kenobi in #284
  • Add helper for resolving coercions based on typename and schema. by @obi1kenobi in #283
  • Use Arc of adapter to execute queries. by @obi1kenobi in #286
  • Ensure we always output the inner error message. by @obi1kenobi in #289
  • Clearer error message. by @obi1kenobi in #291
  • Add Schema.subtypes to t-wasm by @u9g in #292
  • Broaden lifetimes in Hackernews example by @benwis in #293
  • Enable trusted publishing for Python packages. by @obi1kenobi in #294
  • Release v0.5.0 with Arc-based query execution. by @obi1kenobi in #295

New Contributors

Full Changelog: trustfall-v0.4.0...trustfall-v0.5.0

Trustfall v0.4.0

24 Apr 14:04
a9d8d78
Compare
Choose a tag to compare

What's Changed

  • Breaking: Adapter trait methods now take &self instead of &mut self to avoid reentrancy bugs: #249
  • Breaking: Released the new optimizations API: Adapter methods now take a resolve_info argument that can be used to get information about the query for the purpose of applying optimizations. In cargo-semver-checks this new API led to a 2354x speedup.
  • Many smaller bug fixes thanks to 26,000+ lines of new tests and test code.

Migrating from Trustfall v0.3

Replace all BasicAdapter and Adapter method receivers with &self instead of &mut self.

If you need mutability, you need to do BOTH of these things:

  • advance the ContextIterator input iterator before doing any mutation, to avoid reentrancy bugs
  • use RefCell around your Adapter or BasicAdapter's mutable state, making sure to not hold its mutable borrow across operations on the input ContextIterator in order to avoid reentrancy bugs

All Merged PRs

New Contributors

Full Changelog: trustfall-v0.3.4...trustfall-v0.4.0

trustfall_wasm-v0.1.0-533911d

15 Jul 23:56
Compare
Choose a tag to compare