feat: add external CLI support for image upload/delete#481
feat: add external CLI support for image upload/delete#481minodisk wants to merge 1 commit intok1LoW:mainfrom
Conversation
## Summary
- Add `-u` (`--image-upload-command`) and `-d` (`--image-delete-command`) flags to the `apply` command
- Enable using external CLI tools for image upload and deletion instead of Google Drive
- Allows integration with custom storage backends (GCS, S3, etc.) via CLI wrappers
- Introduce `Storage` interface for consistent architecture
## Architecture
- `Storage` interface with `Upload()` and `Delete()` methods
- `googleDriveStorage`: default implementation using Google Drive
- `externalStorage`: implementation using external CLI commands
## CLI Specification
### Upload Command
The upload command receives:
- **stdin**: image binary data
- **Environment variable**: `DECK_UPLOAD_MIME` (MIME type of the image)
- **Template variable**: `{{mime}}`, `{{env.XXX}}`
Expected output (stdout):
```
<public URL>
<uploaded ID for deletion>
```
### Delete Command
The delete command receives:
- **Environment variable**: `DECK_DELETE_ID` (uploaded ID to delete)
- **Template variable**: `{{id}}`, `{{env.XXX}}`
## Example Usage
```bash
deck apply -i PRESENTATION_ID \
-u "reprint-gcs upload" \
-d "reprint-gcs delete" \
slides.md
```
## Test plan
- [x] Verify build passes
- [x] Verify existing Google Drive upload still works when no external CLI is specified
- [x] Test with reprint-gcs
|
This is a good idea and a challenge we want to solve. |
|
Thank you for the feedback! On Complexity The design intentionally keeps the default behavior unchanged — users who can use Google Drive don't need any additional configuration. The complexity only applies to users like me who face Google Workspace organizational restrictions and cannot attach images via Google Drive. I also tried implementing GCS support directly inside deck, but it felt unclean to embed specific storage implementations. Delegating to external CLI keeps deck's core simple and allows users to choose their preferred storage backend. On Protocol For the input side, I referenced laminate's protocol — thank you for that elegant design! For the output (which returns 2 values: public URL and uploaded ID), I went with a simple line-based format, but I'm honestly uncertain about this choice and thinking JSON might be better for extensibility. I'd appreciate any feedback on the protocol as a whole if you have suggestions for a better approach. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Code Metrics Report
Details | | main (617ad0b) | main (d7be869) | +/- |
|---------------------|----------------|----------------|------|
| Coverage | 33.8% | 33.8% | 0.0% |
| Files | 31 | 31 | 0 |
| Lines | 3405 | 3405 | 0 |
| Covered | 1151 | 1151 | 0 |
| Code to Test Ratio | 1:0.9 | 1:0.9 | 0.0 |
| Code | 7020 | 7020 | 0 |
| Test | 6581 | 6581 | 0 |
| Test Execution Time | 10s | 10s | 0s |Code coverage of files in pull request scope (42.8% → 42.8%)
Reported by octocov |
Summary
-uand-dflagsStorageinterface to abstract image storage (Google Drive vs external CLI){{mime}},{{id}},{{env.XXX}}) in upload/delete commandsDECK_UPLOAD_MIMEandDECK_DELETE_IDare passed to external commandsMotivation
This provides a workaround for #372.
In restricted Google Workspace environments where public file sharing is prohibited, Google Drive cannot be used for image storage. This feature allows users to use alternative storage backends (e.g., GCS, S3) via external CLI tools.
Usage
External CLI Protocol
Upload command:
DECK_UPLOAD_MIMEcontains the MIME type{{mime}}is also availableDelete command:
DECK_DELETE_IDcontains the uploaded ID{{id}}is also availableExample Implementation
reprint - A GCS-based image storage CLI that implements this protocol
Test plan
🤖 Generated with Claude Code