Publish runnable DotSlash package for argument-comment lint

This commit is contained in:
Michael Bolin
2026-03-19 10:57:34 -07:00
parent e5de13644d
commit 5afbcf6136
5 changed files with 311 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
{
"outputs": {
"argument-comment-lint": {
"platforms": {
"macos-aarch64": {
"regex": "^argument-comment-lint-aarch64-apple-darwin\\.tar\\.gz$",
"path": "argument-comment-lint/bin/argument-comment-lint"
},
"linux-x86_64": {
"regex": "^argument-comment-lint-x86_64-unknown-linux-gnu\\.tar\\.gz$",
"path": "argument-comment-lint/bin/argument-comment-lint"
},
"linux-aarch64": {
"regex": "^argument-comment-lint-aarch64-unknown-linux-gnu\\.tar\\.gz$",
"path": "argument-comment-lint/bin/argument-comment-lint"
},
"windows-x86_64": {
"regex": "^argument-comment-lint-x86_64-pc-windows-msvc\\.zip$",
"path": "argument-comment-lint/bin/argument-comment-lint.exe"
}
}
}
}
}

View File

@@ -0,0 +1,103 @@
name: rust-release-argument-comment-lint
on:
workflow_call:
inputs:
publish:
required: true
type: boolean
jobs:
skip:
if: ${{ !inputs.publish }}
runs-on: ubuntu-latest
steps:
- run: echo "Skipping argument-comment-lint release assets for prerelease tag"
build:
if: ${{ inputs.publish }}
name: Build - ${{ matrix.runner }} - ${{ matrix.target }}
runs-on: ${{ matrix.runs_on || matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- runner: macos-15-xlarge
target: aarch64-apple-darwin
archive_name: argument-comment-lint-aarch64-apple-darwin.tar.gz
lib_name: libargument_comment_lint@nightly-2025-09-18-aarch64-apple-darwin.dylib
runner_binary: argument-comment-lint
cargo_dylint_binary: cargo-dylint
- runner: ubuntu-24.04
target: x86_64-unknown-linux-gnu
archive_name: argument-comment-lint-x86_64-unknown-linux-gnu.tar.gz
lib_name: libargument_comment_lint@nightly-2025-09-18-x86_64-unknown-linux-gnu.so
runner_binary: argument-comment-lint
cargo_dylint_binary: cargo-dylint
- runner: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
archive_name: argument-comment-lint-aarch64-unknown-linux-gnu.tar.gz
lib_name: libargument_comment_lint@nightly-2025-09-18-aarch64-unknown-linux-gnu.so
runner_binary: argument-comment-lint
cargo_dylint_binary: cargo-dylint
- runner: windows-x64
target: x86_64-pc-windows-msvc
archive_name: argument-comment-lint-x86_64-pc-windows-msvc.zip
lib_name: argument_comment_lint@nightly-2025-09-18-x86_64-pc-windows-msvc.dll
runner_binary: argument-comment-lint.exe
cargo_dylint_binary: cargo-dylint.exe
runs_on:
group: codex-runners
labels: codex-windows-x64
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@1.93.0
with:
toolchain: nightly-2025-09-18
targets: ${{ matrix.target }}
components: llvm-tools-preview, rustc-dev, rust-src
- name: Install tooling
shell: bash
run: |
install_root="${RUNNER_TEMP}/argument-comment-lint-tools"
cargo install --locked cargo-dylint --root "$install_root"
cargo install --locked dylint-link
echo "INSTALL_ROOT=$install_root" >> "$GITHUB_ENV"
- name: Cargo build
working-directory: tools/argument-comment-lint
shell: bash
run: cargo build --release --target ${{ matrix.target }}
- name: Stage artifact
shell: bash
run: |
dest="dist/argument-comment-lint/${{ matrix.target }}"
mkdir -p "$dest"
package_root="${RUNNER_TEMP}/argument-comment-lint"
rm -rf "$package_root"
mkdir -p "$package_root/bin" "$package_root/lib"
cp "tools/argument-comment-lint/target/${{ matrix.target }}/release/${{ matrix.runner_binary }}" \
"$package_root/bin/${{ matrix.runner_binary }}"
cp "${INSTALL_ROOT}/bin/${{ matrix.cargo_dylint_binary }}" \
"$package_root/bin/${{ matrix.cargo_dylint_binary }}"
cp "tools/argument-comment-lint/target/${{ matrix.target }}/release/${{ matrix.lib_name }}" \
"$package_root/lib/${{ matrix.lib_name }}"
archive_path="$dest/${{ matrix.archive_name }}"
if [[ "${{ runner.os }}" == "Windows" ]]; then
(cd "${RUNNER_TEMP}" && 7z a "$GITHUB_WORKSPACE/$archive_path" argument-comment-lint >/dev/null)
else
(cd "${RUNNER_TEMP}" && tar -czf "$GITHUB_WORKSPACE/$archive_path" argument-comment-lint)
fi
- uses: actions/upload-artifact@v7
with:
name: argument-comment-lint-${{ matrix.target }}
path: dist/argument-comment-lint/${{ matrix.target }}/*

View File

@@ -380,11 +380,19 @@ jobs:
publish: true
secrets: inherit
argument-comment-lint-release-assets:
name: argument-comment-lint release assets
needs: tag-check
uses: ./.github/workflows/rust-release-argument-comment-lint.yml
with:
publish: true
release:
needs:
- build
- build-windows
- shell-tool-mcp
- argument-comment-lint-release-assets
name: release
runs-on: ubuntu-latest
permissions:
@@ -521,6 +529,13 @@ jobs:
tag: ${{ github.ref_name }}
config: .github/dotslash-config.json
- uses: facebook/dotslash-publish-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag: ${{ github.ref_name }}
config: .github/dotslash-argument-comment-lint-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.

View File

@@ -68,6 +68,11 @@ cd tools/argument-comment-lint
cargo test
```
GitHub releases also publish a DotSlash file named
`argument-comment-lint` for macOS arm64, Linux arm64, Linux x64, and Windows
x64. The published package contains a small runner executable, a bundled
`cargo-dylint`, and the prebuilt lint library.
Run the lint against `codex-rs` from the repo root:
```bash

View File

@@ -0,0 +1,164 @@
use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::process::ExitCode;
fn main() -> ExitCode {
match run() {
Ok(code) => code,
Err(err) => {
eprintln!("{err}");
ExitCode::from(1)
}
}
}
fn run() -> Result<ExitCode, String> {
let exe_path =
env::current_exe().map_err(|err| format!("failed to locate current executable: {err}"))?;
let bin_dir = exe_path.parent().ok_or_else(|| {
format!(
"failed to locate parent directory for executable {}",
exe_path.display()
)
})?;
let package_root = bin_dir.parent().ok_or_else(|| {
format!(
"failed to locate package root for executable {}",
exe_path.display()
)
})?;
let cargo_dylint = bin_dir.join(cargo_dylint_binary_name());
let library_dir = package_root.join("lib");
let library_path = find_bundled_library(&library_dir)?;
ensure_exists(&cargo_dylint, "bundled cargo-dylint executable")?;
ensure_exists(
&library_dir,
"bundled argument-comment lint library directory",
)?;
let args: Vec<OsString> = env::args_os().skip(1).collect();
let mut command = Command::new(&cargo_dylint);
command.arg("dylint");
command.arg("--lib-path").arg(&library_path);
if !has_library_selection(&args) {
command.arg("--all");
}
command.args(&args);
set_default_env(&mut command);
let status = command
.status()
.map_err(|err| format!("failed to execute {}: {err}", cargo_dylint.display()))?;
Ok(exit_code_from_status(status.code()))
}
fn has_library_selection(args: &[OsString]) -> bool {
let mut expect_value = false;
for arg in args {
if expect_value {
return true;
}
match arg.to_string_lossy().as_ref() {
"--" => break,
"--lib" | "--lib-path" => {
expect_value = true;
}
"--lib=" | "--lib-path=" => return true,
value if value.starts_with("--lib=") || value.starts_with("--lib-path=") => {
return true;
}
_ => {}
}
}
false
}
fn set_default_env(command: &mut Command) {
if let Some(flags) = env::var_os("DYLINT_RUSTFLAGS") {
let mut flags = flags.to_string_lossy().to_string();
append_flag_if_missing(&mut flags, "-D uncommented-anonymous-literal-argument");
append_flag_if_missing(&mut flags, "-A unknown_lints");
command.env("DYLINT_RUSTFLAGS", flags);
} else {
command.env(
"DYLINT_RUSTFLAGS",
"-D uncommented-anonymous-literal-argument -A unknown_lints",
);
}
if env::var_os("CARGO_INCREMENTAL").is_none() {
command.env("CARGO_INCREMENTAL", "0");
}
}
fn append_flag_if_missing(flags: &mut String, flag: &str) {
if flags.contains(flag) {
return;
}
if !flags.is_empty() {
flags.push(' ');
}
flags.push_str(flag);
}
fn cargo_dylint_binary_name() -> &'static str {
if cfg!(windows) {
"cargo-dylint.exe"
} else {
"cargo-dylint"
}
}
fn ensure_exists(path: &Path, label: &str) -> Result<(), String> {
if path.exists() {
Ok(())
} else {
Err(format!("{label} not found at {}", path.display()))
}
}
fn find_bundled_library(library_dir: &Path) -> Result<PathBuf, String> {
let entries = fs::read_dir(library_dir).map_err(|err| {
format!(
"failed to read bundled library directory {}: {err}",
library_dir.display()
)
})?;
let mut candidates = entries
.filter_map(Result::ok)
.map(|entry| entry.path())
.filter(|path| path.is_file())
.filter(|path| {
path.file_name()
.map(|name| name.to_string_lossy().contains('@'))
.unwrap_or(false)
});
let Some(first) = candidates.next() else {
return Err(format!(
"no packaged Dylint library found in {}",
library_dir.display()
));
};
if candidates.next().is_some() {
return Err(format!(
"expected exactly one packaged Dylint library in {}",
library_dir.display()
));
}
Ok(first)
}
fn exit_code_from_status(code: Option<i32>) -> ExitCode {
code.and_then(|value| u8::try_from(value).ok())
.map_or_else(|| ExitCode::from(1), ExitCode::from)
}