cli edit for release #40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish to PyPI | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'cli/**' | |
| - 'pyproject.toml' | |
| - '.github/workflows/publish.yml' | |
| permissions: | |
| contents: write | |
| jobs: | |
| test: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| python-version: ['3.10', '3.12', '3.13'] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install pipx | |
| run: pip install pipx | |
| - name: Install package with pipx | |
| run: pipx install . | |
| - name: Install package editable for pytest (pipx env is isolated) | |
| run: pip install -e ".[dev]" | |
| - name: Check drp entrypoint is on PATH | |
| run: drp --version | |
| - name: Check fallback python -m cli also works | |
| run: python -m cli --version | |
| - name: Run unit tests | |
| run: python -m pytest -v | |
| # ── Smoke tests (require DRP_SMOKE_HOST secret) ─────────────────────── | |
| - name: Smoke — text drop upload, get, delete | |
| if: ${{ env.DRP_SMOKE_HOST != '' }} | |
| env: | |
| DRP_SMOKE_HOST: ${{ secrets.DRP_SMOKE_HOST }} | |
| shell: bash | |
| run: | | |
| KEY="ci-smoke-$(python -c 'import uuid; print(uuid.uuid4().hex[:8])')" | |
| python -c " | |
| from cli import config | |
| cfg = config.load() | |
| cfg['host'] = '${{ secrets.DRP_SMOKE_HOST }}' | |
| config.save(cfg) | |
| " | |
| URL=$(drp up "hello from ci ${{ matrix.os }} py${{ matrix.python-version }}" --key "$KEY") | |
| echo "Uploaded: $URL" | |
| [ -z "$URL" ] && { echo "Upload returned empty URL"; exit 1; } | |
| RESULT=$(drp get "$KEY") | |
| echo "Got: $RESULT" | |
| echo "$RESULT" | grep -q "hello from ci" || { echo "Content mismatch"; exit 1; } | |
| drp ls | grep -q "$KEY" || { echo "Key not found in drp ls"; exit 1; } | |
| drp rm "$KEY" | |
| drp get "$KEY" && { echo "Drop still accessible after delete"; exit 1; } || true | |
| - name: Smoke — file drop upload, get | |
| if: ${{ env.DRP_SMOKE_HOST != '' }} | |
| env: | |
| DRP_SMOKE_HOST: ${{ secrets.DRP_SMOKE_HOST }} | |
| shell: bash | |
| run: | | |
| KEY="ci-file-$(python -c 'import uuid; print(uuid.uuid4().hex[:8])')" | |
| CONTENT="file content from ${{ matrix.os }}" | |
| python -c " | |
| with open('ci_test_file.txt', 'w') as f: | |
| f.write('$CONTENT') | |
| " | |
| URL=$(drp up ci_test_file.txt --key "$KEY") | |
| echo "Uploaded file: $URL" | |
| [ -z "$URL" ] && { echo "File upload returned empty URL"; exit 1; } | |
| echo "$URL" | grep -q '/f/' || { echo "File URL missing /f/ prefix"; exit 1; } | |
| drp get -f "$KEY" -o ci_downloaded.txt | |
| python -c " | |
| content = open('ci_downloaded.txt').read() | |
| assert '$CONTENT' in content, f'Content mismatch: {content!r}' | |
| print('File content verified') | |
| " | |
| drp rm -f "$KEY" | |
| rm -f ci_test_file.txt ci_downloaded.txt | |
| - name: Smoke — authenticated session persists | |
| if: ${{ env.DRP_SMOKE_HOST != '' && env.DRP_SMOKE_EMAIL != '' }} | |
| env: | |
| DRP_SMOKE_HOST: ${{ secrets.DRP_SMOKE_HOST }} | |
| DRP_SMOKE_EMAIL: ${{ secrets.DRP_SMOKE_EMAIL }} | |
| DRP_SMOKE_PASSWORD: ${{ secrets.DRP_SMOKE_PASSWORD }} | |
| shell: bash | |
| run: | | |
| python -c " | |
| import requests | |
| from cli import api, config | |
| from cli.session import save_session | |
| cfg = config.load() | |
| host = cfg['host'] | |
| session = requests.Session() | |
| ok = api.login(host, session, '${{ secrets.DRP_SMOKE_EMAIL }}', '${{ secrets.DRP_SMOKE_PASSWORD }}') | |
| assert ok, 'Login failed' | |
| cfg['email'] = '${{ secrets.DRP_SMOKE_EMAIL }}' | |
| config.save(cfg) | |
| save_session(session) | |
| print('Logged in, session saved') | |
| " | |
| timeout 15 drp ls || { echo "drp ls timed out or failed"; exit 1; } | |
| drp logout | |
| timeout 5 drp ls || true | |
| # ── Publish (only if all tests pass) ────────────────────────────────────── | |
| publish: | |
| needs: test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Bump patch version | |
| id: bump | |
| run: | | |
| current=$(grep -oP "(?<=__version__ = ').*(?=')" cli/__init__.py) | |
| IFS='.' read -r major minor patch <<< "$current" | |
| new_version="$major.$minor.$((patch + 1))" | |
| while git tag | grep -q "^v$new_version$"; do | |
| patch=$((patch + 1)) | |
| new_version="$major.$minor.$patch" | |
| done | |
| sed -i "s/__version__ = '$current'/__version__ = '$new_version'/" cli/__init__.py | |
| echo "version=$new_version" >> "$GITHUB_OUTPUT" | |
| - name: Commit version bump | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add cli/__init__.py | |
| git diff --cached --quiet && exit 0 | |
| git commit -m "v${{ steps.bump.outputs.version }}" | |
| git tag -f "v${{ steps.bump.outputs.version }}" | |
| git push --follow-tags --force-with-lease | |
| - name: Collect commits since last release | |
| run: | | |
| prev_tag=$(git tag --sort=-v:refname | sed -n '2p') | |
| if [ -z "$prev_tag" ]; then | |
| log=$(git log --oneline --no-decorate HEAD) | |
| else | |
| log=$(git log --oneline --no-decorate "$prev_tag"..HEAD~1) | |
| fi | |
| { | |
| echo "$log" | |
| echo "" | |
| echo "Install / upgrade:" | |
| echo '```' | |
| echo 'pipx install drp-cli' | |
| echo '# or upgrade:' | |
| echo 'pipx upgrade drp-cli' | |
| echo '```' | |
| } > /tmp/release_notes.txt | |
| - name: Create GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ steps.bump.outputs.version }} | |
| name: v${{ steps.bump.outputs.version }} | |
| body_path: /tmp/release_notes.txt | |
| - name: Build and publish to PyPI | |
| run: pip install build && python -m build | |
| - uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| password: ${{ secrets.PYPI_API_TOKEN }} |