openresearchworkspace 0.1.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openresearchworkspace-0.1.0a1/.github/workflows/initialize-project.yml +120 -0
- openresearchworkspace-0.1.0a1/.github/workflows/release-alpha.yml +215 -0
- openresearchworkspace-0.1.0a1/.github/workflows/release-checks.yml +53 -0
- openresearchworkspace-0.1.0a1/.github/workflows/test-browser.yml +68 -0
- openresearchworkspace-0.1.0a1/.github/workflows/test-core.yml +72 -0
- openresearchworkspace-0.1.0a1/CHANGELOG.md +26 -0
- openresearchworkspace-0.1.0a1/LICENSE +21 -0
- openresearchworkspace-0.1.0a1/MANIFEST.in +15 -0
- openresearchworkspace-0.1.0a1/PKG-INFO +69 -0
- openresearchworkspace-0.1.0a1/README.md +353 -0
- openresearchworkspace-0.1.0a1/browser/app.js +109 -0
- openresearchworkspace-0.1.0a1/browser/engine.js +170 -0
- openresearchworkspace-0.1.0a1/browser/page.html +80 -0
- openresearchworkspace-0.1.0a1/browser/requirements-test.txt +2 -0
- openresearchworkspace-0.1.0a1/browser/style.css +1 -0
- openresearchworkspace-0.1.0a1/browser/tests/test_ui.py +198 -0
- openresearchworkspace-0.1.0a1/docs/AI_READY_WORKSPACE.md +132 -0
- openresearchworkspace-0.1.0a1/docs/CAPTURE_GETTING_STARTED.md +177 -0
- openresearchworkspace-0.1.0a1/docs/PYPI_README.md +44 -0
- openresearchworkspace-0.1.0a1/docs/browser-generator.md +127 -0
- openresearchworkspace-0.1.0a1/docs/capabilities.md +102 -0
- openresearchworkspace-0.1.0a1/docs/cli.md +108 -0
- openresearchworkspace-0.1.0a1/docs/concepts.md +110 -0
- openresearchworkspace-0.1.0a1/docs/faq.md +51 -0
- openresearchworkspace-0.1.0a1/docs/getting-started.md +338 -0
- openresearchworkspace-0.1.0a1/docs/index.md +102 -0
- openresearchworkspace-0.1.0a1/docs/isa.md +114 -0
- openresearchworkspace-0.1.0a1/docs/portable-implementations.md +411 -0
- openresearchworkspace-0.1.0a1/docs/project-structure.md +77 -0
- openresearchworkspace-0.1.0a1/docs/releases.md +108 -0
- openresearchworkspace-0.1.0a1/docs/ro-crate.md +90 -0
- openresearchworkspace-0.1.0a1/pyproject.toml +42 -0
- openresearchworkspace-0.1.0a1/schema/data_dictionary.schema.json +47 -0
- openresearchworkspace-0.1.0a1/schema/project.schema.json +108 -0
- openresearchworkspace-0.1.0a1/schema/quality_status.schema.json +57 -0
- openresearchworkspace-0.1.0a1/schema/setup.schema.json +108 -0
- openresearchworkspace-0.1.0a1/scripts/build_browser.py +134 -0
- openresearchworkspace-0.1.0a1/scripts/capture_getting_started.py +686 -0
- openresearchworkspace-0.1.0a1/scripts/initialize_project.py +33 -0
- openresearchworkspace-0.1.0a1/scripts/parse_setup_issue.py +88 -0
- openresearchworkspace-0.1.0a1/scripts/release.py +251 -0
- openresearchworkspace-0.1.0a1/scripts/smoke_installed.py +54 -0
- openresearchworkspace-0.1.0a1/scripts/test_distributions.py +43 -0
- openresearchworkspace-0.1.0a1/setup.cfg +4 -0
- openresearchworkspace-0.1.0a1/src/openresearchworkspace.egg-info/PKG-INFO +69 -0
- openresearchworkspace-0.1.0a1/src/openresearchworkspace.egg-info/SOURCES.txt +79 -0
- openresearchworkspace-0.1.0a1/src/openresearchworkspace.egg-info/dependency_links.txt +1 -0
- openresearchworkspace-0.1.0a1/src/openresearchworkspace.egg-info/entry_points.txt +2 -0
- openresearchworkspace-0.1.0a1/src/openresearchworkspace.egg-info/requires.txt +2 -0
- openresearchworkspace-0.1.0a1/src/openresearchworkspace.egg-info/top_level.txt +1 -0
- openresearchworkspace-0.1.0a1/src/orw/__init__.py +20 -0
- openresearchworkspace-0.1.0a1/src/orw/_scaffold.py +357 -0
- openresearchworkspace-0.1.0a1/src/orw/_version.py +2 -0
- openresearchworkspace-0.1.0a1/src/orw/cli.py +330 -0
- openresearchworkspace-0.1.0a1/src/orw/export/__init__.py +23 -0
- openresearchworkspace-0.1.0a1/src/orw/export/_rocrate_model.py +1006 -0
- openresearchworkspace-0.1.0a1/src/orw/export/rocrate.py +174 -0
- openresearchworkspace-0.1.0a1/src/orw/fs_safety.py +86 -0
- openresearchworkspace-0.1.0a1/src/orw/initialize.py +160 -0
- openresearchworkspace-0.1.0a1/src/orw/model.py +187 -0
- openresearchworkspace-0.1.0a1/src/orw/schemas/__init__.py +1 -0
- openresearchworkspace-0.1.0a1/src/orw/schemas/project.schema.json +108 -0
- openresearchworkspace-0.1.0a1/src/orw/templates/project.yml +41 -0
- openresearchworkspace-0.1.0a1/src/orw/templates/workspace.yml +10 -0
- openresearchworkspace-0.1.0a1/src/orw/validate.py +448 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/rocrate/basic.mapping.json +74 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/basic.json +23 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/invalid-orcid.json +19 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/no-assay.json +20 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/orcid-keywords.json +23 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/reinitialize.json +21 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/restricted-external-data.json +21 -0
- openresearchworkspace-0.1.0a1/tests/fixtures/setup/unicode.json +23 -0
- openresearchworkspace-0.1.0a1/tests/test_browser_contract.py +189 -0
- openresearchworkspace-0.1.0a1/tests/test_cli.py +276 -0
- openresearchworkspace-0.1.0a1/tests/test_core.py +183 -0
- openresearchworkspace-0.1.0a1/tests/test_filesystem_aliases.py +81 -0
- openresearchworkspace-0.1.0a1/tests/test_github_adapter.py +125 -0
- openresearchworkspace-0.1.0a1/tests/test_release_process.py +143 -0
- openresearchworkspace-0.1.0a1/tests/test_release_safety.py +202 -0
- openresearchworkspace-0.1.0a1/tests/test_rocrate.py +187 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: Initialize research project
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issues:
|
|
5
|
+
types: [opened]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
issues: write
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: initialize-project-${{ github.repository }}
|
|
13
|
+
cancel-in-progress: false
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
initialize:
|
|
17
|
+
name: Create project structure and metadata
|
|
18
|
+
if: >-
|
|
19
|
+
contains(github.event.issue.body, '### Project title') &&
|
|
20
|
+
contains(github.event.issue.body, '### Ready to initialize') &&
|
|
21
|
+
github.repository != 'dhuzard/OpenResearchWorkspace'
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- name: Check who submitted the setup form
|
|
26
|
+
shell: bash
|
|
27
|
+
env:
|
|
28
|
+
GH_TOKEN: ${{ github.token }}
|
|
29
|
+
REPO: ${{ github.repository }}
|
|
30
|
+
USER: ${{ github.event.issue.user.login }}
|
|
31
|
+
run: |
|
|
32
|
+
permission=$(gh api "repos/$REPO/collaborators/$USER/permission" --jq '.permission')
|
|
33
|
+
case "$permission" in
|
|
34
|
+
admin|maintain|write)
|
|
35
|
+
echo "Setup submitted by authorized repository participant $USER ($permission)."
|
|
36
|
+
;;
|
|
37
|
+
*)
|
|
38
|
+
echo "::error::Project initialization must be submitted by a repository owner or collaborator with write access."
|
|
39
|
+
exit 1
|
|
40
|
+
;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
- name: Check out project
|
|
44
|
+
uses: actions/checkout@v4
|
|
45
|
+
|
|
46
|
+
- name: Refuse accidental re-initialization
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |
|
|
49
|
+
if [ -f .research/initialized ]; then
|
|
50
|
+
echo "::error::This project has already been initialized."
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Read and validate setup form
|
|
55
|
+
id: setup
|
|
56
|
+
run: python scripts/parse_setup_issue.py
|
|
57
|
+
|
|
58
|
+
- name: Create ISA-aligned project files
|
|
59
|
+
env:
|
|
60
|
+
ORW_SETUP_JSON: ${{ steps.setup.outputs.setup_payload }}
|
|
61
|
+
ORW_PROVIDER: github
|
|
62
|
+
ORW_PROVIDER_USER: ${{ github.event.issue.user.login }}
|
|
63
|
+
run: python scripts/initialize_project.py
|
|
64
|
+
|
|
65
|
+
- name: Commit initialized workspace
|
|
66
|
+
shell: bash
|
|
67
|
+
run: |
|
|
68
|
+
git config user.name "github-actions[bot]"
|
|
69
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
70
|
+
git add README.md .research studies project-docs references
|
|
71
|
+
if git diff --cached --quiet; then
|
|
72
|
+
echo "::error::Initialization produced no changes."
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
git commit -m "Initialize research workspace"
|
|
76
|
+
git push
|
|
77
|
+
|
|
78
|
+
- name: Confirm setup in the form thread
|
|
79
|
+
env:
|
|
80
|
+
GH_TOKEN: ${{ github.token }}
|
|
81
|
+
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
82
|
+
REPO: ${{ github.repository }}
|
|
83
|
+
shell: bash
|
|
84
|
+
run: |
|
|
85
|
+
cat > /tmp/orw-success.md <<EOF
|
|
86
|
+
✅ **Your OpenResearchWorkspace project is initialized.**
|
|
87
|
+
|
|
88
|
+
ORW created your first ISA Study/Assay structure and updated the project metadata and README.
|
|
89
|
+
|
|
90
|
+
➡️ **[Open your initialized workspace](https://github.com/$REPO)**
|
|
91
|
+
|
|
92
|
+
This setup form is now complete and will be closed automatically.
|
|
93
|
+
EOF
|
|
94
|
+
gh issue comment "$ISSUE_NUMBER" --repo "$REPO" --body-file /tmp/orw-success.md
|
|
95
|
+
gh issue close "$ISSUE_NUMBER" --repo "$REPO" --reason completed
|
|
96
|
+
|
|
97
|
+
- name: Workflow summary
|
|
98
|
+
run: |
|
|
99
|
+
echo "## Research workspace initialized" >> "$GITHUB_STEP_SUMMARY"
|
|
100
|
+
echo "The setup form was validated and the ISA-aligned workspace was created." >> "$GITHUB_STEP_SUMMARY"
|
|
101
|
+
|
|
102
|
+
- name: Explain a failed setup
|
|
103
|
+
if: failure()
|
|
104
|
+
env:
|
|
105
|
+
GH_TOKEN: ${{ github.token }}
|
|
106
|
+
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
107
|
+
REPO: ${{ github.repository }}
|
|
108
|
+
RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
109
|
+
shell: bash
|
|
110
|
+
run: |
|
|
111
|
+
cat > /tmp/orw-failure.md <<EOF
|
|
112
|
+
❌ **ORW could not finish initialization.**
|
|
113
|
+
|
|
114
|
+
The setup form has been left open so you can ask for help or correct the problem.
|
|
115
|
+
|
|
116
|
+
Technical details: $RUN_URL
|
|
117
|
+
|
|
118
|
+
If you are a beginner, you do not need to understand that log yourself—share the link when asking for help.
|
|
119
|
+
EOF
|
|
120
|
+
gh issue comment "$ISSUE_NUMBER" --repo "$REPO" --body-file /tmp/orw-failure.md
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
name: Publish alpha (TestPyPI first)
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
inputs:
|
|
5
|
+
phase:
|
|
6
|
+
description: 'TestPyPI rehearsal, or promote a successful rehearsal to PyPI'
|
|
7
|
+
required: true
|
|
8
|
+
type: choice
|
|
9
|
+
options: [testpypi, pypi]
|
|
10
|
+
default: testpypi
|
|
11
|
+
version:
|
|
12
|
+
description: 'Explicit alpha version'
|
|
13
|
+
required: true
|
|
14
|
+
type: string
|
|
15
|
+
default: '0.1.0a1'
|
|
16
|
+
rehearsal_run:
|
|
17
|
+
description: 'Successful TestPyPI run ID (required for PyPI promotion)'
|
|
18
|
+
type: string
|
|
19
|
+
default: ''
|
|
20
|
+
confirmation:
|
|
21
|
+
description: 'For public promotion enter: publish 0.1.0a1'
|
|
22
|
+
type: string
|
|
23
|
+
default: ''
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
actions: read
|
|
27
|
+
concurrency:
|
|
28
|
+
group: orw-alpha-${{ inputs.version }}
|
|
29
|
+
cancel-in-progress: false
|
|
30
|
+
env:
|
|
31
|
+
VERSION: ${{ inputs.version }}
|
|
32
|
+
PHASE: ${{ inputs.phase }}
|
|
33
|
+
REHEARSAL_RUN: ${{ inputs.rehearsal_run }}
|
|
34
|
+
CONFIRMATION: ${{ inputs.confirmation }}
|
|
35
|
+
PYTHONUTF8: '1'
|
|
36
|
+
jobs:
|
|
37
|
+
guard:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
41
|
+
with:
|
|
42
|
+
persist-credentials: false
|
|
43
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
44
|
+
with:
|
|
45
|
+
python-version: '3.12'
|
|
46
|
+
- name: Enforce main, alpha version, environment reviewers and rehearsal provenance
|
|
47
|
+
env:
|
|
48
|
+
GH_TOKEN: ${{ github.token }}
|
|
49
|
+
run: python scripts/release.py guard
|
|
50
|
+
|
|
51
|
+
checks:
|
|
52
|
+
needs: guard
|
|
53
|
+
if: inputs.phase == 'testpypi'
|
|
54
|
+
uses: ./.github/workflows/release-checks.yml
|
|
55
|
+
|
|
56
|
+
build:
|
|
57
|
+
needs: [guard, checks]
|
|
58
|
+
if: inputs.phase == 'testpypi'
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
62
|
+
with:
|
|
63
|
+
persist-credentials: false
|
|
64
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
65
|
+
with:
|
|
66
|
+
python-version: '3.12'
|
|
67
|
+
- name: Install build and browser test dependencies
|
|
68
|
+
run: |
|
|
69
|
+
python -m pip install . build twine -r browser/requirements-test.txt
|
|
70
|
+
python -m playwright install --with-deps chromium
|
|
71
|
+
- name: Real browser acceptance tests
|
|
72
|
+
run: python -m unittest discover -s browser/tests -v
|
|
73
|
+
- name: Build and test the immutable candidate
|
|
74
|
+
run: python scripts/release.py build
|
|
75
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
76
|
+
with:
|
|
77
|
+
name: alpha-candidate
|
|
78
|
+
path: candidate/
|
|
79
|
+
if-no-files-found: error
|
|
80
|
+
retention-days: 30
|
|
81
|
+
|
|
82
|
+
publish-testpypi:
|
|
83
|
+
needs: build
|
|
84
|
+
if: inputs.phase == 'testpypi'
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
environment: testpypi
|
|
87
|
+
permissions:
|
|
88
|
+
contents: read
|
|
89
|
+
actions: read
|
|
90
|
+
id-token: write
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
93
|
+
with:
|
|
94
|
+
name: alpha-candidate
|
|
95
|
+
path: candidate/
|
|
96
|
+
- name: Upload exact candidate to TestPyPI
|
|
97
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
|
98
|
+
with:
|
|
99
|
+
repository-url: https://test.pypi.org/legacy/
|
|
100
|
+
packages-dir: candidate/packages/
|
|
101
|
+
skip-existing: true
|
|
102
|
+
|
|
103
|
+
verify-testpypi:
|
|
104
|
+
needs: publish-testpypi
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
108
|
+
with:
|
|
109
|
+
persist-credentials: false
|
|
110
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
111
|
+
with:
|
|
112
|
+
python-version: '3.12'
|
|
113
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
114
|
+
with:
|
|
115
|
+
name: alpha-candidate
|
|
116
|
+
path: candidate/
|
|
117
|
+
- name: Download actual TestPyPI bytes, verify hashes, install wheel and sdist
|
|
118
|
+
run: python scripts/release.py registry --index testpypi
|
|
119
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
120
|
+
with:
|
|
121
|
+
name: alpha-verified
|
|
122
|
+
path: candidate/
|
|
123
|
+
if-no-files-found: error
|
|
124
|
+
retention-days: 30
|
|
125
|
+
|
|
126
|
+
acquire-verified:
|
|
127
|
+
needs: guard
|
|
128
|
+
if: inputs.phase == 'pypi'
|
|
129
|
+
runs-on: ubuntu-latest
|
|
130
|
+
outputs:
|
|
131
|
+
source_sha: ${{ steps.proof.outputs.source_sha }}
|
|
132
|
+
steps:
|
|
133
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
134
|
+
with:
|
|
135
|
+
persist-credentials: false
|
|
136
|
+
fetch-depth: 0
|
|
137
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
138
|
+
with:
|
|
139
|
+
python-version: '3.12'
|
|
140
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
141
|
+
with:
|
|
142
|
+
name: alpha-verified
|
|
143
|
+
path: candidate/
|
|
144
|
+
run-id: ${{ inputs.rehearsal_run }}
|
|
145
|
+
github-token: ${{ github.token }}
|
|
146
|
+
- name: Verify provenance and TestPyPI again; never rebuild
|
|
147
|
+
id: proof
|
|
148
|
+
env:
|
|
149
|
+
GH_TOKEN: ${{ github.token }}
|
|
150
|
+
run: python scripts/release.py promotion
|
|
151
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
152
|
+
with:
|
|
153
|
+
name: alpha-approved
|
|
154
|
+
path: candidate/
|
|
155
|
+
if-no-files-found: error
|
|
156
|
+
retention-days: 30
|
|
157
|
+
|
|
158
|
+
publish-pypi:
|
|
159
|
+
needs: acquire-verified
|
|
160
|
+
runs-on: ubuntu-latest
|
|
161
|
+
environment: pypi
|
|
162
|
+
permissions:
|
|
163
|
+
contents: read
|
|
164
|
+
actions: read
|
|
165
|
+
id-token: write
|
|
166
|
+
steps:
|
|
167
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
168
|
+
with:
|
|
169
|
+
name: alpha-approved
|
|
170
|
+
path: candidate/
|
|
171
|
+
- name: Upload the exact rehearsed artifacts to PyPI
|
|
172
|
+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
|
173
|
+
with:
|
|
174
|
+
packages-dir: candidate/packages/
|
|
175
|
+
skip-existing: true
|
|
176
|
+
|
|
177
|
+
verify-pypi:
|
|
178
|
+
needs: publish-pypi
|
|
179
|
+
runs-on: ubuntu-latest
|
|
180
|
+
steps:
|
|
181
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
182
|
+
with:
|
|
183
|
+
persist-credentials: false
|
|
184
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
185
|
+
with:
|
|
186
|
+
python-version: '3.12'
|
|
187
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
188
|
+
with:
|
|
189
|
+
name: alpha-approved
|
|
190
|
+
path: candidate/
|
|
191
|
+
- name: Verify public index bytes and clean installations
|
|
192
|
+
run: python scripts/release.py registry --index pypi
|
|
193
|
+
|
|
194
|
+
github-prerelease:
|
|
195
|
+
needs: [verify-pypi, acquire-verified]
|
|
196
|
+
runs-on: ubuntu-latest
|
|
197
|
+
permissions:
|
|
198
|
+
contents: write
|
|
199
|
+
actions: read
|
|
200
|
+
steps:
|
|
201
|
+
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
|
|
202
|
+
with:
|
|
203
|
+
name: alpha-approved
|
|
204
|
+
path: candidate/
|
|
205
|
+
- name: Publish matching browser and Python prerelease assets
|
|
206
|
+
env:
|
|
207
|
+
GH_TOKEN: ${{ github.token }}
|
|
208
|
+
GH_REPO: dhuzard/OpenResearchWorkspace
|
|
209
|
+
SOURCE_SHA: ${{ needs.acquire-verified.outputs.source_sha }}
|
|
210
|
+
run: |
|
|
211
|
+
gh release create "v$VERSION" --target "$SOURCE_SHA" --prerelease \
|
|
212
|
+
--title "OpenResearchWorkspace $VERSION" \
|
|
213
|
+
--notes "Evaluation alpha. TestPyPI rehearsal and public package read-back succeeded. Use disposable copies; inspect metadata before sharing. See the release guide and changelog for limitations." \
|
|
214
|
+
candidate/packages/* candidate/orw-browser-generator-*.zip \
|
|
215
|
+
candidate/index.html candidate/manifest.json candidate/rehearsal.json
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Alpha release checks
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
workflow_call:
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
jobs:
|
|
9
|
+
distributions:
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
14
|
+
python: ['3.10', '3.13']
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
env:
|
|
17
|
+
PYTHONUTF8: '1'
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
|
20
|
+
with:
|
|
21
|
+
persist-credentials: false
|
|
22
|
+
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python }}
|
|
25
|
+
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
|
|
26
|
+
with:
|
|
27
|
+
node-version: '22'
|
|
28
|
+
- name: Install build and test dependencies
|
|
29
|
+
run: python -m pip install . build twine
|
|
30
|
+
- name: Regression and cross-language tests
|
|
31
|
+
run: python -m unittest discover -s tests -v
|
|
32
|
+
- name: Build wheel and source distribution
|
|
33
|
+
run: python -m build --outdir dist/packages
|
|
34
|
+
- name: Check package metadata and Markdown
|
|
35
|
+
run: python -m twine check --strict dist/packages/*
|
|
36
|
+
shell: bash
|
|
37
|
+
- name: Test exact artifacts in separate clean environments
|
|
38
|
+
run: python scripts/test_distributions.py dist/packages --version 0.1.0a1
|
|
39
|
+
- name: Rebuild standalone browser from source
|
|
40
|
+
run: python scripts/build_browser.py
|
|
41
|
+
- name: Exercise the candidate-building path without upload credentials
|
|
42
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.13'
|
|
43
|
+
run: |
|
|
44
|
+
python scripts/release.py build --directory dist/release-candidate --version 0.1.0a1
|
|
45
|
+
python scripts/release.py verify --directory dist/release-candidate --version 0.1.0a1
|
|
46
|
+
- name: Share non-published review artifacts
|
|
47
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python == '3.13'
|
|
48
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
49
|
+
with:
|
|
50
|
+
name: alpha-review-artifacts
|
|
51
|
+
path: dist/release-candidate/
|
|
52
|
+
if-no-files-found: error
|
|
53
|
+
retention-days: 14
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Browser generator
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- 'browser/**'
|
|
7
|
+
- 'scripts/build_browser.py'
|
|
8
|
+
- 'src/orw/**'
|
|
9
|
+
- 'schema/**'
|
|
10
|
+
- 'tests/test_browser_contract.py'
|
|
11
|
+
- 'tests/fixtures/setup/**'
|
|
12
|
+
- '.github/workflows/test-browser.yml'
|
|
13
|
+
push:
|
|
14
|
+
branches: [main]
|
|
15
|
+
paths:
|
|
16
|
+
- 'browser/**'
|
|
17
|
+
- 'scripts/build_browser.py'
|
|
18
|
+
- 'src/orw/**'
|
|
19
|
+
- 'schema/**'
|
|
20
|
+
- 'tests/test_browser_contract.py'
|
|
21
|
+
- 'tests/fixtures/setup/**'
|
|
22
|
+
- '.github/workflows/test-browser.yml'
|
|
23
|
+
workflow_dispatch:
|
|
24
|
+
|
|
25
|
+
permissions:
|
|
26
|
+
contents: read
|
|
27
|
+
|
|
28
|
+
concurrency:
|
|
29
|
+
group: browser-${{ github.ref }}
|
|
30
|
+
cancel-in-progress: true
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
browser:
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
timeout-minutes: 10
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v5
|
|
38
|
+
- uses: actions/setup-python@v6
|
|
39
|
+
with:
|
|
40
|
+
python-version: '3.12'
|
|
41
|
+
- uses: actions/setup-node@v5
|
|
42
|
+
with:
|
|
43
|
+
node-version: '22'
|
|
44
|
+
- name: Install test dependencies
|
|
45
|
+
run: |
|
|
46
|
+
python -m pip install . -r browser/requirements-test.txt
|
|
47
|
+
python -m playwright install --with-deps chromium
|
|
48
|
+
- name: Cross-language contract and ZIP tests
|
|
49
|
+
run: python -m unittest discover -s tests -p test_browser_contract.py -v
|
|
50
|
+
- name: Build standalone application
|
|
51
|
+
run: python scripts/build_browser.py
|
|
52
|
+
- name: Browser acceptance (HTTP, file, offline, downloads)
|
|
53
|
+
env:
|
|
54
|
+
ORW_SCREENSHOT_DIR: dist/browser-evidence
|
|
55
|
+
run: python -m unittest discover -s browser/tests -v
|
|
56
|
+
- name: Share tested static build
|
|
57
|
+
uses: actions/upload-artifact@v4
|
|
58
|
+
with:
|
|
59
|
+
name: orw-browser-generator
|
|
60
|
+
path: dist/browser/index.html
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
- name: Share synthetic test screenshots
|
|
63
|
+
if: always()
|
|
64
|
+
uses: actions/upload-artifact@v4
|
|
65
|
+
with:
|
|
66
|
+
name: browser-test-screenshots
|
|
67
|
+
path: dist/browser-evidence/
|
|
68
|
+
if-no-files-found: ignore
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Test ORW core and CLI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths:
|
|
6
|
+
- "src/orw/**"
|
|
7
|
+
- "tests/**"
|
|
8
|
+
- "scripts/**"
|
|
9
|
+
- "schema/**"
|
|
10
|
+
- "pyproject.toml"
|
|
11
|
+
- ".github/workflows/test-core.yml"
|
|
12
|
+
pull_request:
|
|
13
|
+
paths:
|
|
14
|
+
- "src/orw/**"
|
|
15
|
+
- "tests/**"
|
|
16
|
+
- "scripts/**"
|
|
17
|
+
- "schema/**"
|
|
18
|
+
- "pyproject.toml"
|
|
19
|
+
- ".github/workflows/test-core.yml"
|
|
20
|
+
workflow_dispatch:
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
test:
|
|
27
|
+
name: Core, CLI, and installed-command tests
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Check out repository
|
|
32
|
+
uses: actions/checkout@v5
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@v6
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.12"
|
|
38
|
+
|
|
39
|
+
- name: Install ORW package
|
|
40
|
+
run: python -m pip install .
|
|
41
|
+
|
|
42
|
+
- name: Run unit and contract tests
|
|
43
|
+
run: python -m unittest discover -s tests -v
|
|
44
|
+
|
|
45
|
+
- name: Test installed CLI outside checkout
|
|
46
|
+
shell: bash
|
|
47
|
+
run: |
|
|
48
|
+
workdir="$(mktemp -d)"
|
|
49
|
+
cd "$workdir"
|
|
50
|
+
|
|
51
|
+
orw --version
|
|
52
|
+
orw init study --config "$GITHUB_WORKSPACE/tests/fixtures/setup/basic.json"
|
|
53
|
+
orw validate study
|
|
54
|
+
orw validate study --json > validation.json
|
|
55
|
+
orw export study --format ro-crate --output crate
|
|
56
|
+
|
|
57
|
+
python - <<'PY'
|
|
58
|
+
import json
|
|
59
|
+
from pathlib import Path
|
|
60
|
+
|
|
61
|
+
payload = json.loads(Path("validation.json").read_text())
|
|
62
|
+
assert payload["valid"] is True, payload
|
|
63
|
+
assert payload["issues"] == [], payload
|
|
64
|
+
assert Path("study/.research/project.yml").is_file()
|
|
65
|
+
|
|
66
|
+
crate = json.loads(Path("crate/ro-crate-metadata.json").read_text())
|
|
67
|
+
assert crate["@context"] == "https://w3id.org/ro/crate/1.3/context"
|
|
68
|
+
by_id = {entity["@id"]: entity for entity in crate["@graph"]}
|
|
69
|
+
assert by_id["ro-crate-metadata.json"]["conformsTo"]["@id"] == "https://w3id.org/ro/crate/1.3"
|
|
70
|
+
assert by_id["./"]["@type"] == "Dataset"
|
|
71
|
+
assert Path("crate/.research/project.yml").is_file()
|
|
72
|
+
PY
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0a1 — release candidate; not yet published
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Provider-neutral workspace generation, CLI initialization and validation, and RO-Crate 1.3 directory export.
|
|
8
|
+
- Standalone browser generator with local ZIP creation and Python/browser contract checks.
|
|
9
|
+
- Wheel/source-distribution smoke tests and a staged TestPyPI → public PyPI publishing workflow using the same verified artifacts.
|
|
10
|
+
- Software version in `src/orw/_version.py`; specification/template versions remain independent.
|
|
11
|
+
|
|
12
|
+
### Safety fixes
|
|
13
|
+
|
|
14
|
+
- Normal initialization refuses every nonempty destination, including unmarked scientific projects and existing README files.
|
|
15
|
+
- Explicit template initialization verifies the original placeholder metadata and preserves the previous overview and metadata in `.research/template-*` files.
|
|
16
|
+
- Export source/output trees must be disjoint, even with `--force`.
|
|
17
|
+
- Forced replacement requires a recognized, unchanged ORW export inventory. Added or edited files, symlinks/junctions, and legacy unmarked exports are not deleted.
|
|
18
|
+
- New export is validated in staging before replacement; the previous export is renamed aside and restored if final promotion fails.
|
|
19
|
+
- Open resource directories cannot silently include separately private/restricted/embargoed/unknown resources. Contradictory access declarations fail before copy.
|
|
20
|
+
|
|
21
|
+
### Limitations
|
|
22
|
+
|
|
23
|
+
- Evaluation alpha, not a complete OSF replacement or a FAIR certification.
|
|
24
|
+
- Use disposable copies and exclusive access during filesystem mutations; these guards are not a sandbox against malicious concurrent path substitution.
|
|
25
|
+
- Export metadata may contain sensitive names or locations. Inspect before sharing; access labels do not encrypt or control filesystem access.
|
|
26
|
+
- A new output directory is required for exports created before inventory markers were introduced.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Damien Huzard and OpenResearchWorkspace contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
include LICENSE README.md CHANGELOG.md pyproject.toml MANIFEST.in
|
|
2
|
+
recursive-include src *.py *.json *.yml
|
|
3
|
+
recursive-include schema *.json
|
|
4
|
+
recursive-include scripts *.py
|
|
5
|
+
recursive-include tests *.py *.json
|
|
6
|
+
recursive-include browser *.html *.css *.js *.py *.txt
|
|
7
|
+
recursive-include docs *.md
|
|
8
|
+
recursive-include .github/workflows *.yml
|
|
9
|
+
prune docs/assets
|
|
10
|
+
prune dist
|
|
11
|
+
prune build
|
|
12
|
+
prune .git
|
|
13
|
+
prune .venv
|
|
14
|
+
prune .orw-playwright-github
|
|
15
|
+
global-exclude __pycache__ *.py[cod] .DS_Store
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openresearchworkspace
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Local-first research workspace creation, validation, and RO-Crate export
|
|
5
|
+
Author: OpenResearchWorkspace contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dhuzard/OpenResearchWorkspace
|
|
8
|
+
Project-URL: Documentation, https://github.com/dhuzard/OpenResearchWorkspace/blob/main/docs/cli.md
|
|
9
|
+
Project-URL: Repository, https://github.com/dhuzard/OpenResearchWorkspace
|
|
10
|
+
Project-URL: Issues, https://github.com/dhuzard/OpenResearchWorkspace/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/dhuzard/OpenResearchWorkspace/blob/main/CHANGELOG.md
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: PyYAML<7,>=6.0
|
|
23
|
+
Requires-Dist: jsonschema<5,>=4.22
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# OpenResearchWorkspace — public alpha
|
|
27
|
+
|
|
28
|
+
A local-first toolkit for creating, validating, and exporting research workspaces. Git, a hosted forge, and an AI provider are not required. The canonical scientific record is `.research/project.yml`, organized around Investigation, Study, and Assay concepts.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
Once the alpha is published:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pipx install openresearchworkspace==0.1.0a1
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Alternatively, in a Python 3.10+ virtual environment:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
python -m pip install openresearchworkspace==0.1.0a1
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Use
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
orw init my-study
|
|
48
|
+
orw validate my-study
|
|
49
|
+
orw validate my-study --json
|
|
50
|
+
orw export my-study --format ro-crate --output my-study-crate
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Automated initialization accepts the normalized setup contract through `--config setup.json` or `--config -` for standard input. Normal initialization requires a new or empty destination. Export destinations must be outside the source workspace. `--force` only replaces a previously marked ORW export whose files have not been added, removed, or changed.
|
|
54
|
+
|
|
55
|
+
## Browser path
|
|
56
|
+
|
|
57
|
+
The matching standalone HTML generator is distributed separately as a versioned release asset. Open it in a browser, describe the project, review the structure and metadata, and download a workspace ZIP. Python is not required by that browser path. The ZIP is not encrypted and exporting it does not publish anything.
|
|
58
|
+
|
|
59
|
+
## Alpha boundaries
|
|
60
|
+
|
|
61
|
+
This release is for evaluation on disposable copies. It is not a complete research-data repository, a security sandbox, or a guarantee of FAIR compliance. Initialization creates one Study and an optional first Assay. Browser editing of existing workspaces, DOI deposition, richer provenance, and agent integrations remain planned.
|
|
62
|
+
|
|
63
|
+
RO-Crate output is a local package, not a publication. Base checks are bounded to the exporter; a dedicated ORW RO-Crate Profile is not claimed. Metadata and the project README are included, so inspect them for sensitive information before sharing. Only explicitly open local resources are copied; overlapping open/restricted declarations are refused. Metadata access labels are not filesystem permissions or encryption. Mutation operations require exclusive workspace access; concurrent or hostile filesystem mutation is outside the alpha's guarantees.
|
|
64
|
+
|
|
65
|
+
## Documentation and source
|
|
66
|
+
|
|
67
|
+
[CLI guide](https://github.com/dhuzard/OpenResearchWorkspace/blob/main/docs/cli.md) · [Browser guide](https://github.com/dhuzard/OpenResearchWorkspace/blob/main/docs/browser-generator.md) · [Release process](https://github.com/dhuzard/OpenResearchWorkspace/blob/main/docs/releases.md) · [Issues](https://github.com/dhuzard/OpenResearchWorkspace/issues)
|
|
68
|
+
|
|
69
|
+
The software is MIT licensed. Research outputs do not automatically inherit that license. ORW specification and template versions are independent of the software release version.
|