Skip to content

Commit b65d78c

Browse files
authored
ci: added sonar action and separated e2e action from the rest (#14)
* ci: added sonar action and separated e2e action from the rest * test: added more retries * ci: passing coverage from build step * ci: moved artifact for coverage to correct job * ci: changed if from ubuntu to Linux * ci: corrected ifs * ci: corrected every runner os * ci: added webviews build output to actions * ci: correcting cache, trying to add tests to sonar * ci: correcting cache parts * docs: added badges * refactor: corrected sonar warnings * refacotor: corrected type * ci: trying to get coverage results * test: updated max retries for docker commands * ci: updates timeout for docker start * ci: trying to use sonarqube reporter * ci: corrected config creation * ci: trying to use only mocha-reporter-sonarqube * ci: check if there are reports * ci: removed coverage from action * refactor: removed not needed code
1 parent c4ee1fa commit b65d78c

26 files changed

+157
-204
lines changed

.github/workflows/lint.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

.github/workflows/nodejs.yml

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,67 @@ jobs:
3131
- name: Check Docker Version
3232
run: docker --version
3333

34-
- name: Check Node.js version
35-
run: node -v
36-
3734
- name: Check npm versions
3835
run: npm -v
3936

37+
- name: Cache node_modules
38+
uses: actions/cache@v4
39+
with:
40+
path: |
41+
node_modules
42+
webview-ui/build
43+
webview-ui/node-modules
44+
key: node_modules-${{ matrix.os }}-node-${{ matrix.node-version }}-${{ hashFiles('package-lock.json') }}
45+
restore-keys: |
46+
node_modules-${{ matrix.os }}-node-${{ matrix.node-version }}
47+
4048
- name: Run clean install
4149
run: npm ci
4250

43-
- run: xvfb-run -a npm test
51+
52+
- name: Run tests on Linux
53+
run: xvfb-run -a npm test
4454
if: runner.os == 'Linux'
45-
- run: npm test
55+
- name: Run tests on macOS and Windows
56+
run: npm test
4657
if: runner.os != 'Linux'
4758

59+
e2e-tests:
60+
needs: build
61+
strategy:
62+
matrix:
63+
# No windows runner, because in this extension, we have a lot of tests that need docker in the WSL.
64+
# Sadly, the setup-wsl (https://github.com/Vampire/setup-wsl) and the current windows runners only support WSL 1.
65+
# Therefore, we can not install and start a docker container in the WSL.
66+
67+
# Currently, no macOS runner, because during the setup of docker, this runner hangs: https://github.com/douglascamata/setup-docker-macos-action/issues/37
68+
node-version: [18.x, 20.x, 22.x]
69+
os: [ubuntu-latest]
70+
runs-on: ${{ matrix.os }}
71+
steps:
72+
- uses: actions/checkout@v4
73+
- name: Set up Node.js
74+
uses: actions/setup-node@v4
75+
with:
76+
node-version: ${{ matrix.node-version }}
77+
78+
- name: Set up JDK for Liquibase CLI
79+
uses: actions/setup-java@v4
80+
with:
81+
java-version: 21
82+
distribution: temurin
83+
84+
- name: Restore cached node_modules
85+
uses: actions/cache@v4
86+
with:
87+
path: |
88+
node_modules
89+
webview-ui/build
90+
webview-ui/node-modules
91+
key: node_modules-${{ matrix.os }}-node-${{ matrix.node-version }}-${{ hashFiles('package-lock.json') }}
92+
restore-keys: |
93+
node_modules-${{ matrix.os }}-node-${{ matrix.node-version }}
94+
4895
- name: run e2e tests
4996
run: xvfb-run -a npm run test:e2e -- --storage ./out/test-resources/${{ matrix.os }}/${{ matrix.node-version }}
5097
if: runner.os == 'Linux'
@@ -61,3 +108,38 @@ jobs:
61108
path: ./out/test-resources/**/screenshots/**
62109
retention-days: 5
63110
if-no-files-found: ignore
111+
112+
sonar:
113+
name: Run eslint and sonar scanning
114+
runs-on: ubuntu-latest
115+
needs: build
116+
steps:
117+
- name: Checkout code
118+
uses: actions/checkout@v4
119+
120+
- name: Set up Node.js
121+
uses: actions/setup-node@v4
122+
with:
123+
node-version: 22.x
124+
125+
- name: Restore cached node_modules
126+
uses: actions/cache@v4
127+
with:
128+
path: |
129+
node_modules
130+
webview-ui/build
131+
webview-ui/node-modules
132+
key: node_modules-ubuntu-latest-node-22.x-${{ hashFiles('package-lock.json') }}
133+
restore-keys: |
134+
node_modules-ubuntu-latest-node-22.x
135+
- name: Run ESLint
136+
run: npm run lint -- --format json --output-file eslint-results.json || true
137+
138+
- name: Analyze with SonarCloud
139+
uses: SonarSource/sonarcloud-github-action@master
140+
env:
141+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
142+
with:
143+
args: -Dsonar.projectKey=aditosoftware_vscode-liquibase
144+
-Dsonar.organization=aditosoftware
145+
-Dsonar.eslint.reportPaths=eslint-results.json

.vscode-test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default defineConfig({
77
launchArgs: ["--disable-extensions", "--profile-temp"],
88
mocha: {
99
ui: "tdd",
10-
retries: 3,
10+
retries: 5,
1111
},
1212
coverage: {
1313
// coverage exclusion currently does not work: https://github.com/microsoft/vscode-test-cli/issues/40

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=aditosoftware_vscode-liquibase&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aditosoftware_vscode-liquibase)
2+
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=aditosoftware_vscode-liquibase&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=aditosoftware_vscode-liquibase)
3+
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=aditosoftware_vscode-liquibase&metric=ncloc)](https://sonarcloud.io/summary/new_code?id=aditosoftware_vscode-liquibase)
4+
15
# Liquibase
26

37
A Visual Studio Code extension that supports executing [Liquibase commands](https://docs.liquibase.com/commands/command-list.html) without needing to use the command line.

src/cache/CacheHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ export class CacheHandler {
268268
readContexts(connectionLocation: string, changelogLocation: string): ContextSelection {
269269
const existingChangelog = this.getChangelog(connectionLocation, changelogLocation).existingChangelog;
270270

271-
if (existingChangelog && existingChangelog.contexts) {
271+
if (existingChangelog?.contexts) {
272272
// sort any loaded contexts
273273
existingChangelog.contexts.loadedContexts?.sort((a, b) => a.localeCompare(b));
274274

@@ -287,7 +287,7 @@ export class CacheHandler {
287287
readChangelogs(connectionLocation: string): string[] {
288288
const cache = this.readCache();
289289

290-
if (cache[connectionLocation] && cache[connectionLocation].changelogs) {
290+
if (cache[connectionLocation]?.changelogs) {
291291
return cache[connectionLocation].changelogs
292292
.toSorted((a, b) => b.lastUsed - a.lastUsed)
293293
.map((pChangelog) => pChangelog.path);

src/cache/CacheRemover.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class CacheRemover {
8484

8585
const toRemove = result.inputValues.get(CacheRemover.removeOption);
8686

87-
if (toRemove && toRemove[0]) {
87+
if (toRemove?.[0]) {
8888
this.handleRemoval(toRemove[0], result);
8989
}
9090
}
@@ -170,9 +170,9 @@ export class CacheRemover {
170170

171171
// Build the details
172172
let detail = "";
173-
if (toRemove && toRemove[0]) {
173+
if (toRemove?.[0]) {
174174
// add information about the remove option
175-
detail = CacheRemover.removeOptions.get(toRemove[0]) || "";
175+
detail = CacheRemover.removeOptions.get(toRemove[0]) ?? "";
176176
}
177177

178178
if (propertyFiles) {
@@ -193,7 +193,7 @@ export class CacheRemover {
193193
private shouldShowPropertyFileSelection(currentResults: DialogValues): boolean {
194194
const toRemove = currentResults.inputValues.get(CacheRemover.removeOption);
195195

196-
if (toRemove && toRemove[0]) {
196+
if (toRemove?.[0]) {
197197
return toRemove[0] !== RemoveCacheOptions.WHOLE_CACHE;
198198
} else {
199199
return false;

src/configuration/data/DatabaseConnection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class DatabaseConnection {
7474
if (driver) {
7575
// and extract the url parts
7676
return driver.extractUrlParts(this.url);
77-
} else if (customDriver && customDriver[this.databaseType]) {
77+
} else if (customDriver?.[this.databaseType]) {
7878
return new CustomDriver(customDriver[this.databaseType]).extractUrlParts(this.url);
7979
}
8080

@@ -100,7 +100,7 @@ export class DatabaseConnection {
100100
* @param pValue - the value that should be set
101101
* @returns the updated element
102102
*/
103-
setValue(pName: keyof DatabaseConnection, pValue: string): DatabaseConnection {
103+
setValue(pName: keyof DatabaseConnection, pValue: string): this {
104104
if (typeof this[pName] === "string") {
105105
(this[pName] as string) = pValue;
106106
}

src/configuration/data/LiquibaseConfigurationData.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export class LiquibaseConfigurationData {
188188
}
189189

190190
// and write the reference properties
191-
if (this.referenceDatabaseConnection && this.referenceDatabaseConnection.hasData()) {
191+
if (this.referenceDatabaseConnection?.hasData()) {
192192
this.referenceDatabaseConnection.writeDataForConnection(properties, true, pDisguisePassword);
193193
}
194194

src/configuration/handleChangelogSelection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export async function chooseFileForChangelog(data: LiquibaseConfigurationData):
2121
},
2222
});
2323

24-
if (result && result[0]) {
24+
if (result?.[0]) {
2525
const chosenFile = result[0].fsPath;
2626

2727
// find out relative path

src/executeJar.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export function executeJarAsync<ErrorCode extends number>(
135135
}
136136
});
137137

138-
childProcess.on("error", (error) => {
138+
childProcess.on("error", (error: Error) => {
139139
Logger.getLogger().error({ message: "Child process encountered an error", error });
140140
reject(error);
141141
});
@@ -233,11 +233,11 @@ export async function loadContextsFromChangelogFile(
233233
error: { stack: result.stderr },
234234
notifyUser: true,
235235
});
236-
reject(`Error ${result.status}, ${result.error?.message}\n ${result.stderr}`);
236+
reject(new Error(`Error ${result.status}, ${result.error?.message}\n ${result.stderr}`));
237237
}
238238
} catch (error) {
239239
Logger.getLogger().error({ message: "Error loading contexts", error, notifyUser: true });
240-
reject(error);
240+
reject(error as Error);
241241
}
242242
});
243243
}

src/handleChangelogFileInput.ts

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export class HandleChangelogFileInput {
105105
*/
106106
private static getChangelogFileFromProperties(dialogValues: DialogValues): string | undefined {
107107
const propertyFile = dialogValues.inputValues.get(PROPERTY_FILE);
108-
if (propertyFile && propertyFile[0]) {
108+
if (propertyFile?.[0]) {
109109
const changelog = readChangelog(propertyFile[0]);
110110
if (changelog) {
111111
// if there is a changelog in in property-file, return it, so we can show it in the dialog
@@ -114,24 +114,6 @@ export class HandleChangelogFileInput {
114114
}
115115
}
116116

117-
/**
118-
* Checks if the changelog needs to be put into by an extra open dialog.
119-
*
120-
* @param dialogValues - the current dialog values
121-
* @returns `true` if an OpenDialog is needed for selecting the changelog
122-
*/
123-
private static isChangelogFromOpenDialogNeeded(dialogValues: DialogValues): boolean {
124-
if (this.isExtraQueryForChangelogNeeded(dialogValues)) {
125-
const changelogPreSelection = dialogValues.inputValues.get(this.CHANGELOG_QUICK_PICK_NAME);
126-
if (changelogPreSelection && changelogPreSelection[0]) {
127-
// check, if the correct option was selected
128-
return changelogPreSelection[0] === CHOOSE_CHANGELOG_OPTION;
129-
}
130-
}
131-
132-
return false;
133-
}
134-
135117
/**
136118
* Sets the changelog file from the current dialog correctly as uri (exactly as context menu).
137119
* This will mimic the behavior from a context menu, which is correct in this case.
@@ -145,7 +127,7 @@ export class HandleChangelogFileInput {
145127

146128
let changelogPath: string | undefined;
147129

148-
if (fileSelection && fileSelection[0]) {
130+
if (fileSelection?.[0]) {
149131
if (fileSelection[0] === CHOOSE_CHANGELOG_OPTION) {
150132
// we are not having a correct values selected, but instead a dialog progression value
151133
// => we do not need to save anything

src/handleContexts.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,7 @@ export function generateContextInputs(): PickPanelConfig[] {
7474
export function generateItemsForContextPreDialog(contextCacheInfo?: ContextCacheInformation): vscode.QuickPickItem[] {
7575
const items: vscode.QuickPickItem[] = [];
7676

77-
if (
78-
contextCacheInfo &&
79-
contextCacheInfo.contexts.loadedContexts &&
80-
contextCacheInfo.contexts.loadedContexts.length !== 0
81-
) {
77+
if (contextCacheInfo?.contexts.loadedContexts && contextCacheInfo?.contexts.loadedContexts.length !== 0) {
8278
const cachedContexts = contextCacheInfo.contexts.loadedContexts.join(", ");
8379
items.push({
8480
label: ContextOptions.USE_RECENTLY_LOADED,
@@ -132,10 +128,8 @@ export function saveSelectedContexts(dialogValues: DialogValues, contextCacheInf
132128
*/
133129
function generateCmdArgsForPreContextSelection(dialogValues: DialogValues): string[] | undefined {
134130
const selected = dialogValues.inputValues.get(contextPreDialog);
135-
if (selected && selected[0]) {
136-
if (selected[0] === ContextOptions.NO_CONTEXT) {
137-
return [`--contexts=${NO_CONTEXT_USED}`];
138-
}
131+
if (selected?.[0] === ContextOptions.NO_CONTEXT) {
132+
return [`--contexts=${NO_CONTEXT_USED}`];
139133
}
140134
}
141135

@@ -189,7 +183,7 @@ export function loadCacheForPropertyFile(currentResults: DialogValues): ContextC
189183
function showContextSelection(dialogValues: DialogValues): boolean {
190184
const result = dialogValues.inputValues.get(contextPreDialog);
191185

192-
if (result && result[0]) {
186+
if (result?.[0]) {
193187
return result[0] !== ContextOptions.NO_CONTEXT;
194188
}
195189

src/handleLiquibaseSettings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export function getDefaultDatabaseForConfiguration(): string {
8787
NO_PRE_CONFIGURED_DRIVER
8888
);
8989

90-
return defaultDatabaseForConfiguration ? defaultDatabaseForConfiguration : NO_PRE_CONFIGURED_DRIVER;
90+
return defaultDatabaseForConfiguration || NO_PRE_CONFIGURED_DRIVER;
9191
}
9292

9393
/**

src/liquibaseCommandsUtilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export async function openIndexHtmlAfterCommandExecution(dialogValues: DialogVal
109109
export async function changeAndEmptyOutputDirectory(dialogValues: DialogValues): Promise<void> {
110110
const folder = dialogValues.inputValues.get(folderSelectionName)?.[0];
111111

112-
if (folder && folder.includes(os.tmpdir())) {
112+
if (folder?.includes(os.tmpdir())) {
113113
const propertyFile = dialogValues.inputValues.get(PROPERTY_FILE)?.[0];
114114

115115
let configurationName = "db-doc";

0 commit comments

Comments
 (0)