Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build-local/
bblocks-config-local.yml
bblocks-config-local.yaml
.volumes
*.bak
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Note: see issue #11 — EarthCODE example URLs currently 404 and block the register build.
# Open Science Building Blocks

The repository documents a set of [OGC Building Blocks](https:blocks.ogc.org). for Open Science, which in turn leverage reusable ontologies, schemas, APIs etc. from published OGC standards.
Expand Down
13 changes: 13 additions & 0 deletions _sources/prov-processing-step/bblock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "Geospatial Processing Step Provenance",
"abstract": "A profile of the PROV-O building block constrained to the description of a single geospatial processing step, with a required link to a registered process type.",
"status": "under-development",
"dateTimeAddition": "2026-08-05T00:00:00Z",
"itemClass": "schema",
"version": "0.1.0",
"dateOfLastChange": "2026-08-05",
"maturity": "development",
"scope": "unstable",
"tags": ["provenance", "prov-o", "processing", "ospd"],
"dependsOn": ["ogc.ogc-utils.prov"]
}
20 changes: 20 additions & 0 deletions _sources/prov-processing-step/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Geospatial Processing Step Provenance

This building block profiles `ogc-utils.prov` down to a single unit: one
geospatial processing step.

PROV-O is deliberately general. Any valid PROV document is a valid description
of a processing step, which makes validation weak and cross-platform comparison
hard.

OGC API - Processes Part 5 (draft 26-038) narrows this for job provenance: a
job entity, a process entity, an activity joining them, and input/output
artifacts carrying roles. This profile follows that shape.

Part 5 does not define any link from a process to a registered process type.
This profile makes that link required, via the processType property. It is the
point at which the OSPD 2026 profile-plus-register pattern closes: the profile
gives the structure, the register gives the controlled term.

Under development as part of OSPD 2026, deliverable D104 (Aganitha Space
Technologies, Workflow Profiler).
45 changes: 45 additions & 0 deletions _sources/prov-processing-step/examples.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
- title: Reprojection of a gridded precipitation dataset
description: >-
A single reprojection step, transforming a gridded precipitation dataset
from a geographic CRS to a projected CRS. Reprojection was the one
operation common to every workflow presented at the OSPD 2026 kick-off,
which makes it the natural first candidate for the process-type register.
snippets:
- language: json
code: |
{
"id": "urn:aganitha:step:reproject:20260805T101500Z",
"provType": "Activity",
"processType": "https://example.org/ospd/process-types/reprojection",
"label": "Reproject precipitation grid to national projected CRS",
"startedAtTime": "2026-08-05T10:15:00Z",
"endedAtTime": "2026-08-05T10:15:42Z",
"used": ["urn:aganitha:dataset:precip-daily-geographic"],
"generated": ["urn:aganitha:dataset:precip-daily-projected"],
"qualifiedUsage": [
{
"entity": "urn:aganitha:dataset:precip-daily-geographic",
"hadRole": "https://example.org/ospd/roles/sourceGrid"
}
],
"wasAssociatedWith": ["https://gdal.org/"],
"parameters": {
"sourceCrs": "EPSG:4326",
"targetCrs": "EPSG:7755",
"resamplingMethod": "bilinear"
}
}

- title: Minimal conforming step
description: >-
The smallest document that satisfies this profile.
snippets:
- language: json
code: |
{
"id": "urn:example:step:0001",
"provType": "Activity",
"processType": "https://example.org/ospd/process-types/reprojection",
"used": ["urn:example:input:0001"],
"generated": ["urn:example:output:0001"]
}
82 changes: 82 additions & 0 deletions _sources/prov-processing-step/schema.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
$schema: https://json-schema.org/draft/2020-12/schema
title: Geospatial Processing Step Provenance
description: >-
A single geospatial processing step, expressed as a constrained profile of
PROV-O. Inputs and outputs are entity references; the role each played is
expressed through prov:qualifiedUsage rather than inline, so the profile
stays compatible with the PROV-O object model.

allOf:
- $ref: bblocks://ogc.ogc-utils.prov
- type: object
required:
- id
- processType
- used
- generated
properties:

id:
description: Stable identifier for this processing step activity.
type: string

processType:
description: >-
Identifier of the registered process type this step is an instance
of. This is the link that PROV-O and OGC API - Processes Part 5 do
not themselves provide.
type: string

label:
type: string

startedAtTime:
type: string
format: date-time

endedAtTime:
type: string
format: date-time

used:
description: Entities consumed by this step.
type: array
minItems: 1
items:
type: string

generated:
description: Entities produced by this step.
type: array
minItems: 1
items:
type: string

qualifiedUsage:
description: >-
Which declared input slot of the process type each consumed entity
occupied. Makes two runs of the same process type comparable.
type: array
items:
type: object
required:
- entity
- hadRole
properties:
entity:
type: string
hadRole:
type: string

wasAssociatedWith:
type: array
items:
type: string

parameters:
description: >-
Parameter values that determined the behaviour of this step. Keys
SHOULD be drawn from the parameter terms declared by the registered
process type.
type: object
additionalProperties: true
1 change: 1 addition & 0 deletions bblocks-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ imports:
- https://ogcincubator.github.io/bblocks-ogcapi-processes
- https://ogcincubator.github.io/prov-cwl/
- https://ogcincubator.github.io/bblocks-wf4ever/
- https://ogcincubator.github.io/bblock-prov-schema/
- https://ogcincubator.github.io/bblocks-stac
- https://ogcincubator.github.io/cross-domain-model

Expand Down
3 changes: 3 additions & 0 deletions build-devel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash
# Process building blocks using the development (rolling) image build
BBP_IMAGE_TAG=develop exec "$(dirname "$0")/build.sh" "$@"
2 changes: 1 addition & 1 deletion build.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if [ -f '.volumes' ]; then
fi
done < .volumes)
fi
docker run --pull=always --rm --workdir /workspace -v "$(pwd):/workspace" ${VOLUMES} \
docker run -it --pull=always --rm --workdir /workspace -v "$(pwd):/workspace" ${VOLUMES} \
ghcr.io/opengeospatial/bblocks-postprocess \
--clean true --base-url http://localhost:9090/register/

Expand Down
148 changes: 148 additions & 0 deletions create-clean-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env bash
# Creates a "clean" branch of a Building Blocks register fork, excluding all
# changes in the build/ directory (and fork-only config overrides), so that
# it can be used to open a Pull Request against the upstream register without
# generated-artifact merge conflicts.
#
# See https://opengeospatial.github.io/bblocks-docs/build/contribution for details.

usage() {
echo "Usage: $0 [-u upstreamRemote] [-f forkRemote] [-b upstreamBranch] [-d buildDirectory] [-t tempBranch] [-P]"
echo
echo "Options:"
echo " -u Upstream remote name (default: 'fork-parent')"
echo " -f Fork remote name (default: 'origin')"
echo " -b Upstream branch (default: 'main' or 'master')"
echo " -d Build directory (default: 'build')"
echo " -t Name for the temporary clean branch (default: randomly generated)"
echo " -P Do not push to remote"
echo " -h Show this help message"
exit 1
}

UPSTREAM_REMOTE=fork-parent
BUILD_DIR=build
FORK_REMOTE=origin
UPSTREAM_BRANCH=
PUSH_TO_REMOTE=1
TMP_BRANCH=

while getopts "u:f:b:d:t:Ph" opt; do
case $opt in
u) UPSTREAM_REMOTE="$OPTARG" ;;
f) FORK_REMOTE="$OPTARG" ;;
b) UPSTREAM_BRANCH="$OPTARG" ;;
d) BUILD_DIR="$OPTARG" ;;
P) PUSH_TO_REMOTE=;;
t) TMP_BRANCH="$OPTARG";;
h) usage ;;
\?) usage ;;
esac
done

trap_add() {
local cmd="$1"
# shellcheck disable=SC2064
trap "${cmd};$(trap -p EXIT | cut -d"'" -f2)" EXIT
}

if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "This script must be run inside a git directory."
echo "If you are using Docker, check you have mounted the right volumes."
exit 1
fi

if ! ( git diff --quiet && git diff --cached --quiet ); then
echo "There are pending changes. Please commit or stash them before continuing."
exit 1
fi

# Detect git-filter-repo
if [[ -x "./git-filter-repo" ]]; then
FILTER_REPO_CMD="./git-filter-repo"
elif command -v git-filter-repo >/dev/null 2>&1; then
FILTER_REPO_CMD="git-filter-repo"
elif git filter-repo --help >/dev/null 2>&1; then
FILTER_REPO_CMD="git filter-repo"
else
# Download the latest released version to a temp location
LATEST_TAG=$(curl -sSfL https://api.github.com/repos/newren/git-filter-repo/releases/latest \
| sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
if [[ -z "$LATEST_TAG" ]]; then
echo "Could not determine the latest git-filter-repo release." >&2
exit 1
fi
TMP_DIR=$(mktemp -d)
FILTER_REPO_CMD="$TMP_DIR/git-filter-repo"
if ! curl -sSfL -o "$FILTER_REPO_CMD" \
"https://raw.githubusercontent.com/newren/git-filter-repo/${LATEST_TAG}/git-filter-repo"; then
echo "Failed to download git-filter-repo ${LATEST_TAG}." >&2
rm -rf "$TMP_DIR"
exit 1
fi
chmod +x "$FILTER_REPO_CMD"
trap_add "rm -rf \"$TMP_DIR\""
fi
echo "Using git-filter-repo command: $FILTER_REPO_CMD"

CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
trap_add "git checkout \"$CURRENT_BRANCH\" >/dev/null 2>/dev/null"

UPSTREAM_URL=$(git remote get-url "$UPSTREAM_REMOTE" 2>/dev/null)
if [[ $? -ne 0 || -z "$UPSTREAM_URL" ]]; then
echo "Upstream remote '$UPSTREAM_REMOTE' does not exist. Please add it first by running:"
echo " git remote add ${UPSTREAM_REMOTE} git@github.com:username/repo.git"
exit 1
fi
echo "Using upstream remote: ${UPSTREAM_REMOTE} / ${UPSTREAM_URL}"

FORK_URL=$(git remote get-url "$FORK_REMOTE" 2>/dev/null)
if [[ $? -ne 0 || -z "$FORK_URL" ]]; then
echo "Fork (local) remote '$FORK_REMOTE' does not exist."
exit 1
fi
echo "Using fork remote: ${FORK_REMOTE} / ${FORK_URL}"

set -euo pipefail
git fetch "${UPSTREAM_REMOTE}"

if [[ -z "$TMP_BRANCH" ]]; then
TMP_BRANCH="clean-pr-$(date +%s).$RANDOM"
fi
git checkout -b "$TMP_BRANCH"

if [[ -z "${UPSTREAM_BRANCH}" ]]; then
if git rev-parse --verify --quiet "${UPSTREAM_REMOTE}"/main >/dev/null; then
UPSTREAM_BRANCH=main
else
UPSTREAM_BRANCH=master
fi
fi
echo "Using upstream branch: ${UPSTREAM_BRANCH}"

$FILTER_REPO_CMD --path "${BUILD_DIR}" --path .fork --path bblocks-config-override.yml --path bblocks-config-override.yaml --invert-paths --force \
--refs "${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}..HEAD"

if [[ -n "$PUSH_TO_REMOTE" ]]; then
git push "${FORK_REMOTE}" "${TMP_BRANCH}"
echo "Branch created and changed pushed"

# Strip a trailing .git suffix, then split "owner/repo" on the last slash/colon.
UPSTREAM_PATH="${UPSTREAM_URL#git@github.com:}"
UPSTREAM_PATH="${UPSTREAM_PATH#https://github.com/}"
UPSTREAM_PATH="${UPSTREAM_PATH%.git}"

FORK_PATH="${FORK_URL#git@github.com:}"
FORK_PATH="${FORK_PATH#https://github.com/}"
FORK_PATH="${FORK_PATH%.git}"

PR_URL="https://github.com/${UPSTREAM_PATH}/compare/${UPSTREAM_BRANCH}...${FORK_PATH%%/*}:${FORK_PATH#*/}:${TMP_BRANCH}?expand=1"
echo ""
echo "========"
echo "You can use the following URL to create the Pull Request:"
echo " ${PR_URL}"
echo "========"
echo ""
else
echo "Branch '${TMP_BRANCH}' created - push disabled"
fi
Empty file modified view.sh
100644 → 100755
Empty file.