Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: test production gateways #108

Merged
merged 37 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
3b5e34e
ci: add test production e2e
laurentsenta Jul 4, 2023
f2ad9a3
fix: missing curl option
laurentsenta Jul 4, 2023
e20ec2b
feat: pin & wait for status
laurentsenta Jul 4, 2023
7f92d35
fix cid
laurentsenta Jul 4, 2023
f032203
ci: error catching
laurentsenta Jul 4, 2023
c26577f
ci: naming
laurentsenta Jul 4, 2023
4adbae2
test: public gateways
laurentsenta Jul 4, 2023
1aa6463
wip: merge car
laurentsenta Jul 5, 2023
cda83ce
attempt to more tweaks
laurentsenta Jul 5, 2023
2e8f648
trying out more tweaks: using maps and dag pb, no success
laurentsenta Jul 5, 2023
90ea812
more tweaks
laurentsenta Jul 5, 2023
3638221
go mod tidy
laurentsenta Jul 5, 2023
05ef708
ci: continue after 2 minutes
laurentsenta Jul 5, 2023
ad9de32
ci: generate fixtures
laurentsenta Jul 5, 2023
5f69a67
ci: wip test artifacts
laurentsenta Jul 6, 2023
1d7b92d
ci: run always
laurentsenta Jul 6, 2023
77e185a
ci: tweak artifacts
laurentsenta Jul 25, 2023
d279d76
ci: add aggregations
laurentsenta Jul 25, 2023
b29dbab
tooling: fix merge
laurentsenta Jul 25, 2023
86fc45e
CHANGELOG: add merged note
laurentsenta Jul 25, 2023
62dce94
ci: simplif & clean
laurentsenta Jul 25, 2023
7e4db53
link to dashboard
laurentsenta Jul 25, 2023
5ba0765
ci: simplif
laurentsenta Jul 25, 2023
d757d0f
attempt with completed-with-failure
laurentsenta Jul 25, 2023
84a8527
tweaks
laurentsenta Jul 25, 2023
270219c
tmp
laurentsenta Jul 25, 2023
f5cc719
tweak
laurentsenta Jul 25, 2023
49eb243
feat: wip release fixtures
laurentsenta Jun 30, 2023
b0a6d6b
ci: udpate badge
github-actions[bot] Jul 26, 2023
eb667ff
ci: use w3 upload
laurentsenta Jul 27, 2023
323585d
ci: sleep instead of pinning API
laurentsenta Jul 27, 2023
64b2dcb
ci: drop duplicate flags
laurentsenta Jul 27, 2023
415964a
fix: drop debug log
laurentsenta Jul 27, 2023
49fde93
fix: explicit permission
laurentsenta Jul 27, 2023
c8a6a38
ci: use output instead of env
laurentsenta Jul 27, 2023
3d60a15
ci: use w3 storage actions
laurentsenta Jul 27, 2023
cfd4188
ci: concurrency group
laurentsenta Jul 27, 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
23 changes: 23 additions & 0 deletions .github/workflows/release-fixtures.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Release Fixtures
on:
workflow_dispatch:
workflow_run:
workflows: [Release]
types:
- completed


jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Ganerate Fixtures
env:
W3STORAGE_TOKEN: ${{ secrets.W3STORAGE_TOKEN }}
run: |
make fixtures.car
- name: Upload fixtures
uses: web3-storage/add-to-web3@v2
with:
web3_token: ${{ secrets.W3STORAGE_TOKEN }}
path_to_add: 'fixtures.car'
115 changes: 115 additions & 0 deletions .github/workflows/test-prod-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Test Production (e2e)

on:
workflow_dispatch:
push:
branches:
- main
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }}
cancel-in-progress: true

jobs:
upload-fixtures:
runs-on: "ubuntu-latest"
defaults:
run:
shell: bash
steps:
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: 1.20.4
- uses: actions/checkout@v3
with:
path: "gateway-conformance"
- name: Extract fixtures
uses: ./gateway-conformance/.github/actions/extract-fixtures
with:
output: ./
merged: true
# https://web3.storage/docs/how-tos/store/#storing-ipfs-content-archives
- name: Upload fixtures
laurentsenta marked this conversation as resolved.
Show resolved Hide resolved
id: upload
uses: web3-storage/add-to-web3@v2
with:
web3_token: ${{ secrets.W3STORAGE_TOKEN }}
path_to_add: 'fixtures.car'
- name: Wait for pinning
laurentsenta marked this conversation as resolved.
Show resolved Hide resolved
run: |
sleep 180 # 3 minutes
# see rational in https://github.com/ipfs/gateway-conformance/pull/108#discussion_r1274628865
test:
runs-on: "ubuntu-latest"
strategy:
matrix:
target: ["ipfs.runfission.com", "w3s.link"]
fail-fast: false
defaults:
run:
shell: bash
needs: upload-fixtures
steps:
- name: Setup Go
uses: actions/setup-go@v3
with:
go-version: 1.20.4
- uses: actions/checkout@v3
with:
path: "gateway-conformance"
- name: Run the tests
uses: ./gateway-conformance/.github/actions/test
with:
gateway-url: https://${{ matrix.target }}
subdomain-url: https://${{ matrix.target }}
json: output.json
xml: output.xml
html: output.html
markdown: output.md
- name: Upload one-page HTML report
if: (failure() || success())
uses: actions/upload-artifact@v3
with:
name: conformance-${{ matrix.target }}.html
path: ./output.html
- name: Upload JSON output
if: (failure() || success())
uses: actions/upload-artifact@v3
with:
name: conformance-${{ matrix.target }}.json
path: ./output.json
aggregate:
runs-on: "ubuntu-latest"
needs: [test]
# the tests might have failed
if: always()
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v3
with:
path: "gateway-conformance"
- name: Download Artifacts
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Aggregate results
working-directory: ./artifacts
run: |
mkdir ./aggregates

# download-artifact downloads artifacts in a directory named after the artifact
# details: https://github.com/actions/download-artifact#download-all-artifacts
for folder in ./conformance-*.json; do
file="${folder}/output.json"
new_file="aggregates/${folder#conformance-}"
jq -ns 'inputs' "$file" | node ../gateway-conformance/aggregate.js 1 > "${new_file}"
done

node ../gateway-conformance/aggregate-into-table.js ./aggregates/*.json > ./table.md
- name: Set summary
if: (failure() || success())
run: cat ./artifacts/table.md >> $GITHUB_STEP_SUMMARY
63 changes: 63 additions & 0 deletions .github/workflows/update-badge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Note: this workflow requires the repository to give Write access to Github Workflows.
# in Settings > Actions > General > Workflow permissions
laurentsenta marked this conversation as resolved.
Show resolved Hide resolved

permissions:
contents: write
name: Update Badge

on:
workflow_run:
workflows:
- Test Production (e2e)
types:
- completed
branches:
- main

defaults:
run:
shell: bash

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

jobs:
update-badge:
runs-on: ubuntu-latest
steps:
- uses: pl-strflt/job-summary-url-action@v1
id: metadata
with:
workflow: test-prod-e2e.yml # ${{ github.event.workflow.path }}
run_id: ${{ github.event.workflow_run.id }}
run_attempt: ${{ github.event.workflow_run.run_attempt }}
job: aggregate
- uses: actions/checkout@v3
# https://github.com/orgs/community/discussions/26560
- run: |
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
- run: |
echo GITHUB_JOB_SUMMARY_URL=${GITHUB_JOB_SUMMARY_URL}
IN='[![Conformance Production Dashboard](https://github.com/ipfs/gateway-conformance/actions/workflows/test-prod-e2e.yml/badge.svg?branch=master)](.*)'
ESCAPED_IN=$(printf '%s\n' "$IN" | sed -e 's/[][\/!&]/\\&/g')

OUT="[![Conformance Production Dashboard](https://github.com/ipfs/gateway-conformance/actions/workflows/test-prod-e2e.yml/badge.svg?branch=master)](${GITHUB_JOB_SUMMARY_URL})"

sed -i "s;${ESCAPED_IN};${OUT};" README.md
env:
GITHUB_JOB_SUMMARY_URL: ${{ steps.metadata.outputs.job_summary_url }}
REPOSITORY: ${{ github.repository }}
- id: git
run: |
if [[ -n $(git diff --shortstat 2> /dev/null | tail -n1) ]]; then
echo "dirty=1" >> $GITHUB_OUTPUT
else
echo "dirty=0" >> $GITHUB_OUTPUT
fi
- if: steps.git.outputs.dirty == '1'
run: |
git add README.md
git commit -m 'chore: update the link to the dashboard [skip ci]'
git push
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed
- finalized port of Kubo's sharness tests. [PR](https://github.com/ipfs/gateway-conformance/pull/92)
- `extract-fixtures --merged` generates a car version 1 with a single root now

## [0.2.0] - 2023-06-26
### Added
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

`gateway-conformance` is a tool designed to test if an IPFS Gateway implementation complies with the IPFS Gateway Specification correctly. The tool is distributed as a Docker image, as well as a GitHub Action(s).

[![Conformance Production Dashboard](https://github.com/ipfs/gateway-conformance/actions/workflows/test-prod-e2e.yml/badge.svg?branch=master)]()

## Table of Contents

- [Commands](#commands)
Expand Down
86 changes: 86 additions & 0 deletions aggregate-into-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const fs = require("fs");

// retrieve the list of input files from the command line
const files = process.argv.slice(2);

// read all input files (json)
const inputs = files.map((file) => {
return JSON.parse(fs.readFileSync(file, 'utf8'));
}
);

// merge all the unique keys from all the inputs
let keys = new Set();
inputs.forEach((input) => {
Object.keys(input).forEach((key) => {
keys.add(key);
});
});
keys = Array.from(keys).sort();

// generate a table
const columns = [];

// add the leading column ("gateway", "key1", "key2", ... "keyN")
const leading = ["gateway"];
keys.forEach((key) => {
// Skip the "Test" prefix
const niceKey = key.replace(/^Test/, '');
leading.push(niceKey);
});
columns.push(leading);

// add the data for every input
const cellRender = (cell) => {
if (cell === null) {
return '';
}

if (cell['fail'] > 0) {
return `:red_circle: (${cell['pass']} / ${cell['total']})`;
}
if (cell['skip'] > 0) {
return `:yellow_circle: (skipped)`;
}
if (cell['pass'] > 0) {
return `:green_circle: (${cell['pass']} / ${cell['total']})`;
}
laurentsenta marked this conversation as resolved.
Show resolved Hide resolved

throw new Error(`Unhandled cell value: ${JSON.stringify(cell)}`);
}

inputs.forEach((input, index) => {
// clean name (remove path and extension)
let name = files[index].replace(/\.json$/, '').replace(/^.*\//, '');

const col = [name];
keys.forEach((key) => {
col.push(cellRender(input[key] || null));
});
columns.push(col);
});

// # Rotate the table
// it's easier to create the table by column, but we want to render it by row
let rows = columns[0].map((_, i) => columns.map(col => col[i]));

// # Render the table into a markdown table

// add the hyphen header row after the first row
const hyphenated = rows[0].map((x, i) => {
if (i === 0) {
return '-'.repeat(Math.max(0, x.length - 2)) + '-:'
}
return ':-' + '-'.repeat(Math.max(0, x.length - 2));
})

rows = [
rows[0],
hyphenated,
...rows.slice(1),
]

let markdown = rows.map(row => '| ' + row.join(' | ') + ' |').join('\n');

// output the table to stdout
fs.writeFileSync(1, markdown);
Loading