Skip to content
Open
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
208 changes: 208 additions & 0 deletions .github/workflows/elixir-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
name: "Elixir SDK"

# Builds the Rustler NIF for the Elixir SDK on each supported target, publishes
# the NIF archives to the GitHub Release, and publishes the Hex package with the
# generated Rustler checksum file.

on:
workflow_call:
inputs:
pre_release:
description: Run as part of the canonical pre-release suite
required: false
type: boolean
default: false
release_tag:
description: Existing GitHub Release tag to upload artifacts to
required: false
type: string
default: ""
workflow_dispatch:
inputs:
release_tag:
description: Existing GitHub Release tag to upload artifacts to
required: false
type: string
default: ""
push:
tags:
- v**
pull_request:
paths:
- "secretspec-ex/**"
- ".github/workflows/elixir-package.yml"
- "scripts/install-rustup.sh"
- "scripts/sync-sdk-versions.sh"

permissions:
contents: read

jobs:
test:
name: Elixir tests
if: >-
inputs.pre_release ||
github.event_name != 'pull_request' ||
!startsWith(github.event.pull_request.title, 'Release ')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: erlef/setup-beam@v1
with:
otp-version: "28"
elixir-version: "1.19"
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Fetch dependencies
working-directory: secretspec-ex
run: mix deps.get
- name: Run tests
working-directory: secretspec-ex
run: mix test

nif:
name: NIF ${{ matrix.target }}
if: >-
inputs.pre_release ||
github.event_name != 'pull_request' ||
!startsWith(github.event.pull_request.title, 'Release ')
needs: [test]
runs-on: ${{ matrix.runner }}
container: ${{ matrix.container || null }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
container: quay.io/pypa/manylinux_2_28_x86_64:2026.08.05-1@sha256:e0b40ace8e818e96026eb47714b01998cbca022a6995797d0905474ce3e82ae8
- target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm
container: quay.io/pypa/manylinux_2_28_aarch64:2026.08.05-1@sha256:f766b402889e40f439e7a3ee5788eef1aa3ef399d0110107d27419fa2ba9d905
- { target: aarch64-apple-darwin, runner: macos-latest }
- { target: x86_64-pc-windows-msvc, runner: windows-latest }
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
submodules: recursive
- name: Install verified rustup (the manylinux container ships none)
if: matrix.container
shell: bash
run: |
bash scripts/install-rustup.sh
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install Rust (pinned by rust-toolchain.toml)
run: rustup toolchain install
- name: Sync SDK package versions
run: bash scripts/sync-sdk-versions.sh
- name: Build Rustler NIF
id: build
uses: philss/rustler-precompiled-action@v1.1.5
env:
CARGO_TARGET_DIR: target
with:
project-name: secretspec_native
project-version: ${{ env.PROJECT_VERSION }}
target: ${{ matrix.target }}
nif-version: "2.15"
project-dir: secretspec-ex/native/secretspec_native
- name: Verify Linux portability (glibc <= 2.28, no libdbus)
if: matrix.container
shell: bash
run: >-
bash scripts/check-linux-portability.sh
secretspec-ex/native/secretspec_native/target/${{ matrix.target }}/release/libsecretspec_native.so
- name: Verify generated archive
shell: bash
run: test -s "${{ steps.build.outputs.file-path }}"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: elixir-nif-${{ matrix.target }}
path: ${{ steps.build.outputs.file-path }}

publish-nifs:
name: Publish Elixir NIFs
needs: [nif]
if: >-
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
inputs.release_tag != ''
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: elixir-nif-*
path: artifacts
merge-multiple: true
- name: Attach NIF archives to the GitHub Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ inputs.release_tag || github.ref_name }}
run: |
set -euo pipefail
mapfile -t assets < <(find artifacts -type f -name '*secretspec_native-*.tar.gz' -print | sort)
if [[ "${#assets[@]}" -ne 4 ]]; then
printf 'expected 4 Elixir NIF archives, found %s\n' "${#assets[@]}" >&2
printf '%s\n' "${assets[@]}" >&2
exit 1
fi
bash scripts/upload-release-asset.sh "$RELEASE_TAG" "${assets[@]}"

package:
name: Build and publish Elixir package
needs: [test, publish-nifs]
if: >-
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) ||
inputs.release_tag != ''
runs-on: ubuntu-latest
permissions:
contents: read
environment:
name: hex
url: https://hex.pm/packages/secretspec
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: erlef/setup-beam@v1
with:
otp-version: "28"
elixir-version: "1.19"
- name: Install Hex and Rebar
run: |
mix local.hex --force
mix local.rebar --force
- name: Sync SDK package versions
run: bash scripts/sync-sdk-versions.sh
- name: Fetch dependencies
working-directory: secretspec-ex
run: mix deps.get
- name: Generate Rustler checksums from release assets
working-directory: secretspec-ex
run: mix rustler_precompiled.download SecretSpec.Native --all --print
- name: Verify Rustler checksum file
working-directory: secretspec-ex
run: test -s checksum-Elixir.SecretSpec.Native.exs
- name: Build Hex package
working-directory: secretspec-ex
run: mix hex.build
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: elixir-package
path: secretspec-ex/secretspec-*.tar
- name: Publish package to Hex.pm
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
working-directory: secretspec-ex
env:
HEX_API_KEY: ${{ secrets.HEX_API_KEY }}
run: mix hex.publish --yes
12 changes: 12 additions & 0 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ on:
- "secretspec-dotnet/src/SecretSpec/SecretSpec.csproj"
- "secretspec-jvm/gradle.properties"
- "Package.swift"
- "secretspec-ex/**"
- ".github/workflows/elixir-package.yml"

permissions:
contents: read
Expand Down Expand Up @@ -83,6 +85,16 @@ jobs:
pre_release: true
publish: false

elixir:
name: Elixir SDK
needs: authorize
permissions:
contents: read
uses: ./.github/workflows/elixir-package.yml
Comment thread
sylvesterroos marked this conversation as resolved.
with:
pre_release: true
release_tag: ""

python:
name: Python wheels
needs: authorize
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sdks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: "SDKs"

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

on:
workflow_call:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
configurable RSA available for compatibility. OpenSSH generation likewise
defaults to Ed25519 and supports configurable RSA keys and comments.

- **Elixir SDK (0.21+)** (`secretspec-ex`) resolves SecretSpec declarations from
Comment thread
sylvesterroos marked this conversation as resolved.
Elixir through a Rustler binding, with precompiled NIF archives for supported
Linux, macOS, and Windows targets.

## [0.20.0] - 2026-08-31

### Changed
Expand Down
48 changes: 46 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ members = [
"secretspec-node",
"secretspec-php",
"secretspec-py",
"secretspec-ex/native/secretspec_native",
]
resolver = "2"

Expand Down
8 changes: 5 additions & 3 deletions conformance/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Cross-language conformance suite

Every SecretSpec SDK (Python, Go, Ruby, Node.js, Haskell, C#, PHP, and Swift
(0.18+)) is a thin client over the same resolver contract. This suite proves
Every SecretSpec SDK (Python, Go, Ruby, Node.js, Haskell, C#, PHP, Swift
(0.18+), JVM (0.20+), and Elixir (0.21+)) is a thin client over the same
resolver contract. This suite proves
they agree: each SDK resolves the same fixtures and must produce the identical
**canonical** result.

Expand Down Expand Up @@ -65,4 +66,5 @@ relative to the repo root:
`swift test --filter SecretSpecTests.testCrossLanguageConformance` after
staging the local XCFramework as described in `secretspec-swift/README.md`
- JVM (0.20+):
`cd secretspec-jvm && ./gradlew test`
`cd secretspec-jvm && ./gradlew test`
- Elixir (0.21+): `cd secretspec-ex && mix test test/conformance_test.exs`
8 changes: 8 additions & 0 deletions conformance/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ run_jvm() { (
cd secretspec-jvm
./gradlew test
); }
run_elixir() { (
cd secretspec-ex
mix local.hex --force
mix local.rebar --force
mix deps.get
mix test test/conformance_test.exs
); }

run "Python" python run_python
run "Go" go run_go
Expand All @@ -117,6 +124,7 @@ else
fi
# The gradle wrapper will download gradle, use "bash" as a placeholder
run "JVM" bash run_jvm
run "Elixir" mix run_elixir

echo
echo "==> Conformance summary"
Expand Down
4 changes: 4 additions & 0 deletions devenv.nix
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
enable = true;
jdk.package = pkgs.jdk21;
};
languages.elixir = {
enable = true;
package = pkgs.beam28Packages.elixir_1_19;
};

packages = [
# documentation link validation
Expand Down
Loading