Migrate Azure Blob adapter from abandoned SDK to azure-oss/storage#402
Merged
sebastianfeldmann merged 3 commits intoJun 20, 2026
Merged
Conversation
Microsoft abandoned the microsoft/azure-storage-* libraries with no Composer replacement. Migrate the Azure Blob sync adapter, collector and file classes from MicrosoftAzure\Storage\Blob\BlobRestProxy to the maintained azure-oss/storage SDK (BlobServiceClient / BlobContainerClient / BlobClient). - Sync\AzureBlob: build a BlobContainerClient from the connection string; use exists()/create() instead of listContainers()/createContainer(); upload via getBlobClient()->upload(). - Collector\AzureBlob: list via BlobContainerClient::getBlobs() (the SDK paginates transparently, so the manual continuation-token loop is gone); the collector now receives the container client directly. - File\AzureBlob: read name/size/last-modified from the Blob model's readonly properties; delete via getBlobClient()->delete(). The azure-oss client classes are final and cannot be mocked, so the tests drive the real adapter logic through small seams (createClient, listBlobs, deleteBlob, ...) and build the offline BlobContainerClient and Blob models directly. Container existence, the create/skip-create branch, upload, exception wrapping, blob listing/filtering and deletion are covered. Also update the phar build (build.xml, build/phar-manifest.php) to bundle azure-oss/storage and its dependencies instead of microsoft/azure-storage-*. Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
- Narrow the upload seam (uploadBlob) so the real upload() body and getUploadPath() composition run under test; assert the computed blob path. - Assert the listBlobs() prefix and the deleted blob pathname so a wrong prefix / wrong-target regression is caught. - Replace brittle exact debug() call-count expectations with assertions on the actual log messages and resulting state. - Assert simulate() masks the credential-bearing connection string (connectionString: ********) and never logs the raw value. Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
sebastianfeldmann
approved these changes
Jun 20, 2026
Owner
|
Well done, looks solid! |
Replace the in-file Testable* subclass doubles with phpbu's standard PHPUnit mock pattern (createPartialMock / getMockBuilder->onlyMethods), matching the sibling AmazonS3v3 tests. The azure-oss client is final, so the mocks target the adapter's own protected seams rather than the SDK client; coverage of the orchestration is preserved. Assert the values passed to the SDK seams via with() matchers instead of capturing internal state: the upload path, the list prefix and the deleted blob path are now verified, and the File fixture uses a nested blob name so pathname and filename are distinguishable. Also align the adapters with the AmazonS3v3 sibling: $client is now protected (Sync and File), and File\AzureBlob::deleteBlob() takes the blob path as an argument. Signed-off-by: Sebastian Mendel <sebastian.mendel@netresearch.de>
This was referenced Jun 20, 2026
Merged
CybotTM
added a commit
to netresearch/phpbu-docker
that referenced
this pull request
Jun 20, 2026
#154) Removes the abandoned `microsoft/azure-storage-blob` SDK from the **full** image by adopting phpbu 6.0.32's migration to the maintained `azure-oss/storage`. ## Background `microsoft/azure-storage-blob` is abandoned upstream (Microsoft archived it; Packagist `abandoned: true`, no replacement). It was a direct require in the full image only because phpbu's Azure Blob sync adapter was hardwired to it. That's now fixed at the root: phpbu migrated the adapter to `azure-oss/storage` in [sebastianfeldmann/phpbu#402](sebastianfeldmann/phpbu#402), released in [phpbu 6.0.32](https://github.com/sebastianfeldmann/phpbu/releases/tag/6.0.32). ## What changed (`app/full/composer.json` + lock) - `phpbu/phpbu` `^6.0` → `^6.0.32` (the release whose Azure adapter uses azure-oss). - Direct require `microsoft/azure-storage-blob: ^1.4` → `azure-oss/storage: ^1.9` (phpbu lists azure-oss as `suggest`/`require-dev`, so the full image still declares it explicitly to enable the adapter). - `composer update` removed `microsoft/azure-storage-blob` + `microsoft/azure-storage-common` entirely; pulled `azure-oss/storage` 1.9.0, `azure-oss/storage-common`, `azure-oss/identity`. ## Verification - `composer validate` clean; **no abandoned packages remain in the lock**; `composer audit` reports no advisories. - phpbu 6.0.32's `azureblob` sync runs in `--simulate` under PHP 8.5: loads `AzureOss\Storage\Blob\BlobServiceClient` (no "SDK not loaded") and masks the credential (`connectionString: ********`). - The Security Scan (Trivy) runs on this PR and rebuilds the full image — it should now be clean of the abandonment finding. ## Supersedes This replaces the documentation-only workaround in #153 (which explained why the abandoned package was kept). With the package removed, that note is obsolete — closing #153 in favour of this fix.
Owner
|
Thanks! Great job! |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The Azure Blob sync adapter depends on
microsoft/azure-storage-blob, which Microsoft has officially abandoned (Packagistabandoned: true, no Composer replacement, capped at1.5.4; repo archived Nov 2023). The maintained community successor isazure-oss/storage(active —1.9.0, 2026-03; PHP^8.1, compatible with phpbu's>=8.1).What changed
Three classes consumed the old
MicrosoftAzure\Storage\Blob\BlobRestProxygod-object; they now use the azure-oss fluent client hierarchy (BlobServiceClient→BlobContainerClient→BlobClient):Backup\Sync\AzureBlob— builds aBlobContainerClientfrom the connection string; container check/create usesexists()/create()(replacinglistContainers()+createContainer()); upload viagetBlobClient()->upload($stream).Backup\Collector\AzureBlob— lists viaBlobContainerClient::getBlobs($prefix). The SDK paginates transparently, so the manualListBlobsOptions+ continuation-token loop is removed. The collector now receives the container client directly.Backup\File\AzureBlob— readsname/contentLength/lastModifiedfrom theBlobmodel's readonly properties; deletes viagetBlobClient()->delete().composer.jsonrequire-dev+suggestswapped toazure-oss/storage: ^1.9. End-user config (connection_string,container_name,path) is unchanged. The adapters follow theAmazonS3v3sibling conventions (protected$client, thin protected seams).Tests
Tests use phpbu's standard PHPUnit mock pattern (
createPartialMock/getMockBuilder->onlyMethods), matchingAmazonS3v3Test. Because the azure-oss client classes arefinal, the mocks target the adapter's own protected seams rather than the SDK client, and the values passed to those seams (upload path, list prefix, deleted blob path) are asserted viawith()matchers.simulate()is verified to mask the credential-bearing connection string. Full suite green locally (901 tests); PSR-2 (phpcs) and PHPStan level 3 clean on the changed files.Phar build — built & smoke-tested
build.xml/build/phar-manifest.phpupdated to bundleazure-oss/storage+ its deps (azure-oss/storage-common,azure-oss/identity,caseyamcl/guzzle_retry_middleware,symfony/deprecation-contracts,symfony/polyfill-php80). I built the phar withant pharand ran anazureblobsync through it in--simulate: it loadedAzureOss\Storage\Blob\BlobServiceClientand emittedconnectionString: ********. Note:azure-oss/storage+storage-commonship noLICENSEfile, so I omitted theirLICENSEcopy tasks — the redistributed phar should still carry the MIT notice (worth adding a LICENSE / upstream issue).Independent review
I ran multi-perspective reviews (correctness, reliability, security, conformity, test coverage) and applied the conformity + coverage findings (the test pattern above, sibling-aligned visibility, SDK-argument assertions). A few suggestions I intentionally did not apply, to stay consistent with the
AmazonS3v3sibling and keep this a faithful migration — flagging them for your call:createClient()/ container existence-check in a try/catch so SDK exceptions surface asSync\Exception. Declined:AmazonS3v3::sync()is structured identically (client creation + bucket check outside the try); matching the sibling. Failures still propagate loudly.createIfNotExists()for the container (removes a check-then-create race). The old code andAmazonS3v3both use check-then-create; kept the faithful port. azure-oss offers the safer primitive if you'd prefer it.AmazonS3v3has the same property — so this is an adapter-wide logging-policy decision rather than something to fix only here.php-http/discoveryinallow-plugins(it's an install-time composer-plugin pulled transitively viaazure-oss/identity; not reached at runtime on the shared-key path). Flagged as a project-wide install-policy choice.