Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 9 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ jobs:
with:
python-version: "3.12"

- name: Verify release version
run: |
VERSION="$(cat VERSION)"
if [[ "${GITHUB_REF_NAME}" != "v${VERSION}" ]]; then
echo "Tag ${GITHUB_REF_NAME} does not match VERSION ${VERSION}." >&2
exit 1
fi

- name: Build release ZIP
run: |
VERSION="${GITHUB_REF_NAME#v}"
VERSION="$(cat VERSION)"
python scripts/package_release.py --version "${VERSION}"
ls -lah dist

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 1.0.1 - 2026-07-10

- Stop embedding R2 API tokens in generated DuckDB SQL
- Read `ICEBERG_TOKEN` from the DuckDB process environment
- Verify source version declarations and release tags agree

## 1.0.0

Initial release.
Expand Down
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ ruff check .
## Release

```bash
git tag v1.0.0
git push origin v1.0.0
VERSION="$(cat VERSION)"
git tag "v${VERSION}"
git push origin "v${VERSION}"
```

The release workflow builds a ZIP and uploads it to GitHub Releases.
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,12 @@ DuckDB で使う attach SQL を生成します。
iceberg-r2-lab duckdb-sql > .generated/duckdb_attach.sql
```

DuckDB を起動します
生成SQLにtoken値は含まれません。`.env`をshell環境へexportしてからDuckDBを起動します

```bash
set -a
source .env
set +a
duckdb
```

Expand Down Expand Up @@ -211,15 +214,16 @@ make package
出力:

```text
dist/iceberg-r2-online-lab-v1.0.0.zip
dist/iceberg-r2-online-lab-v1.0.0.zip.sha256
dist/iceberg-r2-online-lab-v1.0.1.zip
dist/iceberg-r2-online-lab-v1.0.1.zip.sha256
```

GitHub Actions で release する場合:

```bash
git tag v1.0.0
git push origin v1.0.0
VERSION="$(cat VERSION)"
git tag "v${VERSION}"
git push origin "v${VERSION}"
```

`.github/workflows/release.yml` が release asset として ZIP と SHA256 を添付します。
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.0
1.0.1
29 changes: 25 additions & 4 deletions docs/duckdb-ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,31 @@
iceberg-r2-lab duckdb-sql > .generated/duckdb_attach.sql
```

`.generated/duckdb_attach.sql` には token が入るため、commit しないでください
生成SQLにはtoken値を埋め込みません。DuckDB 1.3以降の`getenv()`を使い、実行時に`ICEBERG_TOKEN`を読みます

## DuckDB

`.env`の値をshell環境へexportしてからDuckDBを起動します。

### bash / zsh

```bash
set -a
source .env
set +a
duckdb
```

### PowerShell

```powershell
$line = Get-Content .env | Where-Object { $_ -match '^ICEBERG_TOKEN=' }
$env:ICEBERG_TOKEN = $line.Split('=', 2)[1]
duckdb
```

token値をcommand lineへ直接書かないため、shell historyにもtoken literalを残しません。

```sql
.read .generated/duckdb_attach.sql

Expand All @@ -35,7 +52,7 @@ LOAD httpfs;

CREATE SECRET r2_iceberg_secret (
TYPE iceberg,
TOKEN '<ICEBERG_TOKEN>'
TOKEN getenv('ICEBERG_TOKEN')
);

ATTACH '<ICEBERG_WAREHOUSE>' AS r2_iceberg (
Expand All @@ -60,5 +77,9 @@ LOAD httpfs;

### token が漏れそう

生成済み SQL は `.generated/` に置きます。
`.generated/` は `.gitignore` に含まれています。
生成SQLにはtoken値が入りません。`ICEBERG_TOKEN`はDuckDB processの環境だけに渡してください。
DuckDB CLIへtoken literalを含む`CREATE SECRET`を直接入力するとhistoryへ残るため、`getenv()`を使います。

### `getenv('ICEBERG_TOKEN')` が空になる

Python CLIは`.env`を読みますが、別processで起動したDuckDBには自動継承されません。上記のbash / zshまたはPowerShell手順で環境変数を設定してから起動してください。
14 changes: 8 additions & 6 deletions docs/release-ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,24 @@ make package
出力:

```text
dist/iceberg-r2-online-lab-v1.0.0.zip
dist/iceberg-r2-online-lab-v1.0.0.zip.sha256
dist/iceberg-r2-online-lab-v1.0.1.zip
dist/iceberg-r2-online-lab-v1.0.1.zip.sha256
```

## GitHub release

```bash
git tag v1.0.0
git push origin v1.0.0
VERSION="$(cat VERSION)"
git tag "v${VERSION}"
git push origin "v${VERSION}"
```

`.github/workflows/release.yml` が ZIP と SHA256 を GitHub Release に添付します。

## Verify SHA256

```bash
shasum -a 256 dist/iceberg-r2-online-lab-v1.0.0.zip
cat dist/iceberg-r2-online-lab-v1.0.0.zip.sha256
VERSION="$(cat VERSION)"
shasum -a 256 "dist/iceberg-r2-online-lab-v${VERSION}.zip"
cat "dist/iceberg-r2-online-lab-v${VERSION}.zip.sha256"
```
3 changes: 2 additions & 1 deletion examples/duckdb/attach_r2_template.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
-- Replace placeholders before running.
-- Do not commit a filled-in version of this file.
-- Export ICEBERG_TOKEN before starting DuckDB; the token is not embedded here.

INSTALL iceberg;
LOAD iceberg;
Expand All @@ -9,7 +10,7 @@ LOAD httpfs;

CREATE SECRET r2_iceberg_secret (
TYPE iceberg,
TOKEN '<ICEBERG_TOKEN>'
TOKEN getenv('ICEBERG_TOKEN')
);

ATTACH '<ICEBERG_WAREHOUSE>' AS r2_iceberg (
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "iceberg-r2-online-lab"
version = "1.0.0"
version = "1.0.1"
description = "A low-cost online Apache Iceberg lab using Cloudflare R2 Data Catalog"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
2 changes: 1 addition & 1 deletion src/iceberg_r2_lab/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Iceberg R2 Online Lab."""

__version__ = "1.0.0"
__version__ = "1.0.1"
7 changes: 3 additions & 4 deletions src/iceberg_r2_lab/duckdb_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ def generate_attach_sql(settings: Settings) -> str:
)
warehouse = sql_quote(settings.warehouse)
endpoint = sql_quote(settings.catalog_uri)
token = sql_quote(settings.token)

return f"""-- Generated by iceberg-r2-lab duckdb-sql.
-- This file contains a token. Do not commit it.
-- DuckDB CLI may store CREATE SECRET statements in command history.
-- The token is read from ICEBERG_TOKEN at execution time and is not embedded here.
-- Start DuckDB with ICEBERG_TOKEN exported in its environment.

INSTALL iceberg;
LOAD iceberg;
Expand All @@ -43,7 +42,7 @@ def generate_attach_sql(settings: Settings) -> str:

CREATE SECRET r2_iceberg_secret (
TYPE iceberg,
TOKEN {token}
TOKEN getenv('ICEBERG_TOKEN')
);

ATTACH {warehouse} AS {alias} (
Expand Down
7 changes: 4 additions & 3 deletions tests/test_duckdb_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@
from iceberg_r2_lab.settings import Settings


def test_generate_attach_sql_escapes_token():
def test_generate_attach_sql_reads_token_from_environment():
settings = Settings(
catalog_uri="https://example.com/catalog",
warehouse="warehouse",
token="abc'def",
token="never-write-this-token",
)

sql = generate_attach_sql(settings)

assert "CREATE SECRET" in sql
assert "abc''def" in sql
assert "TOKEN getenv('ICEBERG_TOKEN')" in sql
assert settings.token not in sql
assert "INSTALL httpfs;" in sql
assert "LOAD httpfs;" in sql
assert "ATTACH 'warehouse' AS \"r2_iceberg\"" in sql
Expand Down
17 changes: 17 additions & 0 deletions tests/test_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from pathlib import Path
import re

from iceberg_r2_lab import __version__


ROOT = Path(__file__).parents[1]


def test_version_declarations_agree():
release_version = (ROOT / "VERSION").read_text(encoding="utf-8").strip()
pyproject = (ROOT / "pyproject.toml").read_text(encoding="utf-8")
match = re.search(r'^version = "([^"]+)"$', pyproject, flags=re.MULTILINE)

assert match is not None
assert match.group(1) == release_version
assert __version__ == release_version