data-refinery-cli 0.5.1__tar.gz → 0.5.2__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.
- data_refinery_cli-0.5.2/.github/workflows/publish-stack.yml +175 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/CHANGELOG.md +6 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/CLAUDE.md +3 -1
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/PKG-INFO +1 -1
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/docs/stack-image.md +15 -5
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/pyproject.toml +1 -1
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/uv.lock +1 -1
- data_refinery_cli-0.5.1/.github/workflows/publish-stack.yml +0 -95
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/agent-config/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/agent-config/scripts/show.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/prompts/explore.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/prompts/review.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/prompts/write.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/scripts/ask-colleague.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/run-tests/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/think/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/think/scripts/think.sh +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/version-bump/SKILL.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills.local.yaml.example +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.devague/current +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.devague/current_plan +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.devague/frames/data-refinery-cli-ships-the-storage-data-quality-i.json +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.devague/plans/data-refinery-cli-ships-the-storage-data-quality-i.json +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.flake8 +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.github/workflows/publish.yml +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.github/workflows/tests.yml +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.gitignore +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.markdownlint-cli2.yaml +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/AGENTS.colleague.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/LICENSE +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/README.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/culture.yaml +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/__main__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/cli.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/doctor.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/explain.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/learn.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/overview.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/quality.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/stack.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/store.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_commands/whoami.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_errors.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/cli/_output.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/explain/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/explain/catalog.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/quality/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/quality/checks.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/backend.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/backends/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/backends/files.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/backends/mongo.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/backends/neo4j.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/envelope.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/docker-compose.yml +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/docs/contract.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/docs/plans/2026-06-20-data-refinery-cli-ships-the-storage-data-quality-i.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/docs/skill-sources.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/docs/specs/2026-06-20-data-refinery-cli-ships-the-storage-data-quality-i.md +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/sonar-project.properties +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/__init__.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/conftest.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_cli.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_cli_introspection.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_live_stack.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_no_optional_top_import.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_quality.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_scope_no_leak.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_stack.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_store_adapters.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_store_api.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_store_backends.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_store_cli.py +0 -0
- {data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/tests/test_store_envelope.py +0 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
name: Release — auto-tag + conditional stack publish
|
|
2
|
+
|
|
3
|
+
# On every push to main (a merged PR) this tags the commit `vX.Y.Z` from the
|
|
4
|
+
# pyproject version, so git tags track the PyPI release 1:1 (PyPI itself is
|
|
5
|
+
# published by publish.yml on the same push). The storage-stack OCI artifact
|
|
6
|
+
# (docker-compose.yml -> ghcr.io/<owner>/data-refinery-stack) is republished
|
|
7
|
+
# ONLY when docker-compose.yml actually changed since the previous tag — most
|
|
8
|
+
# PRs touch CLI code, not the substrate, so the image would otherwise be
|
|
9
|
+
# byte-identical churn.
|
|
10
|
+
#
|
|
11
|
+
# Manual (re)publish of a specific version: run via workflow_dispatch with the
|
|
12
|
+
# tag input; that always publishes the stack for that tag.
|
|
13
|
+
#
|
|
14
|
+
# When the stack IS published, two consumption paths ship for the version:
|
|
15
|
+
# 1. OCI via `docker compose publish` —
|
|
16
|
+
# ghcr.io/<owner>/data-refinery-stack:<version> (+ :latest). A single
|
|
17
|
+
# manifest REFERENCING upstream mongo:8.0 + neo4j:5-community (not a custom
|
|
18
|
+
# image). Consume with:
|
|
19
|
+
# docker compose -f oci://ghcr.io/<owner>/data-refinery-stack:<version> up -d
|
|
20
|
+
# 2. The raw docker-compose.yml attached to the GitHub Release.
|
|
21
|
+
#
|
|
22
|
+
# Tags/releases are immutable per version: a given <version> is published once.
|
|
23
|
+
|
|
24
|
+
on:
|
|
25
|
+
push:
|
|
26
|
+
branches: [main]
|
|
27
|
+
workflow_dispatch:
|
|
28
|
+
inputs:
|
|
29
|
+
tag:
|
|
30
|
+
description: "Tag to (re)publish the stack for, e.g. v0.5.0"
|
|
31
|
+
required: true
|
|
32
|
+
|
|
33
|
+
jobs:
|
|
34
|
+
tag:
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
permissions:
|
|
37
|
+
contents: write # push the version tag
|
|
38
|
+
outputs:
|
|
39
|
+
tag: ${{ steps.plan.outputs.tag }}
|
|
40
|
+
version: ${{ steps.plan.outputs.version }}
|
|
41
|
+
publish: ${{ steps.plan.outputs.publish }}
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
44
|
+
with:
|
|
45
|
+
fetch-depth: 0
|
|
46
|
+
fetch-tags: true
|
|
47
|
+
|
|
48
|
+
- name: Plan tag + compose-change gate
|
|
49
|
+
id: plan
|
|
50
|
+
env:
|
|
51
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
52
|
+
INPUT_TAG: ${{ github.event.inputs.tag }}
|
|
53
|
+
run: |
|
|
54
|
+
set -euo pipefail
|
|
55
|
+
|
|
56
|
+
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
|
|
57
|
+
# Manual: (re)publish exactly the requested tag, always.
|
|
58
|
+
TAG="$INPUT_TAG"
|
|
59
|
+
VERSION="${TAG#v}"
|
|
60
|
+
PUBLISH="true"
|
|
61
|
+
echo "Manual dispatch: will publish stack for ${TAG}"
|
|
62
|
+
else
|
|
63
|
+
# Push to main: derive the version from pyproject and tag it.
|
|
64
|
+
VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml | head -n1)"
|
|
65
|
+
if [ -z "$VERSION" ]; then
|
|
66
|
+
echo "::error::could not read version from pyproject.toml"
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
TAG="v${VERSION}"
|
|
70
|
+
# Previous tag = highest v* EXCLUDING the current one. Excluding TAG
|
|
71
|
+
# matters on a re-run: if an earlier run pushed the tag but then
|
|
72
|
+
# failed before publishing, we must still compare against the real
|
|
73
|
+
# previous release and be able to re-publish to recover — never treat
|
|
74
|
+
# "tag exists" as "already published" and skip. Tag CREATION below is
|
|
75
|
+
# still idempotent (skipped when the tag exists); only publishing is
|
|
76
|
+
# decided by the compose-change gate.
|
|
77
|
+
PREV="$(git tag --list 'v*' --sort=-v:refname | grep -vxF "${TAG}" | head -n1 || true)"
|
|
78
|
+
if [ -z "$PREV" ] || ! git diff --quiet "${PREV}" HEAD -- docker-compose.yml; then
|
|
79
|
+
PUBLISH="true"
|
|
80
|
+
echo "Substrate changed (or bootstrap) since ${PREV:-none} — will publish stack."
|
|
81
|
+
else
|
|
82
|
+
PUBLISH="false"
|
|
83
|
+
echo "docker-compose.yml unchanged since ${PREV} — tag only, no stack publish."
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Create the tag if it does not exist yet (push: always new here;
|
|
88
|
+
# dispatch: only when targeting a not-yet-created tag).
|
|
89
|
+
if ! git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
|
|
90
|
+
git config user.name "github-actions[bot]"
|
|
91
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
92
|
+
git tag -a "${TAG}" -m "data-refinery-cli ${TAG}"
|
|
93
|
+
git push origin "${TAG}"
|
|
94
|
+
echo "Created and pushed ${TAG}"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
{
|
|
98
|
+
echo "tag=${TAG}"
|
|
99
|
+
echo "version=${VERSION}"
|
|
100
|
+
echo "publish=${PUBLISH}"
|
|
101
|
+
} >> "$GITHUB_OUTPUT"
|
|
102
|
+
|
|
103
|
+
publish-stack:
|
|
104
|
+
needs: tag
|
|
105
|
+
if: needs.tag.outputs.publish == 'true'
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
permissions:
|
|
108
|
+
contents: write # create/attach the release asset
|
|
109
|
+
packages: write # push the OCI artifact to GHCR
|
|
110
|
+
steps:
|
|
111
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
112
|
+
with:
|
|
113
|
+
ref: ${{ needs.tag.outputs.tag }}
|
|
114
|
+
|
|
115
|
+
- name: Resolve image ref
|
|
116
|
+
id: ref
|
|
117
|
+
run: |
|
|
118
|
+
IMAGE="ghcr.io/${GITHUB_REPOSITORY_OWNER}/data-refinery-stack"
|
|
119
|
+
IMAGE="$(echo "$IMAGE" | tr '[:upper:]' '[:lower:]')"
|
|
120
|
+
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
|
|
121
|
+
echo "Publishing ${IMAGE}:${{ needs.tag.outputs.version }}"
|
|
122
|
+
|
|
123
|
+
- name: Verify compose + OCI publish support
|
|
124
|
+
run: |
|
|
125
|
+
docker compose version
|
|
126
|
+
docker compose -f docker-compose.yml config --quiet
|
|
127
|
+
# `docker compose publish` landed in Compose v2.24 — fail early with a
|
|
128
|
+
# clear message on an older runner instead of a cryptic publish error.
|
|
129
|
+
docker compose publish --help >/dev/null 2>&1 || {
|
|
130
|
+
echo "::error::this docker compose has no 'publish' subcommand (needs v2.24+)"
|
|
131
|
+
exit 1
|
|
132
|
+
}
|
|
133
|
+
echo "compose validates; publish supported"
|
|
134
|
+
|
|
135
|
+
- name: Log in to GHCR
|
|
136
|
+
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
|
137
|
+
|
|
138
|
+
- name: Publish compose as an OCI artifact
|
|
139
|
+
env:
|
|
140
|
+
IMAGE: ${{ steps.ref.outputs.image }}
|
|
141
|
+
VERSION: ${{ needs.tag.outputs.version }}
|
|
142
|
+
run: |
|
|
143
|
+
docker compose -f docker-compose.yml publish "${IMAGE}:${VERSION}" -y
|
|
144
|
+
docker compose -f docker-compose.yml publish "${IMAGE}:latest" -y
|
|
145
|
+
|
|
146
|
+
- name: Attach docker-compose.yml to the release (portable fallback)
|
|
147
|
+
env:
|
|
148
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
149
|
+
RAW_TAG: ${{ needs.tag.outputs.tag }}
|
|
150
|
+
IMAGE: ${{ steps.ref.outputs.image }}
|
|
151
|
+
VERSION: ${{ needs.tag.outputs.version }}
|
|
152
|
+
run: |
|
|
153
|
+
if gh release view "${RAW_TAG}" >/dev/null 2>&1; then
|
|
154
|
+
gh release upload "${RAW_TAG}" docker-compose.yml --clobber
|
|
155
|
+
else
|
|
156
|
+
# --target pins the release (and the tag) at this commit, so a manual
|
|
157
|
+
# dispatch for a not-yet-existing tag still works.
|
|
158
|
+
gh release create "${RAW_TAG}" docker-compose.yml \
|
|
159
|
+
--target "${GITHUB_SHA}" \
|
|
160
|
+
--title "${RAW_TAG}" \
|
|
161
|
+
--notes "Storage stack (mongo 27018 + neo4j 7687). OCI: docker compose -f oci://${IMAGE}:${VERSION} up -d"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
- name: Summary
|
|
165
|
+
env:
|
|
166
|
+
IMAGE: ${{ steps.ref.outputs.image }}
|
|
167
|
+
VERSION: ${{ needs.tag.outputs.version }}
|
|
168
|
+
RAW_TAG: ${{ needs.tag.outputs.tag }}
|
|
169
|
+
run: |
|
|
170
|
+
{
|
|
171
|
+
echo "### Storage stack published"
|
|
172
|
+
echo ""
|
|
173
|
+
echo "- OCI: \`docker compose -f oci://${IMAGE}:${VERSION} up -d\`"
|
|
174
|
+
echo "- Release asset: \`docker-compose.yml\` on release ${RAW_TAG}"
|
|
175
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/). This project
|
|
6
6
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.5.2] - 2026-06-21
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `publish-stack.yml` now runs on every push to `main`: a `tag` job derives the version from `pyproject.toml` and creates the `v<version>` git tag (tags now track the PyPI release 1:1), and the stack OCI image is **republished only when `docker-compose.yml` changed** since the previous tag — most releases bump the CLI, not the substrate, so the image no longer churns on every merge. A `workflow_dispatch` with a `tag` input still force-(re)publishes a specific version. (`docs/stack-image.md` + `CLAUDE.md` updated.)
|
|
13
|
+
|
|
8
14
|
## [0.5.1] - 2026-06-21
|
|
9
15
|
|
|
10
16
|
### Changed
|
|
@@ -14,7 +14,9 @@ and freshness of data as it is stored and fetched. It is being split out of
|
|
|
14
14
|
*Wave 1* (issue #1): the storage substrate (`docker-compose.yml` — mongo 27018 +
|
|
15
15
|
neo4j 7687/apoc) and the `data-refinery stack up/down/status` verb wrapping
|
|
16
16
|
`docker compose`, plus the GHCR publish workflow
|
|
17
|
-
(`.github/workflows/publish-stack.yml`
|
|
17
|
+
(`.github/workflows/publish-stack.yml` — on every push to `main` it auto-tags
|
|
18
|
+
`v<version>` from `pyproject.toml`, then republishes the stack OCI image **only
|
|
19
|
+
when `docker-compose.yml` changed** since the previous tag) and the pinnable docs
|
|
18
20
|
(`docs/stack-image.md`, `docs/contract.md`). *Wave 2* (issue #3): the
|
|
19
21
|
storage-neutral **store** — the generic envelope (`data_refinery/store/`), the
|
|
20
22
|
importable `data_refinery.store.put/get/list` library mirrored by `data-refinery
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: data-refinery-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Agent and CLI for data quality in storage and retrieval — validating, deduplicating, and checking the integrity and freshness of data as it is stored and fetched. Split out of eidetic-cli so eidetic keeps agent-memory; sibling to daria, the Data Refinery Intelligent Agent.
|
|
5
5
|
Project-URL: Homepage, https://github.com/agentculture/data-refinery-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/agentculture/data-refinery-cli/issues
|
|
@@ -33,8 +33,13 @@ project.
|
|
|
33
33
|
- **Name:** `ghcr.io/agentculture/data-refinery-stack`
|
|
34
34
|
- **Tags:** the release version without the leading `v` (e.g. `0.4.0`), plus
|
|
35
35
|
`latest`.
|
|
36
|
-
- **Immutability:** a given version tag is published exactly once
|
|
37
|
-
`
|
|
36
|
+
- **Immutability:** a given version tag is published exactly once. Treat
|
|
37
|
+
`0.4.0` as immutable; `latest` floats.
|
|
38
|
+
- **Cadence:** the image is **only (re)published when `docker-compose.yml`
|
|
39
|
+
actually changes** between releases — most releases bump the CLI, not the
|
|
40
|
+
substrate, so the stack image stays put while the PyPI version moves. The
|
|
41
|
+
image version therefore tracks the latest release in which the compose
|
|
42
|
+
changed, not every release.
|
|
38
43
|
|
|
39
44
|
> **Not a multi-arch image.** The published artifact is a single OCI manifest
|
|
40
45
|
> produced by `docker compose publish` — it *references* the upstream `mongo:8.0`
|
|
@@ -81,6 +86,11 @@ consumer that needs byte-for-byte reproducibility should pin the upstream image
|
|
|
81
86
|
## Publishing
|
|
82
87
|
|
|
83
88
|
[`.github/workflows/publish-stack.yml`](../.github/workflows/publish-stack.yml)
|
|
84
|
-
runs on
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
runs on every **push to `main`** (a merged PR). Its `tag` job derives the version
|
|
90
|
+
from `pyproject.toml` and creates the `v<version>` git tag (so tags track the
|
|
91
|
+
PyPI release 1:1), then gates: it only proceeds to publish when `docker-compose.yml`
|
|
92
|
+
differs from the previous tag. When it does, the `publish-stack` job validates the
|
|
93
|
+
compose, logs in to GHCR with the workflow token, `docker compose publish`es the
|
|
94
|
+
OCI artifact at the version tag and `latest`, and attaches `docker-compose.yml` to
|
|
95
|
+
the release. A `workflow_dispatch` with a `tag` input force-(re)publishes a
|
|
96
|
+
specific version's stack regardless of the gate.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "data-refinery-cli"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.2"
|
|
4
4
|
description = "Agent and CLI for data quality in storage and retrieval — validating, deduplicating, and checking the integrity and freshness of data as it is stored and fetched. Split out of eidetic-cli so eidetic keeps agent-memory; sibling to daria, the Data Refinery Intelligent Agent."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
name: Publish storage stack to GHCR
|
|
2
|
-
|
|
3
|
-
# Publishes the storage substrate (docker-compose.yml) on a version tag.
|
|
4
|
-
#
|
|
5
|
-
# Two consumption paths are published for the same version (issue #1):
|
|
6
|
-
# 1. An OCI artifact via `docker compose publish` —
|
|
7
|
-
# ghcr.io/agentculture/data-refinery-stack:<version> (+ :latest).
|
|
8
|
-
# The artifact is a SINGLE manifest that REFERENCES the upstream
|
|
9
|
-
# mongo:8.0 + neo4j:5-community images (which are themselves multi-arch);
|
|
10
|
-
# it is not a custom multi-arch image. Consume with:
|
|
11
|
-
# docker compose -f oci://ghcr.io/agentculture/data-refinery-stack:<version> up -d
|
|
12
|
-
# 2. The raw docker-compose.yml attached to the GitHub Release, for consumers
|
|
13
|
-
# whose docker/compose predates OCI compose support — curl + `-f` it.
|
|
14
|
-
#
|
|
15
|
-
# Tags are immutable per release: a given <version> is published once.
|
|
16
|
-
|
|
17
|
-
on:
|
|
18
|
-
push:
|
|
19
|
-
tags:
|
|
20
|
-
- "v*"
|
|
21
|
-
workflow_dispatch:
|
|
22
|
-
inputs:
|
|
23
|
-
tag:
|
|
24
|
-
description: "Tag to publish (e.g. v0.4.0)"
|
|
25
|
-
required: true
|
|
26
|
-
|
|
27
|
-
permissions:
|
|
28
|
-
contents: write # create/attach the release asset
|
|
29
|
-
packages: write # push the OCI artifact to GHCR
|
|
30
|
-
|
|
31
|
-
jobs:
|
|
32
|
-
publish-stack:
|
|
33
|
-
runs-on: ubuntu-latest
|
|
34
|
-
steps:
|
|
35
|
-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
36
|
-
|
|
37
|
-
- name: Resolve version + image ref
|
|
38
|
-
id: ref
|
|
39
|
-
run: |
|
|
40
|
-
RAW_TAG="${{ github.event.inputs.tag || github.ref_name }}"
|
|
41
|
-
VERSION="${RAW_TAG#v}"
|
|
42
|
-
IMAGE="ghcr.io/${GITHUB_REPOSITORY_OWNER}/data-refinery-stack"
|
|
43
|
-
IMAGE="$(echo "$IMAGE" | tr '[:upper:]' '[:lower:]')"
|
|
44
|
-
echo "raw_tag=${RAW_TAG}" >> "$GITHUB_OUTPUT"
|
|
45
|
-
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
46
|
-
echo "image=${IMAGE}" >> "$GITHUB_OUTPUT"
|
|
47
|
-
echo "Publishing ${IMAGE}:${VERSION}"
|
|
48
|
-
|
|
49
|
-
- name: Verify compose + OCI publish support
|
|
50
|
-
run: |
|
|
51
|
-
docker compose version
|
|
52
|
-
docker compose -f docker-compose.yml config --quiet
|
|
53
|
-
# `docker compose publish` landed in Compose v2.24 — fail early with a
|
|
54
|
-
# clear message on an older runner instead of a cryptic publish error.
|
|
55
|
-
docker compose publish --help >/dev/null 2>&1 || {
|
|
56
|
-
echo "::error::this docker compose has no 'publish' subcommand (needs v2.24+)"
|
|
57
|
-
exit 1
|
|
58
|
-
}
|
|
59
|
-
echo "compose validates; publish supported"
|
|
60
|
-
|
|
61
|
-
- name: Log in to GHCR
|
|
62
|
-
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
|
63
|
-
|
|
64
|
-
- name: Publish compose as an OCI artifact
|
|
65
|
-
env:
|
|
66
|
-
IMAGE: ${{ steps.ref.outputs.image }}
|
|
67
|
-
VERSION: ${{ steps.ref.outputs.version }}
|
|
68
|
-
run: |
|
|
69
|
-
docker compose -f docker-compose.yml publish "${IMAGE}:${VERSION}" -y
|
|
70
|
-
docker compose -f docker-compose.yml publish "${IMAGE}:latest" -y
|
|
71
|
-
|
|
72
|
-
- name: Attach docker-compose.yml to the release (portable fallback)
|
|
73
|
-
env:
|
|
74
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
75
|
-
RAW_TAG: ${{ steps.ref.outputs.raw_tag }}
|
|
76
|
-
run: |
|
|
77
|
-
if gh release view "${RAW_TAG}" >/dev/null 2>&1; then
|
|
78
|
-
gh release upload "${RAW_TAG}" docker-compose.yml --clobber
|
|
79
|
-
else
|
|
80
|
-
# --target pins the release (and creates the tag) at this commit, so
|
|
81
|
-
# a manual workflow_dispatch with a not-yet-existing tag still works.
|
|
82
|
-
gh release create "${RAW_TAG}" docker-compose.yml \
|
|
83
|
-
--target "${GITHUB_SHA}" \
|
|
84
|
-
--title "${RAW_TAG}" \
|
|
85
|
-
--notes "Storage stack (mongo 27018 + neo4j 7687). OCI: docker compose -f oci://${{ steps.ref.outputs.image }}:${{ steps.ref.outputs.version }} up -d"
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
- name: Summary
|
|
89
|
-
run: |
|
|
90
|
-
{
|
|
91
|
-
echo "### Storage stack published"
|
|
92
|
-
echo ""
|
|
93
|
-
echo "- OCI: \`docker compose -f oci://${{ steps.ref.outputs.image }}:${{ steps.ref.outputs.version }} up -d\`"
|
|
94
|
-
echo "- Release asset: \`docker-compose.yml\` on release ${{ steps.ref.outputs.raw_tag }}"
|
|
95
|
-
} >> "$GITHUB_STEP_SUMMARY"
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/agent-config/scripts/show.sh
RENAMED
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/prompts/explore.md
RENAMED
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/prompts/review.md
RENAMED
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/ask-colleague/prompts/write.md
RENAMED
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/assign-to-workforce/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/_resolve-nick.sh
RENAMED
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/portability-lint.sh
RENAMED
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/cicd/scripts/pr-status.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/communicate/scripts/post-issue.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/doc-test-alignment/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/run-tests/scripts/test.sh
RENAMED
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/sonarclaude/scripts/sonar.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/.claude/skills/version-bump/scripts/bump.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{data_refinery_cli-0.5.1 → data_refinery_cli-0.5.2}/data_refinery/store/backends/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|