Skip to content

Commit 0eecc45

Browse files
authored
Merge remote-tracking branch 'origin/main' into feat/awssm-tags-kms
# Conflicts: # CHANGELOG.md
2 parents 743dc64 + 5625f10 commit 0eecc45

39 files changed

Lines changed: 2528 additions & 76 deletions

.github/workflows/ffi-build.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ jobs:
2727
build:
2828
name: ${{ matrix.target }}
2929
runs-on: ${{ matrix.runner }}
30+
# Needed by the tag-only "Publish cdylib to the release" step below, which
31+
# attaches the library to the GitHub Release cargo-dist creates for the tag.
32+
permissions:
33+
contents: write
3034
strategy:
3135
fail-fast: false
3236
matrix:
@@ -75,3 +79,28 @@ jobs:
7579
path: |
7680
target/${{ matrix.target }}/release/${{ matrix.artifact }}
7781
secretspec-ffi/include/secretspec.h
82+
83+
# On a version tag, attach the cdylib (named for its target, with a sha256
84+
# sidecar) to the GitHub Release so the PHP SDK's `secretspec-install-lib`
85+
# command can fetch the right one for a plain `composer require` install.
86+
# cargo-dist's release.yml creates the release for this same tag, so wait
87+
# for it to exist, then upload with --clobber (both workflows may retry).
88+
- name: Publish cdylib to the release
89+
if: startsWith(github.ref, 'refs/tags/v')
90+
shell: bash
91+
env:
92+
GH_TOKEN: ${{ github.token }}
93+
run: |
94+
set -euo pipefail
95+
tag="${GITHUB_REF_NAME}"
96+
ext="${{ matrix.artifact }}"; ext="${ext##*.}"
97+
asset="secretspec-ffi-${{ matrix.target }}.${ext}"
98+
cp "target/${{ matrix.target }}/release/${{ matrix.artifact }}" "$asset"
99+
# sha256 sidecar (BSD shasum on macOS, GNU sha256sum on Linux; both here).
100+
if command -v sha256sum >/dev/null; then sha256sum "$asset" > "$asset.sha256"
101+
else shasum -a 256 "$asset" > "$asset.sha256"; fi
102+
# Wait for cargo-dist to create the release (concurrent workflow).
103+
for _ in $(seq 1 30); do
104+
gh release view "$tag" >/dev/null 2>&1 && break || sleep 20
105+
done
106+
gh release upload "$tag" "$asset" "$asset.sha256" --clobber

.github/workflows/php-ext.yml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: "PHP extension"
2+
3+
# Builds the secretspec-php-native PHP extension (ext-php-rs) as a prebuilt
4+
# shared object for each supported PHP minor x platform, smoke tests that it
5+
# loads and registers its functions, and on a version tag attaches the binaries
6+
# to the GitHub Release.
7+
#
8+
# DISTRIBUTION STATUS (see RELEASE.md): this builds and publishes prebuilt
9+
# extension binaries. Installing them is documented in the PHP SDK docs
10+
# (download + `extension=`, or `docker-php-ext-enable`, or build from source with
11+
# cargo). A one-command PIE install is a follow-up: PIE builds non-Windows
12+
# extensions from source via phpize, which does not apply to a Cargo/ext-php-rs
13+
# extension, so the prebuilt-binary path here is what is validated.
14+
#
15+
# The SDK itself is exercised on every PR by the devenv-based sdks.yml (both the
16+
# extension and the ext-ffi fallback); this workflow only builds the
17+
# distributable extension binaries.
18+
19+
on:
20+
workflow_dispatch:
21+
push:
22+
tags:
23+
- v**
24+
pull_request:
25+
paths:
26+
- "secretspec-php/**"
27+
- ".github/workflows/php-ext.yml"
28+
29+
jobs:
30+
build:
31+
name: php-${{ matrix.php }}-${{ matrix.target }}
32+
runs-on: ${{ matrix.runner }}
33+
permissions:
34+
contents: write # attach binaries to the release (tag runs only)
35+
strategy:
36+
fail-fast: false
37+
matrix:
38+
# Full php x target cross-product: the `include` entries share the
39+
# `target` key with the axis, so they merge in the runner (rather than
40+
# creating standalone combinations). Non-thread-safe (NTS) is the default
41+
# CLI/FPM build. 8.1 is omitted (end of life). Windows and ZTS builds are
42+
# a follow-up (ext-php-rs on Windows needs the PHP SDK dev pack + rust-lld;
43+
# Windows users can use the ext-ffi backend meanwhile).
44+
php: ["8.2", "8.3", "8.4"]
45+
target:
46+
- x86_64-unknown-linux-gnu
47+
- aarch64-unknown-linux-gnu
48+
- aarch64-apple-darwin
49+
include:
50+
- { target: x86_64-unknown-linux-gnu, runner: ubuntu-latest }
51+
- { target: aarch64-unknown-linux-gnu, runner: ubuntu-24.04-arm }
52+
- { target: aarch64-apple-darwin, runner: macos-latest }
53+
54+
steps:
55+
- uses: actions/checkout@v5
56+
57+
- name: Set up PHP ${{ matrix.php }}
58+
uses: shivammathur/setup-php@v2
59+
with:
60+
php-version: ${{ matrix.php }}
61+
# php-config + headers, needed by ext-php-rs's build.
62+
tools: none
63+
env:
64+
# Ensure the dev headers are available for the build.
65+
phpts: nts
66+
67+
- name: Install Linux build dependencies (clang for bindgen, dbus for keyring)
68+
if: runner.os == 'Linux'
69+
run: sudo apt-get update && sudo apt-get install -y llvm-dev libclang-dev clang libdbus-1-dev pkg-config
70+
71+
- name: Install Rust (pinned by rust-toolchain.toml)
72+
run: rustup toolchain install
73+
74+
- name: Build the extension
75+
# Each runner is the target's native arch, so a plain release build emits
76+
# the target's binary (no cross-compilation).
77+
run: cargo build --release -p secretspec-php-native
78+
79+
- name: Stage the extension under its distribution name
80+
id: stage
81+
shell: bash
82+
run: |
83+
set -euo pipefail
84+
case "$(uname -s)" in
85+
Darwin) built="libsecretspec_php_native.dylib" ;;
86+
*) built="libsecretspec_php_native.so" ;;
87+
esac
88+
# dlopen resolves by path, not suffix, so the macOS .dylib ships as .so.
89+
asset="secretspec-php-native-${{ matrix.php }}-nts-${{ matrix.target }}.so"
90+
cp "target/release/$built" "$asset"
91+
echo "asset=$asset" >> "$GITHUB_OUTPUT"
92+
93+
- name: Smoke test (load the extension, check it registers)
94+
# Every row builds natively, so the runner can load what it built.
95+
shell: bash
96+
run: |
97+
php -d extension="$PWD/${{ steps.stage.outputs.asset }}" -r '
98+
assert(function_exists("secretspec_native_resolve"));
99+
assert(function_exists("secretspec_native_abi_version"));
100+
echo secretspec_native_abi_version(), PHP_EOL;
101+
'
102+
103+
- uses: actions/upload-artifact@v4
104+
with:
105+
name: php-ext-${{ matrix.php }}-${{ matrix.target }}
106+
path: ${{ steps.stage.outputs.asset }}
107+
108+
- name: Publish extension to the release
109+
if: startsWith(github.ref, 'refs/tags/v')
110+
shell: bash
111+
env:
112+
GH_TOKEN: ${{ github.token }}
113+
run: |
114+
set -euo pipefail
115+
asset="${{ steps.stage.outputs.asset }}"
116+
if command -v sha256sum >/dev/null; then sha256sum "$asset" > "$asset.sha256"
117+
else shasum -a 256 "$asset" > "$asset.sha256"; fi
118+
# cargo-dist's release.yml creates the release for this tag; wait for it.
119+
for _ in $(seq 1 30); do
120+
gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1 && break || sleep 20
121+
done
122+
gh release upload "${GITHUB_REF_NAME}" "$asset" "$asset.sha256" --clobber

.github/workflows/sdks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: "SDKs"
22

33
# Runs every language SDK's full test suite (unit + cross-language conformance +
44
# the schema/quicktype codegen pipeline) against a freshly built cdylib, so the
5-
# Python/Go/Ruby/Node/Haskell bindings cannot silently rot.
5+
# Python/Go/Ruby/Node/Haskell/PHP bindings cannot silently rot.
66

77
on:
88
pull_request:

.github/workflows/test.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,8 @@ jobs:
3535
- name: Install Rust
3636
run: rustup toolchain install stable --profile minimal
3737
- name: cargo test
38-
run: cargo test --all
38+
# Exclude secretspec-php-native: it is an ext-php-rs extension that needs a
39+
# PHP dev toolchain (php-config/headers) this bare runner does not have, and
40+
# ext-php-rs rejects the runner's PHP version anyway. The PHP SDK is built
41+
# and tested by sdks.yml / php-ext.yml instead.
42+
run: cargo test --workspace --exclude secretspec-php-native

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
target
55

66
.DS_Store
7+
8+
# PHP (Composer) — manifest at repo root, vendor-dir points into secretspec-php/
9+
/composer.lock

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
a customer-managed KMS key or "tag-on-create" guardrails (an SCP requiring
1515
`aws:RequestTag/*` on `CreateSecret`) can now store secrets. A pre-existing
1616
secret keeps the key and tags it was created with.
17+
- PHP SDK (`cachix/secretspec`): resolve secrets from PHP, Laravel, and Symfony
18+
over the same shared resolver as the other language SDKs. It ships as a native
19+
PHP extension that embeds the resolver (works under PHP-FPM with no
20+
`ffi.enable`, like `ext-redis`), with an `ext-ffi` fallback that dlopens the
21+
library at runtime for CLI and local development.
1722

1823
### Changed
1924
- A `ref` routed at a single store (an explicit `--provider`, a single-provider
@@ -47,6 +52,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4752
the same "use `onepassword` instead" correction that `--provider 1password`
4853
gives, instead of a generic undefined-alias error.
4954
- `import` prints its per-secret summary in a stable, name-sorted order.
55+
- `run` no longer aborts when the environment contains a non-UTF-8 variable.
56+
Such variables are now passed through to the child process untouched, with
57+
resolved secrets overlaid on top.
5058

5159
## [0.14.0] - 2026-07-09
5260

0 commit comments

Comments
 (0)