From b0d7c0226ea25225d34c2acabe102f0d788f1827 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 25 Jul 2026 14:44:14 +0200 Subject: [PATCH 1/2] feat: Integrate oxc and release configs --- .editorconfig | 14 +++++++ .github/workflows/unit-test.yml | 2 +- .releaserc | 37 ----------------- eslint.config.mjs | 5 --- lib/helpers.ts | 10 ++--- lib/xcode.ts | 33 ++++++---------- oxfmt.config.mjs | 6 +++ oxlint.config.mjs | 6 +++ package.json | 70 ++++++++++++++------------------- release.config.mjs | 3 ++ test/e2e/xcode.spec.ts | 6 ++- test/unit/index.spec.ts | 3 +- tsconfig.json | 5 +-- 13 files changed, 83 insertions(+), 117 deletions(-) create mode 100644 .editorconfig delete mode 100644 .releaserc delete mode 100644 eslint.config.mjs create mode 100644 oxfmt.config.mjs create mode 100644 oxlint.config.mjs create mode 100644 release.config.mjs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b8fa91e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 120 + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 1985353..f5001f8 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -28,6 +28,6 @@ jobs: - name: Run linter run: npm run lint - run: npm run format:check - name: Run Prettier check + name: Run format check - name: Run unit tests run: npm run test diff --git a/.releaserc b/.releaserc deleted file mode 100644 index 93cf006..0000000 --- a/.releaserc +++ /dev/null @@ -1,37 +0,0 @@ -{ - "plugins": [ - ["@semantic-release/commit-analyzer", { - "preset": "angular", - "releaseRules": [ - {"type": "chore", "release": "patch"} - ] - }], - ["@semantic-release/release-notes-generator", { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - {"type": "feat", "section": "Features"}, - {"type": "fix", "section": "Bug Fixes"}, - {"type": "perf", "section": "Performance Improvements"}, - {"type": "revert", "section": "Reverts"}, - {"type": "chore", "section": "Miscellaneous Chores"}, - {"type": "refactor", "section": "Code Refactoring"}, - {"type": "docs", "section": "Documentation", "hidden": true}, - {"type": "style", "section": "Styles", "hidden": true}, - {"type": "test", "section": "Tests", "hidden": true}, - {"type": "build", "section": "Build System", "hidden": true}, - {"type": "ci", "section": "Continuous Integration", "hidden": true} - ] - } - }], - ["@semantic-release/changelog", { - "changelogFile": "CHANGELOG.md" - }], - "@semantic-release/npm", - ["@semantic-release/git", { - "assets": ["docs", "package.json", "CHANGELOG.md"], - "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" - }], - "@semantic-release/github" - ] -} diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 4d52325..0000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -import appiumConfig from '@appium/eslint-config-appium-ts'; - -export default [ - ...appiumConfig, -]; diff --git a/lib/helpers.ts b/lib/helpers.ts index f00ef29..df47f18 100644 --- a/lib/helpers.ts +++ b/lib/helpers.ts @@ -1,7 +1,8 @@ +import path from 'node:path'; + +import {fs, plist} from '@appium/support'; import {exec} from 'teen_process'; import type {TeenProcessExecResult} from 'teen_process'; -import {fs, plist} from '@appium/support'; -import path from 'node:path'; export const XCRUN_TIMEOUT = 15000; @@ -22,10 +23,7 @@ export async function runXcrunCommand( } catch (err) { if (err instanceof Error) { // the true error can be hidden within the stderr - const stderr = - err && typeof err === 'object' && 'stderr' in err - ? String((err as {stderr: unknown}).stderr) - : ''; + const stderr = err && typeof err === 'object' && 'stderr' in err ? String((err as {stderr: unknown}).stderr) : ''; if (stderr) { err.message = `${err.message}: ${stderr}`; } diff --git a/lib/xcode.ts b/lib/xcode.ts index 665e2f9..54c56b0 100644 --- a/lib/xcode.ts +++ b/lib/xcode.ts @@ -1,8 +1,10 @@ -import {fs, logger, util} from '@appium/support'; import path from 'node:path'; + +import {fs, logger, util} from '@appium/support'; import {retry} from 'asyncbox'; -import {exec} from 'teen_process'; import * as semver from 'semver'; +import {exec} from 'teen_process'; + import {runXcrunCommand, findAppPaths, XCRUN_TIMEOUT, readXcodePlist} from './helpers.js'; import type {XcodeVersion} from './types.js'; @@ -25,9 +27,7 @@ export async function getPathFromXcodeSelect(timeout: number = XCRUN_TIMEOUT): P return `${prefix}. Consider installing Xcode to address this issue.`; } - const proposals = xcodePaths.map( - (p) => ` sudo xcode-select -s "${path.join(p, 'Contents', 'Developer')}"`, - ); + const proposals = xcodePaths.map((p) => ` sudo xcode-select -s "${path.join(p, 'Contents', 'Developer')}"`); return ( `${prefix}. ` + `Consider running${proposals.length > 1 ? ' any of' : ''}:\n${proposals.join('\n')}\nto address this issue.` @@ -38,8 +38,7 @@ export async function getPathFromXcodeSelect(timeout: number = XCRUN_TIMEOUT): P try { ({stdout} = await exec('xcode-select', ['--print-path'], {timeout})); } catch (e) { - const stderr = - e && typeof e === 'object' && 'stderr' in e ? String((e as {stderr: unknown}).stderr) : ''; + const stderr = e && typeof e === 'object' && 'stderr' in e ? String((e as {stderr: unknown}).stderr) : ''; const message = e instanceof Error ? e.message : String(e); const msg = `Cannot determine the path to Xcode by running 'xcode-select -p' command. ` + @@ -93,8 +92,9 @@ export async function getPathFromDeveloperDir(): Promise { * @returns Full path to Xcode Developer subfolder timeout * @throws {Error} If there was an error while retrieving the path. */ -export const getPath = util.memoize((timeout: number = XCRUN_TIMEOUT): Promise => - process.env.DEVELOPER_DIR ? getPathFromDeveloperDir() : getPathFromXcodeSelect(timeout), +export const getPath = util.memoize( + (timeout: number = XCRUN_TIMEOUT): Promise => + process.env.DEVELOPER_DIR ? getPathFromDeveloperDir() : getPathFromXcodeSelect(timeout), ); /** @@ -107,11 +107,7 @@ export const getPath = util.memoize((timeout: number = XCRUN_TIMEOUT): Promise; -export async function getVersion( - parse: true, - retries?: number, - timeout?: number, -): Promise; +export async function getVersion(parse: true, retries?: number, timeout?: number): Promise; export async function getVersion( parse: boolean = false, retries: number = DEFAULT_NUMBER_OF_RETRIES, @@ -149,10 +145,7 @@ export async function getClangVersion(): Promise { try { await fs.which('clang'); } catch { - log.info( - 'Cannot find clang executable on the local system. ' + - 'Are Xcode Command Line Tools installed?', - ); + log.info('Cannot find clang executable on the local system. ' + 'Are Xcode Command Line Tools installed?'); return null; } const {stdout} = await exec('clang', ['--version']); @@ -238,9 +231,7 @@ export const getMaxTVOSSDK = util.memoize(async function getMaxTVOSSDK( * @returns Xcode version * @throws {Error} If there was a failure while retrieving the version */ -async function getVersionWithoutRetry( - timeout: number = XCRUN_TIMEOUT, -): Promise { +async function getVersionWithoutRetry(timeout: number = XCRUN_TIMEOUT): Promise { const developerPath = await getPath(timeout); // we want to read the CFBundleShortVersionString from Xcode's plist. const {CFBundleShortVersionString} = await readXcodePlist(developerPath); diff --git a/oxfmt.config.mjs b/oxfmt.config.mjs new file mode 100644 index 0000000..4752f81 --- /dev/null +++ b/oxfmt.config.mjs @@ -0,0 +1,6 @@ +import appiumConfig, {defineConfig, ignorePatterns} from '@appium/oxc-config/oxfmt'; + +export default defineConfig({ + ...appiumConfig, + ignorePatterns: [...ignorePatterns], +}); diff --git a/oxlint.config.mjs b/oxlint.config.mjs new file mode 100644 index 0000000..34ea238 --- /dev/null +++ b/oxlint.config.mjs @@ -0,0 +1,6 @@ +import appiumConfig, {defineConfig, ignorePatterns} from '@appium/oxc-config/oxlint'; + +export default defineConfig({ + extends: [appiumConfig], + ignorePatterns: [...ignorePatterns], +}); diff --git a/package.json b/package.json index a5c5c66..28e7a0d 100644 --- a/package.json +++ b/package.json @@ -1,75 +1,65 @@ { "name": "appium-xcode", + "version": "7.0.0", "description": "Interact with Xcode", "keywords": [ "appium", "ios", "xcode" ], - "version": "7.0.0", - "author": "Appium Contributors", + "bugs": { + "url": "https://github.com/appium/appium-xcode/issues" + }, "license": "Apache-2.0", + "author": "Appium Contributors", "repository": { "type": "git", "url": "https://github.com/appium/appium-xcode.git" }, - "bugs": { - "url": "https://github.com/appium/appium-xcode/issues" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": ">=10" - }, - "main": "./build/lib/index.js", - "types": "./build/lib/index.d.ts", "files": [ "lib", "build/lib", "CHANGELOG.md" ], - "dependencies": { - "@appium/support": "^7.2.2", - "asyncbox": "^6.0.1", - "semver": "^7.0.0", - "teen_process": "^4.0.4" + "type": "module", + "main": "./build/lib/index.js", + "types": "./build/lib/index.d.ts", + "exports": { + ".": { + "types": "./build/lib/index.d.ts", + "import": "./build/lib/index.js" + }, + "./package.json": "./package.json" }, "scripts": { "build": "tsc -b", "clean": "npm run build -- --clean", "rebuild": "npm run clean; npm run build", "dev": "npm run build -- --watch", - "lint": "eslint .", - "lint:fix": "npm run lint -- --fix", - "format": "prettier -w ./lib ./test", - "format:check": "prettier --check ./lib ./test", + "lint": "oxlint -c oxlint.config.mjs .", + "lint:fix": "oxlint -c oxlint.config.mjs --fix .", + "format": "oxfmt -c oxfmt.config.mjs .", + "format:check": "oxfmt -c oxfmt.config.mjs --check .", "prepare": "npm run build", "test": "node --enable-source-maps --test --test-timeout=60000 \"./build/test/unit/**/*.spec.js\"", "e2e-test": "node --enable-source-maps --test --test-force-exit --test-concurrency=1 --test-timeout=300000 \"./build/test/e2e/**/*.spec.js\"" }, - "prettier": { - "bracketSpacing": false, - "printWidth": 100, - "singleQuote": true + "dependencies": { + "@appium/support": "^7.2.2", + "asyncbox": "^6.0.1", + "semver": "^7.0.0", + "teen_process": "^4.0.4" }, "devDependencies": { - "@appium/eslint-config-appium-ts": "^3.0.0", - "@appium/tsconfig": "^1.0.0-rc.1", + "@appium/oxc-config": "^1.1.0", + "@appium/semantic-release-config": "^1.1.0", + "@appium/tsconfig": "^1.2.0", "@appium/types": "^1.0.0-rc.1", - "@semantic-release/changelog": "^6.0.1", - "@semantic-release/git": "^10.0.1", "@types/node": "^26.0.0", - "@types/semver": "^7.7.1", - "conventional-changelog-conventionalcommits": "^9.3.1", - "prettier": "^3.9.3", - "semantic-release": "^25.0.2", - "typescript": "^6.0.2" + "@types/semver": "^7.7.1" }, - "type": "module", - "exports": { - ".": { - "types": "./build/lib/index.d.ts", - "import": "./build/lib/index.js" - }, - "./package.json": "./package.json" + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0", + "npm": ">=10" } } diff --git a/release.config.mjs b/release.config.mjs new file mode 100644 index 0000000..83f3400 --- /dev/null +++ b/release.config.mjs @@ -0,0 +1,3 @@ +import releaseConfig from '@appium/semantic-release-config'; + +export default releaseConfig(); diff --git a/test/e2e/xcode.spec.ts b/test/e2e/xcode.spec.ts index 5075ffe..05b8531 100644 --- a/test/e2e/xcode.spec.ts +++ b/test/e2e/xcode.spec.ts @@ -1,8 +1,10 @@ -import {fs, util} from '@appium/support'; import assert from 'node:assert/strict'; -import * as xcode from '../../lib/xcode.js'; import {describe, it} from 'node:test'; +import {fs, util} from '@appium/support'; + +import * as xcode from '../../lib/xcode.js'; + // on slow machines and busy CI systems these can be slow and flakey describe('xcode', {timeout: 30000}, function () { describe('getPath', function () { diff --git a/test/unit/index.spec.ts b/test/unit/index.spec.ts index 1dc4354..7e2b973 100644 --- a/test/unit/index.spec.ts +++ b/test/unit/index.spec.ts @@ -1,7 +1,8 @@ import assert from 'node:assert/strict'; -import xcode from '../../lib/index.js'; import {describe, it} from 'node:test'; +import xcode from '../../lib/index.js'; + describe('index', function () { it('exported objects should exist', function () { assert.ok(xcode); diff --git a/tsconfig.json b/tsconfig.json index 7d12b32..22132c1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,5 @@ "module": "NodeNext", "moduleResolution": "NodeNext" }, - "include": [ - "lib", - "test" - ] + "include": ["lib", "test"] } From 474585b3b8ba39421065b7bf84acedcaeb3c32cf Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sat, 25 Jul 2026 19:44:23 +0200 Subject: [PATCH 2/2] Address comments --- lib/xcode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/xcode.ts b/lib/xcode.ts index 54c56b0..7aed961 100644 --- a/lib/xcode.ts +++ b/lib/xcode.ts @@ -145,7 +145,7 @@ export async function getClangVersion(): Promise { try { await fs.which('clang'); } catch { - log.info('Cannot find clang executable on the local system. ' + 'Are Xcode Command Line Tools installed?'); + log.info('Cannot find clang executable on the local system. Are Xcode Command Line Tools installed?'); return null; } const {stdout} = await exec('clang', ['--version']);