Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
f026881
Add sample data structure, local validation scripts, and documentation
e-lo Jul 14, 2023
227c973
update template data
e-lo Jul 14, 2023
343060f
Working tests and scripts
e-lo Jul 22, 2023
ad10dde
Add check for if frictionless is installed
e-lo Jul 22, 2023
45c116a
add documentation about validate-datapackage and validate-datapackage…
e-lo Jul 22, 2023
eee0fd9
old code removed
e-lo Jul 24, 2023
a280001
Update README to be consistent
e-lo Jul 24, 2023
0223c9f
Try capturing results JSON more predictably
SorenSpicknall Aug 24, 2023
1b594aa
Trim after split
SorenSpicknall Aug 24, 2023
c257a7a
Fix trim() call
SorenSpicknall Aug 24, 2023
d6030a4
Remove trim altogether
SorenSpicknall Aug 24, 2023
ab17492
Log before presumed failure point
SorenSpicknall Aug 24, 2023
e30fefb
Additional logging
SorenSpicknall Aug 24, 2023
3318e80
Confirm inaccurate passage suspicion
SorenSpicknall Aug 24, 2023
888958a
Some extra confirmation logging
SorenSpicknall Aug 24, 2023
9cfdbe7
Log in the correct place
SorenSpicknall Aug 24, 2023
ab1c13a
Log full text of samples variable
SorenSpicknall Aug 24, 2023
5a9f22f
Move logging
SorenSpicknall Aug 24, 2023
8519cb6
Echo instead of log
SorenSpicknall Aug 24, 2023
ddea992
Echo variable, not string literal
SorenSpicknall Aug 24, 2023
1d58646
Echo in previous task, just to be sure
SorenSpicknall Aug 24, 2023
0351cf3
Try pushing different name
SorenSpicknall Aug 24, 2023
87a7723
Ref as variable
SorenSpicknall Aug 24, 2023
1174d84
Explicitly set output variable names
SorenSpicknall Aug 25, 2023
d3a0a07
Additional echo for diagnostic purposes
SorenSpicknall Aug 25, 2023
93c169f
Try setting file destination differently
SorenSpicknall Aug 25, 2023
16cdd4b
Echo file reference
SorenSpicknall Aug 25, 2023
9b6dee6
Experiment with upgraded attrs install
SorenSpicknall Aug 25, 2023
716b612
Call validation directly to surface detailed error
SorenSpicknall Aug 25, 2023
0d3d28d
Substitute development files for testing purposes
SorenSpicknall Aug 25, 2023
08b5a76
tree -> blob
SorenSpicknall Aug 25, 2023
ae1a08a
Raw content ref
SorenSpicknall Aug 25, 2023
125739b
Multi-line string env output from action
SorenSpicknall Aug 25, 2023
27ecbd9
Added quotes
SorenSpicknall Aug 25, 2023
23d5506
Echo results before assignment
SorenSpicknall Aug 25, 2023
565e9e5
Use direct env write strategy
SorenSpicknall Aug 25, 2023
300fa9d
Log samples and results
SorenSpicknall Aug 25, 2023
7e78e83
Echo results at end of validation
SorenSpicknall Aug 25, 2023
9a46d52
Try to get correct format for Frictionless output to env
SorenSpicknall Aug 25, 2023
0f12c00
Indentation fix
SorenSpicknall Aug 25, 2023
a64636a
Different echo format
SorenSpicknall Aug 25, 2023
0d48726
Echo instead of cat
SorenSpicknall Aug 25, 2023
45ed933
Log correct things
SorenSpicknall Aug 25, 2023
282361d
Echo at end of previous task once more
SorenSpicknall Aug 25, 2023
599e326
Play around with cat format
SorenSpicknall Aug 25, 2023
fccedfe
Check GITHUB_ENV
SorenSpicknall Aug 25, 2023
ed9814c
Try writing to output instead of env
SorenSpicknall Aug 25, 2023
0b65469
Change most refs back to main
SorenSpicknall Aug 25, 2023
38183ab
Re-add direct validation to surface new error
SorenSpicknall Aug 25, 2023
8e96998
Attempting to ID detailed error for failed validations
SorenSpicknall Aug 25, 2023
cb925f2
Secondary reference
SorenSpicknall Aug 25, 2023
2f8141c
Different echo format
SorenSpicknall Aug 25, 2023
04bebbe
Troubleshooting validationerror status
SorenSpicknall Aug 25, 2023
6a2bfe1
Debug flag
SorenSpicknall Aug 25, 2023
81e1442
Switch back to dev URL refs
SorenSpicknall Aug 25, 2023
fd8a7f9
Experiment with updated column list
SorenSpicknall Aug 25, 2023
2312ad7
Pass validation errors to surface JSON successfully
SorenSpicknall Aug 25, 2023
143f3a6
Escape single quotes in results
SorenSpicknall Aug 25, 2023
dd10ce0
Attempt different quote scheme
SorenSpicknall Aug 25, 2023
93ef96c
Be rid of single quotes
SorenSpicknall Aug 25, 2023
a7ca23f
Try to institute and replace single quote escape around JSON rules
SorenSpicknall Aug 25, 2023
d038ffc
Get rid of single quotes at source
SorenSpicknall Aug 25, 2023
3793dab
Try parse step beforehand
SorenSpicknall Aug 25, 2023
08f3ac4
Remove invalid JSON escape
SorenSpicknall Aug 25, 2023
ccffa17
Modify substitution
SorenSpicknall Aug 25, 2023
693729e
Try to create valid JSON
SorenSpicknall Aug 25, 2023
10e659c
Different apostrophe handling
SorenSpicknall Aug 25, 2023
a704037
Escape characters for values proclamation
SorenSpicknall Aug 25, 2023
aa083e1
Additional escape logic
SorenSpicknall Aug 25, 2023
a0d9c85
Better sequence match
SorenSpicknall Aug 25, 2023
fbf4837
Construct last array element properly
SorenSpicknall Aug 25, 2023
95a369e
Comma handling
SorenSpicknall Aug 25, 2023
c48534f
Get rid of nagging comma
SorenSpicknall Aug 25, 2023
09a70e5
Last comma change
SorenSpicknall Aug 25, 2023
4806405
Demonstrate passing validation
SorenSpicknall Aug 25, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/validate_package_schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
uses: TIDES-transit/json-schema-validator@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
json_schema: spec/tides-data-package.json
json_schema: spec/tides-datapackage-profile.json
json_path_pattern: ^spec/tides\.spec\.json$
send_comment: false
clear_comments: false
32 changes: 24 additions & 8 deletions .github/workflows/validate_samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,47 @@ jobs:
run: |
pwd
samples=$(find ./samples -type d -name 'TIDES')
echo "{name}={value}" >> $GITHUB_OUTPUT
echo $samples
echo "samples=${samples}" >> $GITHUB_OUTPUT
- name: Validate Sample Data
id: validation
run: |
samples=(${{ steps.sample_folders.outputs.samples }})
results=""
results="{\"values\": ["
result=""
for sample in "${samples[@]}"; do
result=$(frictionless validate --schema-sync "$sample/datapackage.json" --json)
results+="$result\n"
results+="$result"
result=$(frictionless validate --schema-sync "${sample}/datapackage.json" --json) || true
result="${result//\'s/}"
result="${result//\\\"/\\\\\"}"
result="$result,"
done
echo "{name}=${results}" >> $GITHUB_ENV

result="${result%?}"
results+="$result"
results+="]}"

echo "RESULTS<<EOF" >> $GITHUB_OUTPUT
echo ${results} >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const samples = '${{ env.samples }}'.trim().split('\n');
const results = '${{ env.results }}'.trim().split('\n');
console.log("Begin sample construction")
const samples = '${{ steps.sample_folders.outputs.samples }}'.split('\n');
const results = JSON.parse('${{ steps.validation.outputs.results }}');
let comment = `**Data Validation Report**\n\n`;
comment += '| Sample | Status |\n';
comment += '| ------ | ------ |\n';
console.log("Constructed header")
for (let i = 0; i < samples.length; i++) {
console.log(samples[i])
console.log(results[i])
const sample = samples[i];
const result = JSON.parse(results[i]);
const result = results.values[i];
let status = '';
if (result.valid) {
status = ':heavy_check_mark:';
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate_table_schemas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ jobs:
json_schema: spec/table-schema.json
json_path_pattern: ^spec/.*\.schema\.json$
send_comment: false
clear_comments: false
clear_comments: false
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ By making any contribution to the projects, contributors self-certify to the [Co

1. [Create a branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository) to work on a new issue (or checkout an existing one where the issue is being worked on).
2. Make your changes.
3. Run `/tests/test_all` script to check and fix formatting, validate schemas, and build documentation locally to preview
4. [Commit](#commits) your work in `git`
5. `push` your changes to Github and submit a [`pull request`](#pull-requests)
3. Run `tests/test_local_spec` script to check and fix formatting, validate profile and schemas with frictionless and with each other, and confirm that documentation can be built locally.
4. Run `tests/test_samples_to_local` script to check if samples conform to any changes to the spec.
5. [Commit](#commits) your work in `git`
6. `push` your changes to Github and submit a [`pull request`](#pull-requests)

### Issues

Expand Down Expand Up @@ -105,7 +106,7 @@ When a change is pushed to the TIDES specification repository, Github Actions de
| **Name** | **What it does** |
| -------- | ----------------- |
| GitHub Actions | Runs following workflow on each push to the TIDES github repository: /.github/workflows/docs.yml |
| mike | runs mkdocs and puts output in a folder in gh_pages branch which corresponds to the name of the branch (i.e. main, develop, pr-163, etc) <br> For new branches with documentation, adds an entry in `versions.json` |
| mike | runs mkdocs and puts output in a folder in gh_pages branch which corresponds to the name of the branch (i.e. main, develop, pr-163, etc) <br> For new branches with documentation, adds an entry in `versions.json` |
| `mkdocs` | Package which generates documentation from markdown and code |

??? info "Overview of Documentation Building Process"
Expand All @@ -116,7 +117,7 @@ When a change is pushed to the TIDES specification repository, Github Actions de
subgraph mkdocs["<b>mkdocs:</b> run on execution of mike"]
md_mike["mike"] -->|runs for current branch| md_mkdocs["mkdocs"]
md_mkdocs.yml["mkdocs.yml"] -->|specifieds parameters| md_mkdocs["mkdocs"]
md_mkdocs_macros["mkdocs-macros"] -->|"plugin for"| md_mkdocs["mkdocs"]
md_mkdocs_macros["mkdocs-macros"] -->|"plugin for"| md_mkdocs["mkdocs"]
main.py[/"main.py"/] -->|defines macros in code available for| md_mkdocs_macros["mkdocs-macros"]
end

Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,35 @@ Human-friendlier documentation is auto-generated and available at:
- [Architecture](https://tides-transit.github.io/TIDES/main/architecture)
- [Table Schemas](https://tides-transit.github.io/TIDES/main/tables)

### Data Package

Directories with TIDES data must contain metadata in a [`datapackage.json`](https://tides-transit.github.io/TIDES/main/datapackage) file in a format compliant with the [`tides-datapackage-profile`](https://tides-transit.github.io/TIDES/main/datapackage) of a [`frictionless data package`](https://specs.frictionlessdata.io/data-package/).

[`/samples/template/datapackage.json`](https://raw.githubusercontent.com/TIDES-transit/TIDES/main/samples/template/datapackage.json) has a template datapackage which can be used.

## Sample Data

[Sample data](https://tides-transit.github.io/TIDES/main/samples) can be found in the `/samples` directory, with one directory for each sample.

### Template

Templates of `datapackage.json` and each TIDES file type are located in the `/samples/template` directory.

## Validating TIDES data

TIDES data with a valid [`datapackage.json`](#data-package) can be easily validated using the [frictionless framework](https://framework.frictionlessdata.io/), which can be installed and invoked as follows:

```bash
pip install frictionless
frictionless validate --schema-sync path/to/your/datapackage.json
```

Several other validation scripts and tools with more flexibility such as validating to the canonical, named version or a local spec can be found in the `/bin` directory, with usage available with the `--help` flag.

```bash
bin/validate-datapackage [-v remote_spec_ref | -l local_spec_path] [-d dataset_path]
```

## Contributing to TIDES

Those who want to help with the development of the TIDES specification should review the guidance in [CONTRIBUTING.md](CONTRIBUTING.md).
Expand Down
98 changes: 98 additions & 0 deletions bin/replace-spec-in-datapackage
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env bash

description="Create a temporary data package if a spec_path_prefix is provided."

usage="
Usage: replace-spec-in-datapackage <dataset_path> [spec_path_prefix] [output_file]

Arguments:
<dataset_path> The path to the dataset directory containing the 'datapackage.json' file.
<spec_path_prefix> The path or URL to the spec to be referenced in the updated data package.
[output_file] (Optional) The path to save the temporary data package. If not provided, the temporary data package will be saved as 'datapackage.tmp.json' in the dataset directory.

"

example_usage="
Example Usage:
bin/replace-spec-in-datapackage samples/template/TIDES spec samples/template/TIDES/datapackage.tmp.json
"

################################################################################
# Help #
################################################################################

# Display help message
function display_help() {
echo "$description"
echo "$usage"
echo "$example_usage"
}

# Check for help flag
if [ "$1" == "--help" ]; then
display_help
exit 0
fi

################################################################################
# SET DEFAULTS #
################################################################################
DEFAULT_TMP_DATAPACKAGE="datapackage.tmp.json"
PROFILE_FILE="tides-datapackage-profile.json"

################################################################################
# MAIN #
################################################################################

echo "$description"

################################################################################
# Check Requirements #
################################################################################
source "$(dirname "${BASH_SOURCE[0]}")/utils"
check_jq

################################################################################
# Process the input options. #
################################################################################
dataset_path=$1
spec_path_prefix=$2
output_file=${3:-"$dataset_path/$DEFAULT_TMP_DATAPACKAGE"}

echo "Parameters:
dataset_path: $dataset_path
spec_path_prefix: $spec_path_prefix
output_file: $output_file
"

# Check if required arguments are missing
if [ -z "$dataset_path" ]; then
echo "Error: Missing dataset_path argument." >&2
display_help
exit 1
fi

# Check if required arguments are missing
if [ -z "spec_path_prefix" ]; then
echo "Error: Missing spec_path_prefix argument." >&2
display_help
exit 1
fi

datapackage_file="$dataset_path/datapackage.json"

check_valid_path "$datapackage_file"

profile_file="$spec_path_prefix/$PROFILE_FILE"
check_valid_path "$profile_file"

################################################################################
# Create updated datapackage #
################################################################################
cp "$datapackage_file" "$output_file"
jq --arg spec_path_prefix "$spec_path_prefix" --arg profile_file "$profile_file" '
.resources |= map(.schema |= ($spec_path_prefix + "/\(. | split("/") | last)"))
| .profile = ($profile_file)
' "$output_file" > "$output_file.tmp" && mv "$output_file.tmp" "$output_file"

echo "$output_file"
75 changes: 75 additions & 0 deletions bin/utils
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash

# Check if jsonschema-cli is installed
check_jsonschema-cli() {
if ! command -v jsonschema-cli >/dev/null 2>&1; then
echo >&2 "\033[31m!!! jsonschema-cli is required but not found.\033[0m

You can install it using 'pip install jsonschema-cli'. Aborting."
exit 1
fi
}

# Check if frictionless is installed
check_frictionless() {
if ! command -v frictionless >/dev/null 2>&1; then
echo >&2 "\033[31m!!! frictionless is required but not found.\033[0m

You can install it using 'pip install frictionless'. Aborting."
exit 1
fi
}

# Function to check jq and provide installation instructions if not found
check_jq() {
if ! command -v jq >/dev/null 2>&1; then
echo >&2 "\033[31m!!! jq is required but not found.\033[0m"

# Determine the operating system
os_type=$(uname -s)

case "$os_type" in
Linux*)
echo >&2 "Please install jq using your package manager."
echo >&2 "For example, on Debian/Ubuntu-based systems, you can use:"
echo >&2 "sudo apt-get install jq"
;;
Darwin*)
echo >&2 "Please install jq using Homebrew."
echo >&2 "If you don't have Homebrew installed, you can install it from https://brew.sh/."
echo >&2 "Once Homebrew is installed, run the following command:"
echo >&2 "brew install jq"
;;
CYGWIN*|MINGW32*|MSYS*|MINGW*)
echo >&2 "Please download the jq binary for Windows from https://stedolan.github.io/jq/download/."
echo >&2 "Extract the downloaded ZIP file and add the 'jq.exe' binary to your PATH..."
echo >&2 "Or run the following command: "
echo >&2 "curl -L -o /usr/bin/jq.exe https://github.com/stedolan/jq/releases/latest/download/jq-win64.exe"
;;
*)
echo >&2 "Unknown operating system. Please install jq from https://stedolan.github.io/jq/download/."
;;
esac

exit 1
fi
}

# Function to check if this is a valid spec path
check_valid_path() {
local path=$1

if [ -n "$path" ]; then
if [ ! -e "$path" ] && [[ ! "$path" =~ ^http ]]; then
echo "\033[31mError: $path is an invalid path. It must be a valid file path, directory path, or a URL starting with 'http'.\033[0m" >&2
display_help
exit 1
elif [[ "$path" =~ ^http ]]; then
# Check if the URL is valid
if ! curl --output /dev/null --silent --head --fail "$path"; then
echo "\033[31mError: Invalid URL. The $path URL is not reachable or does not exist.\033[0m" >&2
exit 1
fi
fi
fi
}
Loading