Skip to content

Commit

Permalink
Add Makefile and test coverage
Browse files Browse the repository at this point in the history
The new script, `.ci/test-cover`, handles the test coverage, installing
needed dependencies and generating the report.

Rename the "Lint Code" workflow job to "Lint and Cover" and add steps to
generate and publish a coverage report. Also fix test failures due to
missing `postgresql.auto.conf` file by removing the data directory from
the `targets` directory, so it won't be cached. This gets all the tests
passing consistently.

Add common tasks to the `Makefile`, including building, installing, and
testing entirely based on the version reported by `pg_config`.

Add license and code coverage badges to the README, and document using
`make` to build and install the extension.

Also, simplify the `V2019_09` and `V2020_12` draft names to `V2019` and
`V2020`.
  • Loading branch information
theory committed Apr 5, 2024
1 parent b9ce030 commit b4eca96
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 35 deletions.
5 changes: 2 additions & 3 deletions .ci/apt-install-postgres
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

# Determine the version of PostgreSQL (and append .0 to a single digit)
# Determine the version of PostgreSQL.
if [ -z ${1+x} ]; then
echo "ERROR: No PostgreSQL version number passed to $0"
echo "Usage:"
Expand All @@ -11,12 +11,11 @@ if [ -z ${1+x} ]; then
fi

PGVERSION=${1:-}
[[ $PGVERSION =~ ^[0-9]$ ]] && PGVERSION+=.0

apt-get update
apt-get install -y --no-install-recommends \
build-essential clang llvm llvm-dev llvm-runtime cmake \
ca-certificates gnupg2 curl libicu-dev libxml2 locales ssl-cert
ca-certificates gnupg2 curl libicu-dev libxml2 locales ssl-cert libxml2-utils
apt-get -y purge postgresql-client-common

curl https://salsa.debian.org/postgresql/postgresql-common/-/raw/master/pgdg/apt.postgresql.org.sh -O --output-dir /usr/local/bin/
Expand Down
48 changes: 48 additions & 0 deletions .ci/test-cover
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash

set -e

# Determine the version of PostgreSQL.
if [ -z ${1+x} ] || [ -z ${2+x} ]; then
echo "ERROR: No PostgreSQL OR PGRX version number passed to $0"
echo "Usage:"
echo " $0 \$PG_VERSION \$PGRX_VERSION"
exit 2
fi

PGVERSION=${1:-}
PGRXVERSION=${2:-}

# Must be absolute to get all the data files from Postgres, too.
DESTDIR="${PWD}/target/cover"

rustup component add llvm-tools
cargo install grcov "cargo-pgrx@${PGRXVERSION}"

export RUSTFLAGS="-Cinstrument-coverage"
if [ "$(uname -o)" = "Darwin" ]; then
export RUSTFLAGS="-Clink-arg=-Wl,-undefined,dynamic_lookup $RUSTFLAGS"
fi

export LLVM_PROFILE_FILE="${DESTDIR}/default_%m_%p.profraw"
cargo test --all --no-default-features --features "pg${PGVERSION} pg_test" -- --nocapture

grcov "${DESTDIR}" \
--ignore '**/clang-sys*/**' \
--ignore '**/pgrx-pg-sys*/**' \
--ignore "$HOME/.cargo/**" \
--ignore-not-existing \
--excl-start 'begin_impossible!' \
--excl-stop 'end_impossible!' \
--llvm \
--binary-path "target/debug/" \
-s . \
--branch \
-o "${DESTDIR}" \
--output-types html,cobertura

xmllint --xpath "concat('Coverage: ', 100 * string(//coverage/@line-rate), '%')" "${DESTDIR}/cobertura.xml"

if [ "$(uname -o)" = "Darwin" ] && [ -z "$CI" ]; then
open "${DESTDIR}/html/index.html"
fi
26 changes: 19 additions & 7 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:

jobs:
lint:
name: 🔎 Lint Code
name: 🔎 Lint and Cover
runs-on: ubuntu-latest
env: { PGVERSION: 16 }
steps:
Expand All @@ -20,13 +20,24 @@ jobs:
- name: Install Postgres
run: sudo ./.ci/apt-install-postgres ${{ env.PGVERSION }}
- name: Install pgrx
run: cargo install cargo-pgrx --locked --version "$(perl -ne '/^pgrx\s+=\s"=?([^"]+)/ && do { print $1; exit }' Cargo.toml)"
run: cargo install cargo-pgrx --locked --version "$(make pgrx-version)"
- name: Initialize pgrx
run: cargo pgrx init --pg${{ env.PGVERSION }}="$(which pg_config)"
- name: Cargo format
run: cargo fmt --all --check
- name: Clippy
run: cargo clippy --features pg${{ env.PGVERSION }} --no-default-features
- name: Generate Coverage
env: { RUST_BACKTRACE: 1, PGUSER: postgres }
run: make cover
- name: Publish Coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: tembo-io/pg-jsonschema
files: target/cover/cobertura.xml
- name: Remove Data Diretory
run: rm -rf target/pgrx-test-data-${{ env.PGVERSION }}

test:
runs-on: ubuntu-latest
Expand All @@ -44,13 +55,14 @@ jobs:
run: sudo ./.ci/apt-install-postgres ${{ matrix.pg }}
- name: Setup Rust Cache
uses: Swatinem/rust-cache@v2
- run: env
- name: Install pgrx
run: cargo install cargo-pgrx --locked --version "$(perl -ne '/^pgrx\s+=\s"=?([^"]+)/ && do { print $1; exit }' Cargo.toml)"
run: cargo install cargo-pgrx --locked --version "$(make pgrx-version)"
- name: Remove Data Diretory
run: rm -rf target/pgrx-test-data-${{ matrix.pg }}
- name: Initialize pgrx
run: cargo pgrx init --pg${{ matrix.pg }}="$(which pg_config)"
- name: Run the tests
env:
RUST_BACKTRACE: 1
PGUSER: postgres
env: { RUST_BACKTRACE: 1, PGUSER: postgres }
run: cargo test --all --no-default-features --features "pg${{ matrix.pg }} pg_test" -- --nocapture
- name: Remove Data Diretory
run: rm -rf target/pgrx-test-data-${{ matrix.pg }}
34 changes: 34 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
PG_CONFIG ?= $(shell which pg_config)
PGRXV="$(shell perl -nE '/^pgrx\s+=\s"=?([^"]+)/ && do { say $$1; exit }' Cargo.toml)"
PGV=$(shell perl -E 'shift =~ /(\d+)/ && say $$1' "$(shell $(PG_CONFIG) --version)")

.DEFAULT_GOAL: package # Build jsonshcmea for the PostgreSQL cluster identified by pg_config.
package:
@cargo pgrx package --pg-config "$(PG_CONFIG)"

.PHONY: install # Install jsonschema into the PostgreSQL cluster identified by pg_config.
install:
@cargo pgrx install --release --pg-config "$(PG_CONFIG)"

.PHONY: test # Run the full test suite against the PostgreSQL version identified by pg_config.
test:
@cargo test --all --no-default-features --features "pg$(PGV) pg_test" -- --nocapture

.PHONY: install-check # An alias for the test target for PGXS compatability.
install-check: test

.PHONY: cover # Run cover tests and generate & open a report.
cover:
@./.ci/test-cover "$(PGV)" "$(PGRXV)"

.PHONY: pg-version # Print the current PGRX version from Cargo.toml
pgrx-version:
@echo $(PGRXV)

.PHONY: pg-version # Print the current Postgres version reported by pg_config.
pg-version: Cargo.toml
@echo $(PGV)

## cleaan: Remove build artifacts and intermediate files.
clean: target
@cargo clean
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
JSON Schema Postgres Extension
==============================

[![PGXN version](https://badge.fury.io/pg/jsonschema.svg)](https://badge.fury.io/pg/jsonschema)
[![🧪 Lint and Test](https://github.com/tembo-io/pg-jsonschema/actions/workflows/lint-and-test.yml/badge.svg)](https://github.com/tembo-io/pg-jsonschema/actions/workflows/lint-and-test.yml)
[![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "⚖️ MIT License")
[![PGXN Version](https://badge.fury.io/pg/jsonschema.svg)](https://badge.fury.io/pg/jsonschema "⚙️ PGXN Version")
[![Build Status](https://github.com/tembo-io/pg-jsonschema/actions/workflows/lint-and-test.yml/badge.svg)](https://github.com/tembo-io/pg-jsonschema/actions/workflows/lint-and-test.yml "🧪 Lint and Test")
[![Code Coverage](https://codecov.io/gh/tembo-io/pg-jsonschema/graph/badge.svg?token=DIFED324ZY)](https://codecov.io/gh/tembo-io/pg-jsonschema "📊 Code Coverage")

This library provides the `jsonschema` extension for validating JSON and JSONB
against a [JSON Schema] in Postgres. It supports the following [specification
Expand Down Expand Up @@ -32,19 +34,19 @@ Then use `cargo` to install `pgrx`:
cargo install --locked cargo-pgrx --version 0.11.3
```

Now build jsonschema against a working PostgreSQL server (including
development libraries and the [pg_config] utility). Here's an example
using PostgreSQL 15:
Now build and jsonschema against a working PostgreSQL server, including
development libraries and the [pg_config], which must be in the path:

``` sh
cargo pgrx init --pg15="$(which pg_config)"
make
make install
```

Adjust the `--pg15` option to your PostgreSQL version. Then build and install
`jsonschema`:
To build with a different `pg_config`, pass it to `make`:

```sh
cargo pgrx install --release
``` sh
make PG_CONFIG=/path/to_pg_config
make install PG_CONFIG=/path/to_pg_config
```

Once jsonschema is installed, you can add it to a database. Simply connect to
Expand Down
6 changes: 3 additions & 3 deletions doc/jsonschema.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ the default), set the `jsonschema.default_draft` configuration to your
preferred default. To set the default for the current session to 2019-09, run:

``` postgres
SET jsonschema.default_draft TO 'V2019_09';
SET jsonschema.default_draft TO 'V2019';
```

For a system-wide default, set it in the `postgresql.conf` file:
Expand All @@ -80,8 +80,8 @@ The supported values are:
* `V4`: Draft for `http://json-schema.org/draft-04/schema`
* `V6`: Draft for `http://json-schema.org/draft-06/schema`
* `V7`: Draft for `http://json-schema.org/draft-07/schema`
* `V2019_09`: Draft for `https://json-schema.org/draft/2019-09/schema`
* `V2020_12`: Draft for `https://json-schema.org/draft/2020-12/schema`
* `V2019`: Draft for `https://json-schema.org/draft/2019-09/schema`
* `V2020`: Draft for `https://json-schema.org/draft/2020-12/schema`

Functions
---------
Expand Down
24 changes: 12 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ enum Draft {
/// Draft for `http://json-schema.org/draft-07/schema`
V7,
/// Draft for `https://json-schema.org/draft/2019-09/schema`
V2019_09,
V2019,
/// Draft for `https://json-schema.org/draft/2020-12/schema`
V2020_12,
V2020,
}

// Convert Draft into boon::Draft.
Expand All @@ -196,14 +196,14 @@ impl Into<boon::Draft> for Draft {
Draft::V4 => boon::Draft::V4,
Draft::V6 => boon::Draft::V6,
Draft::V7 => boon::Draft::V7,
Draft::V2019_09 => boon::Draft::V2019_09,
Draft::V2020_12 => boon::Draft::V2020_12,
Draft::V2019 => boon::Draft::V2019_09,
Draft::V2020 => boon::Draft::V2020_12,
}
}
}

// GUC fetches the jsonschema.default_draft GUC value.
static GUC: pgrx::GucSetting<Draft> = pgrx::GucSetting::<Draft>::new(Draft::V2020_12);
static GUC: pgrx::GucSetting<Draft> = pgrx::GucSetting::<Draft>::new(Draft::V2020);

// initialize the jsonschema.default_draft GUC.
fn init_guc() {
Expand Down Expand Up @@ -318,8 +318,8 @@ mod tests {
assert_eq!(boon::Draft::V4, Draft::V4.into());
assert_eq!(boon::Draft::V6, Draft::V6.into());
assert_eq!(boon::Draft::V7, Draft::V7.into());
assert_eq!(boon::Draft::V2019_09, Draft::V2019_09.into());
assert_eq!(boon::Draft::V2020_12, Draft::V2020_12.into());
assert_eq!(boon::Draft::V2019_09, Draft::V2019.into());
assert_eq!(boon::Draft::V2020_12, Draft::V2020.into());
}

#[test]
Expand Down Expand Up @@ -862,13 +862,13 @@ mod tests {
#[pg_test]
fn test_draft_schema_guc() -> spi::Result<()> {
let draft = Spi::get_one("SELECT current_setting('jsonschema.default_draft')")?;
assert_eq!(Some("V2020_12"), draft);
assert_eq!(Draft::V2020_12, GUC.get());
assert_eq!(Some("V2020"), draft);
assert_eq!(Draft::V2020, GUC.get());

Spi::run("SELECT set_config('jsonschema.default_draft', 'V2019_09', false)")?;
Spi::run("SELECT set_config('jsonschema.default_draft', 'V2019', false)")?;
let draft = Spi::get_one("SELECT current_setting('jsonschema.default_draft')")?;
assert_eq!(Some("V2019_09"), draft);
assert_eq!(Draft::V2019_09, GUC.get());
assert_eq!(Some("V2019"), draft);
assert_eq!(Draft::V2019, GUC.get());

Spi::run("SET jsonschema.default_draft TO 'V4'")?;
let draft = Spi::get_one("SHOW jsonschema.default_draft")?;
Expand Down

0 comments on commit b4eca96

Please sign in to comment.