feat: publish config schema on release (#9572)
Follow up to #8956; publish schema on new release to stable URL. Also canonicalize schema (sort keys) when writing. This avoids reliance on default `schema_rs` behavior and makes the schema easier to read.
This commit is contained in:
parent
f1240ff4fe
commit
c285b88980
3 changed files with 746 additions and 714 deletions
27
.github/workflows/rust-release.yml
vendored
27
.github/workflows/rust-release.yml
vendored
|
|
@ -20,6 +20,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: dtolnay/rust-toolchain@1.92
|
||||
|
||||
- name: Validate tag matches Cargo.toml version
|
||||
shell: bash
|
||||
|
|
@ -45,6 +46,15 @@ jobs:
|
|||
echo "✅ Tag and Cargo.toml agree (${tag_ver})"
|
||||
echo "::endgroup::"
|
||||
|
||||
- name: Verify config schema fixture
|
||||
shell: bash
|
||||
working-directory: codex-rs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "If this fails, run: just write-config-schema to overwrite fixture with intentional changes."
|
||||
cargo run -p codex-core --bin codex-write-config-schema
|
||||
git diff --exit-code core/config.schema.json
|
||||
|
||||
build:
|
||||
needs: tag-check
|
||||
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
|
||||
|
|
@ -358,6 +368,10 @@ jobs:
|
|||
|
||||
ls -R dist/
|
||||
|
||||
- name: Add config schema release asset
|
||||
run: |
|
||||
cp codex-rs/core/config.schema.json dist/config-schema.json
|
||||
|
||||
- name: Define release name
|
||||
id: release_name
|
||||
run: |
|
||||
|
|
@ -428,6 +442,19 @@ jobs:
|
|||
tag: ${{ github.ref_name }}
|
||||
config: .github/dotslash-config.json
|
||||
|
||||
- name: Trigger developers.openai.com deploy
|
||||
# Only trigger the deploy if the release is not a pre-release.
|
||||
# The deploy is used to update the developers.openai.com website with the new config schema json file.
|
||||
if: ${{ !contains(steps.release_name.outputs.name, '-') }}
|
||||
continue-on-error: true
|
||||
env:
|
||||
DEV_WEBSITE_VERCEL_DEPLOY_HOOK_URL: ${{ secrets.DEV_WEBSITE_VERCEL_DEPLOY_HOOK_URL }}
|
||||
run: |
|
||||
if ! curl -sS -f -o /dev/null -X POST "$DEV_WEBSITE_VERCEL_DEPLOY_HOOK_URL"; then
|
||||
echo "::warning title=developers.openai.com deploy hook failed::Vercel deploy hook POST failed for ${GITHUB_REF_NAME}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Publish to npm using OIDC authentication.
|
||||
# July 31, 2025: https://github.blog/changelog/2025-07-31-npm-trusted-publishing-with-oidc-is-generally-available/
|
||||
# npm docs: https://docs.npmjs.com/trusted-publishers
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,8 @@ use schemars::schema::ObjectValidation;
|
|||
use schemars::schema::RootSchema;
|
||||
use schemars::schema::Schema;
|
||||
use schemars::schema::SchemaObject;
|
||||
use serde_json::Map;
|
||||
use serde_json::Value;
|
||||
use std::path::Path;
|
||||
|
||||
/// Schema for the `[features]` map with known + legacy keys only.
|
||||
|
|
@ -60,10 +62,29 @@ pub fn config_schema() -> RootSchema {
|
|||
.into_root_schema_for::<ConfigToml>()
|
||||
}
|
||||
|
||||
/// Canonicalize a JSON value by sorting its keys.
|
||||
fn canonicalize(value: &Value) -> Value {
|
||||
match value {
|
||||
Value::Array(items) => Value::Array(items.iter().map(canonicalize).collect()),
|
||||
Value::Object(map) => {
|
||||
let mut entries: Vec<_> = map.iter().collect();
|
||||
entries.sort_by(|(left, _), (right, _)| left.cmp(right));
|
||||
let mut sorted = Map::with_capacity(map.len());
|
||||
for (key, child) in entries {
|
||||
sorted.insert(key.clone(), canonicalize(child));
|
||||
}
|
||||
Value::Object(sorted)
|
||||
}
|
||||
_ => value.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the config schema as pretty-printed JSON.
|
||||
pub fn config_schema_json() -> anyhow::Result<Vec<u8>> {
|
||||
let schema = config_schema();
|
||||
let json = serde_json::to_vec_pretty(&schema)?;
|
||||
let value = serde_json::to_value(schema)?;
|
||||
let value = canonicalize(&value);
|
||||
let json = serde_json::to_vec_pretty(&value)?;
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
|
|
@ -76,26 +97,10 @@ pub fn write_config_schema(out_path: &Path) -> anyhow::Result<()> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::canonicalize;
|
||||
use super::config_schema_json;
|
||||
use serde_json::Map;
|
||||
use serde_json::Value;
|
||||
use similar::TextDiff;
|
||||
|
||||
fn canonicalize(value: &Value) -> Value {
|
||||
match value {
|
||||
Value::Array(items) => Value::Array(items.iter().map(canonicalize).collect()),
|
||||
Value::Object(map) => {
|
||||
let mut entries: Vec<_> = map.iter().collect();
|
||||
entries.sort_by(|(left, _), (right, _)| left.cmp(right));
|
||||
let mut sorted = Map::with_capacity(map.len());
|
||||
for (key, child) in entries {
|
||||
sorted.insert(key.clone(), canonicalize(child));
|
||||
}
|
||||
Value::Object(sorted)
|
||||
}
|
||||
_ => value.clone(),
|
||||
}
|
||||
}
|
||||
use similar::TextDiff;
|
||||
|
||||
#[test]
|
||||
fn config_schema_matches_fixture() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue