Fix version embedding in release builds

- Add determine-version job to calculate version before building
- Set version in Cargo.toml before building binaries
- Use pre-determined version for npm publishing
- This ensures binaries report correct version instead of 0.0.0
- Fixes upgrade check always appearing due to version mismatch
This commit is contained in:
James Peter
2025-08-14 19:50:53 +10:00
parent 2953a7f60a
commit 537f50b2d0
4 changed files with 188 additions and 4035 deletions
+81 -21
View File
@@ -15,8 +15,57 @@ concurrency:
cancel-in-progress: true
jobs:
determine-version:
name: Determine Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Determine next version
id: version
working-directory: codex-cli
run: |
# Get current version from package.json
CURRENT_VERSION=$(node -p "require('./package.json').version")
echo "Current version in package.json: $CURRENT_VERSION"
# Check latest published version
PUBLISHED_VERSION=$(npm view @just-every/coder version 2>/dev/null || echo "0.0.0")
echo "Latest published version: $PUBLISHED_VERSION"
# Determine the version to use for this build
if [ "$CURRENT_VERSION" = "$PUBLISHED_VERSION" ] || [ "$CURRENT_VERSION" \< "$PUBLISHED_VERSION" ]; then
# Need to bump from published version
echo "Will bump from published version $PUBLISHED_VERSION"
# Calculate next patch version
IFS='.' read -ra VERSION_PARTS <<< "$PUBLISHED_VERSION"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
PATCH=${VERSION_PARTS[2]}
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"
else
echo "Using current version $CURRENT_VERSION which is ahead of published $PUBLISHED_VERSION"
NEW_VERSION=$CURRENT_VERSION
fi
echo "Version for this build: $NEW_VERSION"
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
build-binaries:
name: Build ${{ matrix.target }}
needs: determine-version
runs-on: ${{ matrix.os }}
strategy:
matrix:
@@ -61,6 +110,31 @@ jobs:
sudo apt-get update
sudo apt-get install -y musl-tools pkg-config
- name: Set version in Cargo.toml
run: |
VERSION="${{ needs.determine-version.outputs.version }}"
echo "📝 Setting version to ${VERSION} in Cargo.toml files"
# Update the workspace version in root Cargo.toml
cd codex-rs
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
# Windows doesn't have sed -i, use a different approach
powershell -Command "(Get-Content Cargo.toml) -replace '^version = \".*\"', 'version = \"$env:VERSION\"' | Set-Content Cargo.toml"
else
# Unix-like systems
sed -i.bak "s/^version = \".*\"/version = \"${VERSION}\"/" Cargo.toml
fi
# Verify the update
echo "Updated Cargo.toml:"
grep "^version = " Cargo.toml || true
# Update Cargo.lock to reflect the new version
cargo update --workspace
shell: bash
env:
VERSION: ${{ needs.determine-version.outputs.version }}
- name: Build binaries
run: |
cd codex-rs
@@ -88,7 +162,7 @@ jobs:
release:
name: Publish to npm
needs: build-binaries
needs: [determine-version, build-binaries]
runs-on: ubuntu-latest
timeout-minutes: 30
# Skip if commit message contains [skip ci]
@@ -128,7 +202,7 @@ jobs:
# List assets for verification
ls -la release-assets/
- name: Bump version
- name: Update package.json version
id: version
working-directory: codex-cli
run: |
@@ -136,27 +210,13 @@ jobs:
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
# Get current version
CURRENT_VERSION=$(node -p "require('./package.json').version")
echo "Current version in package.json: $CURRENT_VERSION"
# Use the pre-determined version
NEW_VERSION="${{ needs.determine-version.outputs.version }}"
echo "Setting version to: $NEW_VERSION"
# Check latest published version
PUBLISHED_VERSION=$(npm view @just-every/coder version 2>/dev/null || echo "0.0.0")
echo "Latest published version: $PUBLISHED_VERSION"
# Update package.json with the new version
npm version $NEW_VERSION --no-git-tag-version --allow-same-version
# Compare versions and bump appropriately
if [ "$CURRENT_VERSION" = "$PUBLISHED_VERSION" ] || [ "$CURRENT_VERSION" \< "$PUBLISHED_VERSION" ]; then
# Need to bump from published version
echo "Bumping from published version $PUBLISHED_VERSION"
# Set to published version first, then bump
npm version $PUBLISHED_VERSION --no-git-tag-version --allow-same-version
npm version patch --no-git-tag-version
else
echo "Current version $CURRENT_VERSION is already ahead of published $PUBLISHED_VERSION"
fi
NEW_VERSION=$(node -p "require('./package.json').version")
echo "New version: $NEW_VERSION"
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
# Commit changes
+9
View File
@@ -974,6 +974,15 @@ impl BrowserManager {
async fn capture_screenshot_regular(&self) -> Result<(Vec<std::path::PathBuf>, String)> {
// For launched Chrome, use the regular approach since it's already isolated
let page = self.get_or_create_page().await?;
// For external Chrome connections, skip viewport correction to respect user settings
let config = self.config.read().await;
let is_external = config.connect_port.is_some() || config.connect_ws.is_some();
drop(config);
if is_external {
debug!("Skipping viewport correction for external Chrome connection");
}
// Initialize assets manager if needed
let mut assets_guard = self.assets.lock().await;
+98 -2
View File
@@ -12,6 +12,7 @@ use chromiumoxide::cdp::browser_protocol::input::DispatchMouseEventType;
use chromiumoxide::cdp::browser_protocol::input::MouseButton;
// Import AddScriptToEvaluateOnNewDocumentParams (New)
use base64::Engine as _;
use chromiumoxide::cdp::browser_protocol::emulation::SetDeviceMetricsOverrideParams;
use chromiumoxide::cdp::browser_protocol::page::AddScriptToEvaluateOnNewDocumentParams;
use chromiumoxide::cdp::browser_protocol::page::CaptureScreenshotFormat;
use chromiumoxide::cdp::browser_protocol::page::CaptureScreenshotParams;
@@ -242,6 +243,96 @@ impl Page {
self.cdp_page.get_title().await.ok().flatten()
}
/// Check and fix viewport scaling issues before taking screenshots
async fn check_and_fix_scaling(&self) -> Result<()> {
// Check current viewport and scaling
let check_script = r#"
(() => {
const vw = window.innerWidth;
const vh = window.innerHeight;
const dpr = window.devicePixelRatio || 1;
const zoom = Math.round(window.outerWidth / window.innerWidth * 100) / 100;
// Check if viewport matches expected dimensions
const expectedWidth = %EXPECTED_WIDTH%;
const expectedHeight = %EXPECTED_HEIGHT%;
const expectedDpr = %EXPECTED_DPR%;
return {
currentWidth: vw,
currentHeight: vh,
currentDpr: dpr,
currentZoom: zoom,
expectedWidth: expectedWidth,
expectedHeight: expectedHeight,
expectedDpr: expectedDpr,
needsCorrection: (
Math.abs(vw - expectedWidth) > 5 ||
Math.abs(vh - expectedHeight) > 5 ||
Math.abs(dpr - expectedDpr) > 0.1 ||
Math.abs(zoom - 1.0) > 0.1
)
};
})()
"#;
// Replace placeholders with actual expected values
let script = check_script
.replace("%EXPECTED_WIDTH%", &self.config.viewport.width.to_string())
.replace("%EXPECTED_HEIGHT%", &self.config.viewport.height.to_string())
.replace("%EXPECTED_DPR%", &self.config.viewport.device_scale_factor.to_string());
let result = self.cdp_page.evaluate(script).await?;
if let Some(obj) = result.value() {
let needs_correction = obj.get("needsCorrection")
.and_then(|v| v.as_bool())
.unwrap_or(false);
if needs_correction {
let current_width = obj.get("currentWidth").and_then(|v| v.as_u64()).unwrap_or(0);
let current_height = obj.get("currentHeight").and_then(|v| v.as_u64()).unwrap_or(0);
let current_dpr = obj.get("currentDpr").and_then(|v| v.as_f64()).unwrap_or(1.0);
let current_zoom = obj.get("currentZoom").and_then(|v| v.as_f64()).unwrap_or(1.0);
debug!(
"Viewport needs correction: {}x{} @ {}x DPR (zoom: {}) -> {}x{} @ {}x DPR",
current_width, current_height, current_dpr, current_zoom,
self.config.viewport.width, self.config.viewport.height,
self.config.viewport.device_scale_factor
);
// Use CDP to set the correct viewport metrics
let params = SetDeviceMetricsOverrideParams::builder()
.width(self.config.viewport.width as i64)
.height(self.config.viewport.height as i64)
.device_scale_factor(self.config.viewport.device_scale_factor)
.mobile(self.config.viewport.mobile)
.build()
.map_err(|e| BrowserError::CdpError(format!("Failed to build viewport params: {}", e)))?;
self.cdp_page.execute(params).await?;
// Also reset zoom if it's not 1.0
if (current_zoom - 1.0).abs() > 0.1 {
debug!("Resetting zoom from {} to 1.0", current_zoom);
let reset_zoom_script = r#"
// Reset zoom to 100%
document.body.style.zoom = '1.0';
// Also try to reset CSS transform scale if present
document.documentElement.style.transform = 'scale(1)';
document.documentElement.style.transformOrigin = '0 0';
"#;
let _ = self.cdp_page.evaluate(reset_zoom_script).await;
}
info!("Viewport scaling corrected");
}
}
Ok(())
}
/// (NEW) Injects a virtual cursor element into the page at the current coordinates.
pub async fn inject_virtual_cursor(&self) -> Result<()> {
let cursor = self.cursor_state.lock().await.clone();
@@ -713,14 +804,19 @@ impl Page {
// (UPDATED) Inject cursor before taking screenshot
pub async fn screenshot(&self, mode: ScreenshotMode) -> Result<Vec<Screenshot>> {
// First, check and fix viewport scaling if needed
if let Err(e) = self.check_and_fix_scaling().await {
warn!("Failed to check/fix viewport scaling: {}, continuing anyway", e);
}
// Inject the virtual cursor before capturing
if let Err(e) = self.inject_virtual_cursor().await {
warn!("Failed to inject virtual cursor: {}", e);
// Continue with screenshot even if cursor injection fails
}
// Allow a brief moment for the cursor SVG to render
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
// Allow a brief moment for the cursor SVG to render and scaling to apply
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
match mode {
ScreenshotMode::Viewport => self.screenshot_viewport().await,
File diff suppressed because it is too large Load Diff