Repository navigation
Releases: shiroemons/gcs-mimic
Release list
v0.7.0
gcs-mimic 0.7.0
0.7.0 makes gcs-mimic a drop-in replacement for an existing fake-gcs-server
deployment: the image name is the only required change, and fake-gcs-server
flags and FAKE_GCS_* variables now start the server with a warning instead
of stopping it. It also adds a verified Rails Active Storage setup for
development and test, and SDK setup for Go, Ruby, Node.js, Python and PHP.
It publishes ghcr.io/shiroemons/gcs-mimic:0.7.0 for linux/amd64 and
linux/arm64, mirrors the same digest to Docker Hub as
shiroemons/gcs-mimic:0.7.0, and publishes native archives for all eight
macOS, Windows and Linux targets. The 0.6.0 release notes describe
the previous published release; the feature matrix
lists the exact supported subsets.
Changes
fake-gcs-server settings
servetranslates fake-gcs-server flags (one or two hyphens) and the known
FAKE_GCS_*variables that have a native equivalent: scheme, host and port,
HTTP port, external URL, public host, data, TLS files, CORS headers,
location and log level. Each one logs a warning naming itsGCS_MIMIC_*
replacement. A flag outranks a variable, as in fake-gcs-server, and within
one source a translation overrides a native value with a warning, so the
image's ownGCS_MIMIC_LISTENdoes not defeat an existingFAKE_GCS_PORT.- A command line that starts with a fake-gcs-server flag runs
serve, so a
Composecommandwritten for fake-gcs-server works unchanged. -backend memoryand-filesystem-rootonly warn. Data is kept in
GCS_MIMIC_DATA_DIR;-filesystem-rootis not used as the data directory,
because a reused fake-gcs-server volume is owned by root and the image runs
as UID 10001.- Event settings (
-event.*,FAKE_GCS_EVENT_*) and unknown backends still
stop startup, so a test that waits for notifications fails visibly. - Helper commands such as
healthcheckandurlstill reject legacy names.
Container healthcheck
- When gcs-mimic runs as PID 1, as in the image, and the probe derived from
the environment fails,gcs-mimic healthcheckretries with the server's own
command-line options, so a Composecommandsuch as-scheme httpno
longer leaves the container unhealthy. Ordinary setups never read them.
On Apple Silicon, a read-only amd64 container under Rosetta cannot use this
fallback, because Rosetta needs a writable root to emulate the process's
/procentry; use the native arm64 image orGCS_MIMIC_*variables there.
Authentication
- In strict mode, an unknown bearer token shaped like a JWT, such as the
self-signed token googleauth sends for a non-Googleuniverse_domain, logs
oneauth_self_signed_jwt_rejectedwarning per process. The401 Invalid Credentialsresponse is unchanged, and the token is not logged.
Documentation
- Rails Active Storage: one
config/storage.yml
entry with a non-Googleuniverse_domainlets Active Storage use the
emulator in development and test without contacting Google OAuth, while
production keeps its own entry. The page covers the bucket file with CORS,
Rails in Compose with thegcs.localhostalias, and CI. - SDK setup gives copyable Go, Ruby, Node.js, Python and PHP
settings and notes whereSTORAGE_EMULATOR_HOSTdiffers between SDKs. - The README was rewritten around the quick start, Compose, SDK setup and
migration. The quick start now retries the first request with
--retry-all-errors, because the published port can return an empty reply
right afterdocker run.
SDK tests
just check-active-storageaddsattachments.rb, which checks the
documentedstorage.ymlentry through ahas_one_attachedmodel: uploads,
URLs, redirect and proxy serving, V2 and V4 direct uploads with
browser-equivalent CORS requests, no OAuth request 400 days after startup,
and a production boot that generates no key.
Compatibility and migration
0.7.0 uses the same catalog schema, 35, as 0.6.0, so a data directory from
0.6.0 needs no migration. Upgrading from 0.4.1 or earlier also applies the
0.5.0 migration.
- fake-gcs-server flags and
FAKE_GCS_*variables that stopped startup in
0.6.0 now start the server and warn. Remove them, or rename them to the
GCS_MIMIC_*names in the warnings, to silence the warnings. - Within one source, a
FAKE_GCS_*value now overrides aGCS_MIMIC_*value
for the same setting. Remove one of them if both are set. - Rails apps that followed the earlier application-built Active Storage recipe
should switch to thestorage.ymlentry: the earlier recipe's one-day token
expiry made googleauth try to refresh at Google after a day.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls,
and the Docker Hub workflow mirrors that digest.
Before the release commit, the pre-push checks passed locally on macOS: format,
clippy, cross-compilation checks including the Linux glibc target, all 49 Rust
test binaries and doctests, the compatibility ledger check, the pinned Go,
Ruby, Node.js, Python and PHP SDK suites, and both Linux container smoke
tests. The release-input freshness check
(cargo xtask dependencies check --scope release) reported every input
current.
The first pre-push run failed the linux/amd64 container smoke test: on Apple
Silicon, Rosetta crashed the healthcheck while it read /proc/1/cmdline on the
read-only root, and the published 0.6.0 image stayed healthy in the same
setup. The healthcheck now reads PID 1's options only after the environment's
probe fails, and the complete pre-push run passed on the final source.
just check-active-storage, which is not part of the pre-push checks, passed
its storage.yml cases (10 PASS) and production check; its scenario still
reports the known default-authentication failure of an entry without
universe_domain, as in earlier releases. A Rails app with Puma was checked
in Chrome with Rails on the host and in Compose; see the
Active Storage scenario.
v0.6.0
gcs-mimic 0.6.0
0.6.0 is a reliability release. One faulty request, background job or panic no
longer stops the server or leaves it silently degraded, failed writes and
syncs no longer publish short objects, and readiness reports stopped
background work. It regenerates the built-in development TLS CA so Python
3.13+ clients pass their default strict checks, accepts the Node.js SDK's
default single-request resumable upload, and adds official Node.js, Python and
PHP SDK suites. It publishes ghcr.io/shiroemons/gcs-mimic:0.6.0 for
linux/amd64 and linux/arm64, mirrors the same digest to Docker Hub as
shiroemons/gcs-mimic:0.6.0, and publishes native archives for all eight
macOS, Windows and Linux targets. The 0.5.0 release notes describe
the previous published release; the feature matrix
lists the exact supported subsets.
The built-in development CA changed. HTTPS clients that trust a CA exported
from 0.5.0 or earlier must export it again; see
Compatibility and migration.
Changes
Uploads
- Resumable uploads accept the open-ended
Content-Range: bytes start-*/total
andbytes 0-*/*forms as a final request, as the Node.js SDK sends for its
default single-request upload. A known total, a declaredContent-Lengthor
the end of a chunked body fixes the object size; the body stays bounded by
the object size limit. Short, long, gapped and conflicting requests fail
without advancing the acknowledged prefix.
Local HTTPS
- The built-in development CA, leaf certificate and leaf key now carry Subject
and Authority Key Identifiers, so Python 3.13+ clients accept the server
with their defaultVERIFY_X509_STRICTchecks. Subject names, P-256 keys,
SANs and the ten-year validity are unchanged.
scripts/tls-development-cert.shregenerates the set reproducibly and checks
the chain with-x509_strict. See Local HTTPS.
Durability
- Uploads, resumable chunks and copy, rewrite and compose transfers flush each
blob before syncing it. A failed final write previously went unreported, so
an upload could publish metadata for the full size over a shorter blob. - Appendable objects write and sync through one file descriptor, so a sync
reports an earlier writeback failure. A failed sync rolls the writer back to
its persisted size, so the client must send those bytes again. - A cancelled append keeps its writer slot until its file operation ends, so
it cannot write through an old descriptor after a takeover. - Finalizing an appendable object removes its appendable record in the same
transaction that publishes the generation. A failed separate cleanup could
previously make a deleted object serve its old bytes again.
Fault isolation and readiness
- A panicking HTTP connection is logged and closed; the server keeps
accepting other connections. Previously it stopped the whole server. - A panic inside a catalog operation rolls back its transaction and fails only
that request. Previously every later request returned 503 until restart. - Publication workers and the blob shard creator keep working after a
panicking job. - Background tasks run supervised. Resumable maintenance restarts after a
panic with exponential backoff; readiness turns off after three consecutive
failed passes and recovers on the next successful one. /_internal/readyturns off when the sync mirror stops, instead of staying
200. Transient mirror failures, such as catalog contention or interrupted
I/O, are retried with backoff; invalid names, permission errors, corruption
and panics still stop the mirror.- Seeding fails when the directory walk stops before it finishes, instead of
marking a partial seed complete.
Error reporting
- Compose, copy, rewrite and resumable chunk transfers report a corrupt
catalog or a full disk with the same actionable 503 message as single-shot
uploads, instead of a genericbackendError. Status codes are unchanged. - A closed catalog is reported as closed instead of full.
- On Windows, a blob destination without a file name returns an error instead
of panicking.
Downloads
- Object downloads no longer lose their last chunk when the body producer
finishes. Rarely, and more often under load, a response previously ended
before itsContent-Length.
Performance
- The default
--max-blocking-threads(GCS_MIMIC_MAX_BLOCKING_THREADS) is
8 instead of 2, so one slow fsync no longer stalls every other transfer. The
accepted range is still 1–32. - The catalog runs its operations on a dedicated thread instead of the shared
blocking pool, so file I/O and gzip work no longer delay metadata requests. - Request paths and request-driven maintenance reuse cached prepared
statements. - HTTP and gRPC object bodies stream without zero-filling or copying each
frame. Chunk sizes, channel capacities and limits are unchanged.
SDK tests
just check-sdkalso runs pinned official Node.js, Python and PHP SDK
suites against isolated permissive and strict servers over HTTP and HTTPS,
beside the Go and Ruby suites. See sdk-tests.
Build and checks
just checkalso runs Clippy for the Linux glibc target, so size lints that
depend on Linux std types fail locally rather than only in CI.- The release workflow's freshness gate checks only inputs that build or ship
release artifacts: the Rust toolchain, direct Cargo dependencies, GitHub
Actions and the container build and runtime images. SDK suite dependencies
and test-only images are still checked daily but no longer block a release.
See the dependency policy. - Production code passes a lint gate,
cargo xtask lint, that rejects
unsupervised spawns, uncached SQL on request paths, stringified errors and
file syncs without a preceding flush. See Development.
Compatibility and migration
0.6.0 uses the same catalog schema, 35, as 0.5.0, so a data directory from
0.5.0 needs no migration. Upgrading from 0.4.1 or earlier also applies the
0.5.0 migration.
- The built-in development CA is new. A CA exported from gcs-mimic 0.5.0 or
earlier does not verify the 0.6.0 certificate. Rungcs-mimic tls caagain
and replace the copy that your clients, containers or test profiles trust.
Deployments that setGCS_MIMIC_TLS_DIRto a custom CA are unaffected. /_internal/ready, and therefore the container healthcheck, now reports not
ready when the sync mirror stops or resumable maintenance keeps failing.
0.5.0 reported ready in both cases.- The default blocking thread cap rose from 2 to 8. Set
--max-blocking-threads 2to keep the earlier bound. - Resumable requests with
Content-Range: bytes 0-*/*returned 400 in 0.5.0
and now finalize the upload.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls,
and the Docker Hub workflow mirrors that digest.
Before the release commit, the pre-push checks passed locally on macOS: format,
clippy, cross-compilation checks including the Linux glibc target, all 49 Rust
test binaries and doctests, the compatibility ledger check, the pinned Go,
Ruby, Node.js, Python and PHP SDK suites, and both Linux container smoke
tests. The Foundation checks passed in CI at 526e066, the last code change
before this release. The release-input freshness check
(cargo xtask dependencies check --scope release) reported every input
current.
The full freshness check reports one development-only drift, recorded as the
composer-riscv64-publication-lag exception: the official composer:latest
index still carries the 2.10.3 riscv64 image, so it differs from the pinned
Composer 2.11.0 index used by the PHP SDK suite and scorecard. The amd64 and
arm64 images are identical under both indexes, and no release artifact
contains Composer.
Known limitations
- The Node.js, Python and PHP suites cover the basic API milestone and local
transport, not full SDK compatibility; each suite's README records the
journeys it does not cover. - The 0.5.0 known limitations still apply.
v0.5.0
gcs-mimic 0.5.0
0.5.0 extends the SDK scorecard from Go and
Ruby to five official SDKs: gcs-mimic passes 57 of 57 Go probes and 51 of 51
probes each for Ruby, Node.js, PHP and Python. It adds ACL replacement through
bucket and object PATCH and PUT, bounded response replay for media, multipart
and copy invocation tokens, bounded gzip expansion on JSON media downloads and
JSON object metadata HEAD. It publishes ghcr.io/shiroemons/gcs-mimic:0.5.0
for linux/amd64 and linux/arm64, mirrors the same digest to Docker Hub as
shiroemons/gcs-mimic:0.5.0, and publishes native archives for all eight
macOS, Windows and Linux targets. The 0.4.1 release notes describe
the previous published release; the feature matrix
lists the exact supported subsets.
The first start migrates the data directory to a catalog schema that 0.4.1
cannot open. Read Compatibility and migration
before upgrading a persistent deployment.
Changes
Access control
- Bucket PATCH and PUT accept
aclanddefaultObjectAcl, and object PATCH
and PUT acceptacl. A supplied array replaces the stored entries, an empty
array clears them and omission keeps them. Replacement needs both the
metadata update permission and the resource'ssetIamPolicypermission.
The ACL and the other supplied metadata commit in one transaction with one
metageneration increment; invalid entries, missing permissions, failed
preconditions, uniform bucket-level access and public access prevention roll
back the whole update. See the ACL contract.
Objects
- Media and multipart uploads and JSON copy accept an
X-Goog-Gcs-Idempotency-Tokenwith or without generation conditions. A
matching retry returns the original response, even after a later overwrite,
deletion or restart, and concurrent identical requests publish one
generation. A conflicting request with the same token returns 400. Completed
invocations are kept for ten minutes, at most 4096 entries of up to 64 KiB
each; a full store rejects new tokens with 503. Current permissions are
checked on every retry. See the
upload replay contract. - JSON media downloads of objects stored with
Content-Encoding: gzipare
decompressed in bounded buffers unless the client accepts gzip or the object
hasCache-Control: no-transform. Decompressed responses ignoreRange,
keep the stored hashes and ETag, and abort on corrupt or oversized data. - JSON object metadata HEAD selects the same generation and applies the same
conditions and permissions as GET, without a response body. - Object move accepts an empty JSON object as its body, as the Node.js SDK
sends, and still rejects meaningful body fields. Compose accepts a null
source generation, and object retention accepts a null nested
retentionExpirationTime, as the Python SDK sends.
Uploads
- Resumable chunks may repeat whole-object MD5 and CRC32C declarations, as the
PHP SDK sends. The declarations persist with the acknowledged offset and are
verified against the complete object at finalization; conflicting or new
declarations, including on retries of a completed upload, return 400 without
changing the object. - After initiation, a repeated
X-Upload-Content-Type, as the Python SDK
sends, is validated and treated as advisory. Empty, malformed or duplicate
values return 400.
JSON API
- Boolean query parameters also accept Python's
TrueandFalsespellings.
Other spellings, such asTRUE,0or1, still return 400.
SDK scorecard
- Node.js, PHP and Python probes run alongside Go and Ruby over a shared,
verified HTTPS transport. The runner records clean-source state and derived
SDK metadata with each result, keeps early errors, and the PHP probe signs
URLs for the final endpoint.
Tests
- Test fixtures close catalog handles before removing their directories, and
Unix runs now fail tests that leave files open, so Windows cleanup failures
are caught on every platform.
Compatibility and migration
The first start migrates the catalog from PRAGMA user_version = 34 (0.4.0 and
0.4.1) to 35, adding the invocation replay table. The migration is one-way:
after it runs, 0.4.1 and earlier releases refuse to open the data directory.
Back up the data directory before upgrading if you may need to roll back.
Upgrading from 0.3.0 or earlier also applies the
0.4.0 migration.
- Media and multipart uploads with an invocation token but no
ifGenerationMatchreturned 501 in 0.4.1 and now succeed. A retry of a
committed conditioned upload with the same token now returns the original
object instead of 412. Tests that relied on either response need updating. - PATCH and PUT bodies that change
aclordefaultObjectAclreturned 400 in
0.4.1 and now replace the ACL. Strict-mode callers withoutsetIamPolicy
now receive 403 for those fields; a caller withgetIamPolicycan still echo
the unchanged ACL. - JSON media downloads of gzip-encoded objects without
Accept-Encoding: gzip
now return decompressed bytes. SendAccept-Encoding: gzipor set
Cache-Control: no-transformto keep the stored bytes. - Object metadata HEAD returned 405 in 0.4.1.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls,
and the Docker Hub workflow mirrors that digest.
Before the release commit, the pre-push checks passed locally on macOS: format,
clippy, cross-compilation checks, all Rust test binaries, the compatibility
ledger check, the pinned Go and Ruby SDK suites, including the Ruby strict
profile, and both Linux container smoke tests. The dependency freshness check
reported every input current. The
SDK scorecard at
e7fb384 recorded 100 for gcs-mimic, 44.9 for fake-gcs-server 1.56.1 and 41.5
for gcp-storage-emulator v2026.07.19; later changes touch only tests, the
scorecard runner and documentation.
Known limitations
- Invocation token replay covers media, multipart and JSON copy only; XML,
resumable initiation, PATCH, DELETE, rewrite and compose retries execute
again. The ten-minute retention and capacity limits are local choices, not
Google's cache policy. - Gzip expansion applies only to JSON media GET; XML downloads return the
stored bytes. JSON media HEAD and collection HEAD are unsupported. - The Node.js, PHP and Python results cover the scorecard's permissive,
default-location HTTPS profile. Node.js V4 signing omits a nondefault port
from the canonical host, so strict-mode signing at such an endpoint fails. - The 0.4.0 known limitations still apply.
v0.4.1
gcs-mimic 0.4.1
0.4.1 is the first published release with the
0.4.0 changes: JSON ACL resources, project HMAC keys and the
service agent, bucket notification configurations, Autoclass, storage class on
write, object retention, customer-supplied encryption keys, V4 signed POST
policy uploads and gRPC appendable objects. The v0.4.0 tag exists, but its
Windows release builds failed a test cleanup, so nothing was published for it.
0.4.1 adds one security fix on top. It publishes
ghcr.io/shiroemons/gcs-mimic:0.4.1 for linux/amd64 and linux/arm64,
mirrors the same digest to Docker Hub as shiroemons/gcs-mimic:0.4.1, and
publishes native archives for all eight macOS, Windows and Linux targets. The
0.3.0 release notes
describe the previous published release.
Upgrading from 0.3.0 migrates the data directory to a catalog schema that
0.3.0 cannot open. Read the
0.4.0 compatibility and migration notes
before upgrading a persistent deployment.
Changes since 0.4.0
Security
- PATCH and PUT accept an
aclordefaultObjectAclfield that repeats the
stored ACL only when the caller may read that ACL. In strict mode, a caller
with update permission but without the matchinggetIamPolicypermission
could previously tell whether a guessed ACL matched the stored one, because a
match was accepted and anything else was rejected. Such callers now get the
same 400 response whatever the stored ACL is. Permissive mode is unaffected.
Tests
- Four object retention wire tests now stop their server before the test
directory is removed. Windows cannot delete files the catalog still holds,
which made the 0.4.0 Windows release builds fail.
Compatibility and migration
0.4.1 uses the same catalog schema, 34, as the unpublished 0.4.0. From 0.3.0
or earlier, follow the
0.4.0 compatibility and migration notes:
the first start migrates the catalog from schema 27 one-way, so back up the data
directory if you may need to roll back.
Strict-mode clients that echoed an unchanged ACL in PATCH or PUT without
getIamPolicy permission now receive 400; drop the field or grant the
permission.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls,
and the Docker Hub workflow mirrors that digest.
Before the release commit, all Rust test binaries, format, clippy and the
compatibility ledger check passed locally on macOS, and the Foundation checks,
including the Windows portability tests, passed in CI at the commit that
carries both fixes. The 0.4.0 notes record the earlier SDK suite, container
smoke and SDK scorecard
results; the fixes since then change only ACL echo handling and test cleanup.
Known limitations
The 0.4.0 known limitations still apply.
v0.3.0
gcs-mimic 0.3.0
0.3.0 makes fixture loading work like fake-gcs-server: mount a
BUCKET/OBJECT tree at /data and it is applied on every startup, with no
other setting. It also implements gRPC CancelResumableWrite, lists legacy v1
buckets across projects when the project is omitted, and keeps directory
synchronization running past names the host cannot represent. It publishes
ghcr.io/shiroemons/gcs-mimic:0.3.0 for linux/amd64 and linux/arm64,
mirrors the same digest to Docker Hub as shiroemons/gcs-mimic:0.3.0, and
publishes native archives for all eight macOS, Windows and Linux targets. The
0.2.1 release notes
describe the previous release; the feature matrix lists
the exact supported subsets.
Seeding behavior changes in ways that can overwrite API changes on restart.
Read Compatibility and migration before
upgrading a deployment that sets a seed directory or mounts /data.
Changes
Seed files
- A configured seed directory is applied before readiness on every startup,
not only when a data directory is first initialized. Missing buckets and
objects are created. An object whose bytes or metadata differ from what
seeding writes, including API metadata edits, is replaced as a new
generation; only an exact match keeps its generation. Objects without a seed
file are kept, and removing a seed file never deletes an object. - A held or retained object that needs replacement is left unchanged, counted
asblockedand reported by aseed_blockedwarning. - Regular files directly under the seed root, such as
README.md, are skipped
with aseed_skippedwarning instead of stopping startup. - The new
default_seed_dirsetting (--default-seed-dir,
GCS_MIMIC_DEFAULT_SEED_DIR, JSONdefault_seed_dir) is used only when
seed_diris unset and the directory exists without overlappingdata_dir
orsync_dir. The image sets it to/data. seed_content_typenow defaults toextension, sologo.pngis stored as
image/png. The same setting governs files ingested fromsync_dir.- The ready event's
seedfield reportsbuckets,objects,replaced,
unchanged,blockedandskipped_os_metadata.
See the seed replay change and
loading local files for details.
gRPC
- Storage v2
CancelResumableWritediscards a resumable session through the
same catalog cancellation as the JSON sessionDELETE. Later status queries,
writes and repeated cancellation returnNOT_FOUND; a finalized upload
returnsFAILED_PRECONDITIONand keeps its object. Strict mode requires
storage.objects.create, as resumed writes do. - In strict mode, anonymous callers of Storage v2 object I/O and update/copy
RPCs now receiveUNAUTHENTICATED, like JSON, XML and the other RPCs. They
previously receivedPERMISSION_DENIED. - Legacy Storage v1
ListBucketswithout a project lists every project's
buckets in name order, as the reference emulator does, instead of returning
INVALID_ARGUMENT. Strict callers see only projects where they hold
storage.buckets.list.
Directory synchronization
- Object names with
:or\components are recorded as findings and
skipped on every OS instead of stopping the whole mirror, so later objects
keep exporting. Matching host files are counted as unrepresentable.
Distribution
- The release workflow mirrors the verified GHCR index to Docker Hub without
rebuilding, so both registries serve the same digest.
Compatibility and migration
The data-directory schema remains PRAGMA user_version = 27, shared with
0.2.0 and 0.2.1, so these releases open each other's data directories. No
catalog migration runs.
- Deployments that set
seed_dirand then change seeded objects through the
API see those changes replaced on the next restart. Removeseed_dirafter
the first start, or move fixtures that should stay editable out of the seed
tree. - Objects seeded as
application/octet-streamby earlier releases are
replaced once with the extension-derived type. Set
GCS_MIMIC_SEED_CONTENT_TYPE=octet-streamto keep the previous type, which
also restores it forsync_diringestion. - An image deployment that mounts something other than fixtures at
/data,
without using it asdata_dirorsync_dir, now seeds from it. Mount it
elsewhere, or setGCS_MIMIC_SEED_DIRto the intended fixture directory. - The ready event's
seed.existing_objectsfield and theskippedoutcome are
removed; readunchangedandreplacedinstead. - Strict gRPC clients that matched
PERMISSION_DENIEDfor anonymous Storage v2
object calls should expectUNAUTHENTICATED.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls,
and the Docker Hub workflow mirrors that digest.
Before the release commit, Foundation checks passed on Linux with the pinned
and current stable Rust, the macOS, Windows and Linux musl portability tests,
both native container smoke tests, including seed replay and the implicit
/data mount, and the pinned Go SDK suite. The pinned Ruby SDK suite passed
locally on macOS.
Known limitations
- Seeding has no file watcher and no reseed endpoint; restart to apply edits.
- Seed replay is applied file by file, not as one directory-wide transaction.
- The 0.1.0 known limitations and the feature matrix still apply
to unimplemented API areas.
v0.2.1
gcs-mimic 0.2.1
0.2.1 makes catalog schema upgrades visible: a data directory written by a
newer release is rejected with recovery instructions, and an upgrade migration
is logged. It publishes ghcr.io/shiroemons/gcs-mimic:0.2.1 for linux/amd64
and linux/arm64 and native archives for all eight macOS, Windows and Linux
targets. The 0.2.0 release notes
describe the gRPC listener, bucket and object policies and HTTP/1.1 behavior;
the feature matrix lists the exact supported subsets.
Changes
- Starting with a data directory whose catalog schema is newer than the
release supports now fails with adata_dirdiagnostic that names the
stored and supported schema versions and the ways to recover: run a release
that supports the schema, restore a backup taken before the upgrade, or use
a different data directory. It previously reported only
catalog unavailable or already in use. The catalog file is not modified. - Migrating a data directory from an older schema logs one
infoevent,
catalog_schema_migrated, withfromandtoversions beforeready.
New and already current data directories log none, and alog_levelof
warnorerrorhides it. - Release build jobs keep Windows test files on the workspace volume and build
their test binaries with line tables only.
Compatibility and migration
No migration is required. The data-directory schema remains
PRAGMA user_version = 27, shared with 0.2.0, so 0.2.0 and 0.2.1 open each
other's data directories. Only 0.2.1 and later explain a newer schema; 0.2.0
and 0.1.x still report catalog unavailable or already in use. Upgrading from
0.1.x migrates schema 21 to 27 as described in the 0.2.0 notes; back up the
data directory first.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls.
v0.2.0
gcs-mimic 0.2.0
0.2.0 adds an opt-in gRPC listener for Storage v2 and the legacy Storage v1
migration profile, bucket and object policies that the Go and Ruby SDKs use,
and HTTP/1.1 connection behavior closer to Cloud Storage: persistent
connections and documented, retryable timeout responses. It publishes
ghcr.io/shiroemons/gcs-mimic:0.2.0 for linux/amd64 and linux/arm64 and
native archives for all eight macOS, Windows and Linux targets. The
0.1.0 release notes
describe the base workflows; the feature matrix lists
the exact supported subsets.
Upgrading migrates the data directory to a schema that 0.1.x cannot open, and
several responses change. Read Compatibility and migration
before upgrading.
Changes
gRPC
--grpc-listen(GCS_MIMIC_GRPC_LISTEN, JSONgrpc_listen) starts an
optional plaintext h2c listener forgoogle.storage.v2.Storage. It serves
bucket CRUD, updates, IAM and retention locking; object metadata, media,
listing, deletion and restore; resumable writes; rewrite, compose and move;
and bidirectional ranged reads through the same catalog and authorization
as JSON. CancelResumableWrite, Rapid append, unsupported fields and other
RPCs return non-retryableUNIMPLEMENTEDwithErrorInfo. Point Go clients
at it withSTORAGE_EMULATOR_HOST_GRPC.- The same listener serves the twelve legacy Storage v1 RPCs of the reference
emulator as a migration profile, without a Google GA fidelity claim. - Idle gRPC connections close with GOAWAY, dead peers are detected with
HTTP/2 keepalive, and an open stream silent for 60 seconds is closed.
Buckets
- Uniform bucket-level access, including the 90-day lock and rejection of ACL
parameters while it is enabled. - Retention policies with locking, enforced on deletes and overwrites.
- Soft delete policies, with deleted and replaced generations kept until their
hard-delete time. - Lifecycle rules are validated, stored and returned; they are not executed.
- Regional and predefined dual-region location names in bucket creation,
default_locationand the bucket initializer. Physical placement is not
simulated. buckets.testIamPermissionsanswers with the authorization real operations
use.
Objects
- Temporary holds and monotonic
customTime. objects.restoreof soft-deleted generations andsoftDeletedlistings.- Atomic same-bucket
objects.movethat reuses the stored bytes. matchGlobfiltering for JSON object listings.
Authentication
- Path-style legacy V2 RSA signed URLs for GET and PUT. Strict mode verifies
them with registered keys; permissive mode ignores credentials as it does
for V4.
Directory synchronization
- The synchronized directory is scanned after readiness: external creates,
edits and rename targets are ingested with inherited metadata, and buckets
deleted through the API are not recreated from leftover directories.
External deletions are not yet ingested.
HTTP behavior
- HTTP/1.1 connections stay open between requests. An idle connection closes
after the newkeep_alive_timeout_ms(--keep-alive-timeout-ms,
GCS_MIMIC_KEEP_ALIVE_TIMEOUT_MS; default 120000, range 1–600000), or at
once when everymax_connectionsslot is taken. An error response to a
request that carried a body sendsConnection: close. - A deadline that expires before a response now returns
408uploadBrokenConnectionfor object uploads and 503backendErrorfor
other requests, instead of closing the connection without a response. - After an early rejection the server keeps reading the rest of the request
body for up to 30 seconds, so clients read the rejection instead of a reset. - Recognized but unsupported inputs return 400
badRequest(XML:
400InvalidArgument) instead of 501, so SDKs stop retrying them. - No-op defaults sent by the Ruby SDK, such as an empty
X-Upload-Content-Type, are accepted. - A media read failure after the response headers is logged as
object_body_read_failedwith its cause.
Distribution and tooling
SHA256SUMSuses LF line endings for every entry, so macOS
shasum --checkverifies the Windows archives too.- The daily dependency freshness check handles Go modules that publish only
pseudo-versions. Dependencies were refreshed, including tonic 0.14.8 and
the rebuiltrust:1.99.1-slim-trixiebase image.
Compatibility and migration
- Back up the data directory before upgrading. On first start, 0.2.0
migrates it from schema 21 (PRAGMA user_version = 21, used by 0.1.0
through 0.1.3) to schema 27. 0.1.x releases refuse to open the migrated
directory and report onlycatalog unavailable or already in use;
downgrading requires the backup. - Responses for recognized but unsupported inputs change from 501 to 400, and
known Google JSON routes that are not implemented, such as ACLs,
notifications and HMAC keys, change from 404 to the same 400. Missing
resources and unknown paths still return 404. - Bucket
PUT(buckets.update) now keeps omitted settings instead of
resetting them; explicitnulland empty values keep their field rules. - Clients that read a response until the server closes the connection must
sendConnection: closeor use the response's Content-Length. SDKs and
standard HTTP clients already do. - With
max_connectionsof 1, a connection closes after each response,
because an idle connection gives up the only slot. sync_diris rejected at startup under strict authentication. Directory
synchronization remains unavailable on Windows.
Verification
The release workflow
creates this Release only after validate, including the dependency freshness
check, Foundation and all eight native build/test jobs succeed at the tag's
SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls.
v0.1.3
gcs-mimic 0.1.3
0.1.3 adds native Windows archives for x86-64 (x86_64-pc-windows-msvc) and
ARM64 (aarch64-pc-windows-msvc), so every supported target now ships: macOS,
Windows and Linux GNU/musl, each for ARM64 and x86-64. It also publishes
ghcr.io/shiroemons/gcs-mimic:0.1.3 for linux/amd64 and linux/arm64.
The 0.1.0 release notes
describe the included workflows, compatibility and known limitations.
Changes
gcs-mimic import fake-gcs-servernow detects a source file replaced during
import on Windows even when its size, contents and modification time match.
Windows source fingerprints previously compared only size and modification
time; they now also compare the volume, file index and change time.- On Windows,
sync_diris rejected with a diagnostic that directory
synchronization is supported on Linux and macOS only. It previously claimed
the directory was not writable. - Native test suites pass on Windows runners. The remaining fixes are
test-only: process environments, file handle lifetimes during cleanup, path
separators, file name and time range limits, and platform-specific
connection errors. - Release preparation requires the manual dry run, including the publish job,
to pass on the exact commit before tagging.
Compatibility and migration
No migration is required. The data-directory schema remains
PRAGMA user_version = 21, shared by 0.1.0 through 0.1.3. Windows archives
are unsigned, use the static MSVC runtime and keep the Windows recovery limits
in the 0.1.0 notes: normal restart and process termination are covered, OS
crash and power loss are not. Directory synchronization is not available on
Windows.
Verification
The release workflow
creates this Release only after validate, Foundation and all eight native
build/test jobs succeed at the tag's SHA, including Windows runtime import
checks. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls.
v0.1.2
gcs-mimic 0.1.2
0.1.2 adds native macOS archives for Apple Silicon (aarch64-apple-darwin) and
Intel (x86_64-apple-darwin) next to the four Linux archives, and publishes
ghcr.io/shiroemons/gcs-mimic:0.1.2 for linux/amd64 and linux/arm64.
Application behavior is unchanged from 0.1.1; the
0.1.0 release notes
describe the included workflows, compatibility and known limitations.
Changes
- macOS archives return to the release matrix. Their native test suites now
pass on GitHub runners: the TLS test fixtures no longer produce a CA with a
duplicatebasicConstraintsextension under OpenSSL 1.1.1, and timing-based
upload deadline tests keep enough margin on slower runners. Test-only changes. - Windows archives are still not published. Several Windows catalog,
file-handle and synchronization tests fail on GitHub runners; use the
container image on Windows hosts. - Manual dispatch of the release workflow now runs the publish job as a dry
run up to the Release asset list.
Compatibility and migration
No migration is required. The data-directory schema remains
PRAGMA user_version = 21, shared by 0.1.0, 0.1.1 and 0.1.2. macOS archives are
unsigned and not notarized; macOS recovery limits in the 0.1.0 notes apply.
Verification
The release workflow
creates this Release only after validate, Foundation and all six native
macOS and Linux build/test jobs succeed at the tag's SHA. The
container workflow
then builds both Linux architectures natively, verifies their SBOM and
provenance, publishes the multi-architecture tag and checks anonymous pulls.
v0.1.1
gcs-mimic 0.1.1
0.1.1 is the first release with a container image:
ghcr.io/shiroemons/gcs-mimic:0.1.1 for linux/amd64 and linux/arm64.
It also ships the four Linux archives and SHA256SUMS. Application behavior is
unchanged from 0.1.0; its included workflows, compatibility notes, platform
verification and known limitations all apply. See the
0.1.0 release notes.
Changes
- Container publication accepts the SLSA v1 provenance that BuildKit 0.34
records. The v0.1.0 container step rejected valid images on this check, so
0.1.0 has no container image; use 0.1.1. - A resumable-upload test gives catalog admission enough time on loaded CI
runners. Test-only change.
Compatibility and migration
No migration from 0.1.0 is required. The data-directory schema remains
PRAGMA user_version = 21; 0.1.0 and 0.1.1 read and write the same data
directories. Follow the 0.1.0 notes for fake-gcs-server migration and backups.
Verification
The release workflow
creates this Release only after validate, Foundation and the four native Linux
build/test jobs succeed at the tag's SHA. The
container workflow
then builds both architectures natively, verifies their SBOM and provenance,
publishes the multi-architecture tag and checks anonymous pulls.