Skip to content
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ dist/
.idea/
plan.md
coverage/
tests/integration/resources/sonar-secrets*
.eslintcache
5 changes: 4 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ Use `runCommand()` from `src/lib/run-command.ts` to wrap command handlers — it

## Tests

Please try to create integration tests in priority. If the test is too complicated to set up, write unit tests.
Try to get inspiration from other tests to follow the same structure.

- Unit tests: `tests/unit/` — run with `bun test`
- Integration tests: `tests/integration/` — require env vars, skipped locally by default
- Integration tests: `tests/integration/` — require env vars. They are using a harness to help set up tests and make assertions.
- The UI module has a built-in mock system (`src/ui/mock.ts`) — use it instead of mocking stdout directly.

## Documentation
Expand Down
89 changes: 89 additions & 0 deletions build-scripts/setup-integration-resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* SonarQube CLI
* Copyright (C) 2026 SonarSource Sàrl
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

/**
* Downloads the sonar-secrets binary and its PGP signature for the current
* platform from binaries.sonarsource.com and places them in
* tests/integration/resources/ using the original versioned filenames
* (e.g. sonar-secrets-2.41.0.10709-linux-x86-64.exe).
*
* Run via: bun build-scripts/setup-integration-resources.ts
* Or via: bun run test:integration:prepare
*/

import { existsSync, mkdirSync } from 'node:fs';
import { chmod } from 'node:fs/promises';
import { join } from 'node:path';
import { detectPlatform } from '../src/lib/platform-detector.js';
import {
buildDownloadUrl,
downloadBinary,
verifyBinarySignature,
} from '../src/lib/sonarsource-releases.js';
import {
SONAR_SECRETS_VERSION,
SONAR_SECRETS_SIGNATURES,
SONARSOURCE_PUBLIC_KEY,
} from '../src/lib/signatures.js';

const RESOURCES_DIR = join(import.meta.dir, '..', 'tests', 'integration', 'resources');
const platform = detectPlatform();
const downloadUrl = buildDownloadUrl(SONAR_SECRETS_VERSION, platform);
const signatureUrl = `${downloadUrl}.asc`;
// Keep the original versioned filename so the fake binaries server can match requests exactly
const downloadFilename = downloadUrl.split('/').at(-1)!;
const destPath = join(RESOURCES_DIR, downloadFilename);
const ascDestPath = join(RESOURCES_DIR, `${downloadFilename}.asc`);

const binaryExists = existsSync(destPath);
const ascExists = existsSync(ascDestPath);

if (binaryExists && ascExists) {
console.log(`Resources already present at ${RESOURCES_DIR} — skipping download.`);
process.exit(0);
}

mkdirSync(RESOURCES_DIR, { recursive: true });

if (!binaryExists) {
console.log(
`Downloading sonar-secrets ${SONAR_SECRETS_VERSION} for ${platform.os}-${platform.arch}`,
);
console.log(` from ${downloadUrl}`);
await downloadBinary(downloadUrl, destPath);
console.log(' Download complete.');

console.log('Verifying PGP signature...');
await verifyBinarySignature(destPath, platform, SONAR_SECRETS_SIGNATURES, SONARSOURCE_PUBLIC_KEY);
console.log(' Signature verified.');

if (platform.os !== 'windows') {
await chmod(destPath, 0o755);
}

console.log(`sonar-secrets ready at ${destPath}`);
}

if (!ascExists) {
console.log(`Downloading PGP signature file...`);
console.log(` from ${signatureUrl}`);
await downloadBinary(signatureUrl, ascDestPath);
console.log(` Signature file ready at ${ascDestPath}`);
}
7 changes: 4 additions & 3 deletions build-scripts/update-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ fi

echo "🔄 Updating version to $NEW_VERSION..."

# Update package.json (single source of truth)
# Update package.json (single source of truth — only top-level version field)
echo " 📝 Updating package.json..."
sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"$NEW_VERSION\"/" package.json
npm pkg set version="$NEW_VERSION" --no-git-tag-version 2>/dev/null || \
node -e "const fs=require('fs'),p='package.json',j=JSON.parse(fs.readFileSync(p,'utf8'));j.version='$NEW_VERSION';fs.writeFileSync(p,JSON.stringify(j,null,2)+'\n');"

# Update VERSION in src/version.ts (preserve license header)
# Update src/version.ts (single-line export, safe to replace)
echo " 📝 Updating src/version.ts..."
sed -i '' "s/export const VERSION = '[^']*';/export const VERSION = '$NEW_VERSION';/" src/version.ts

Expand Down
Loading