Skip to content

Commit f4993c6

Browse files
Update Advanced Installer updates INI URL and refactor version handling
The URL for the `updates.ini` file has been changed to `updates-cicd-integration.ini` to resolve issues where the previous URL was marked as malicious on some systems. Additionally, the version retrieval and validation logic has been refactored from standalone functions into an `AdvinstVersions` class for improved code organization, maintainability, and caching.
1 parent e2194c8 commit f4993c6

4 files changed

Lines changed: 63 additions & 85 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
Changelog of Advanced Installer GitHub action
44

5+
## v2.0.3
6+
Bugs:
7+
* Changed updates INI download url. This fixes a problem on some machines which marked the ini file as malicious.
8+
59
## v2.0.2
610
* Update to node24
711

@@ -26,4 +30,3 @@ Changelog of Advanced Installer GitHub action
2630
* Deploy and register Advanced Installer on runner
2731
* Enable PowerShell automation
2832
* Configure and build an Advanced Installer project (.AIP)
29-

__tests__/advinstversions.test.ts

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,50 @@
11
import * as toolCache from '@actions/tool-cache';
2-
import {
3-
getLatest,
4-
getAll,
5-
getMinAllowedAdvinstVersion,
6-
versionIsDeprecated
7-
} from '../src/advinstversions';
2+
import {AdvinstVersions} from '../src/advinstversions';
83
import path from 'path';
94

105
jest.mock('@actions/tool-cache');
116
const mockToolCache: jest.Mocked<typeof toolCache> = <
127
jest.Mocked<typeof toolCache>
138
>toolCache;
149

10+
const testIniPath = path.resolve(__dirname, './__data__/updates.ini');
11+
1512
test('Test getLatest', async () => {
16-
mockToolCache.downloadTool.mockResolvedValue(
17-
path.resolve(__dirname, './__data__/updates.ini')
18-
);
19-
const latest = await getLatest();
13+
mockToolCache.downloadTool.mockResolvedValue(testIniPath);
14+
const latest = await new AdvinstVersions().getLatest();
2015
expect(latest).toBe('21.0.1');
2116
});
2217

2318
test('Test getAll', async () => {
24-
mockToolCache.downloadTool.mockResolvedValue(
25-
path.resolve(__dirname, './__data__/updates.ini')
26-
);
27-
const versions = await getAll();
19+
mockToolCache.downloadTool.mockResolvedValue(testIniPath);
20+
const versions = await new AdvinstVersions().getAll();
2821
expect(versions).toEqual(
2922
expect.arrayContaining(['21.0.1', '21.0', '19.0', '18.9.1', '18.9', '16.0'])
3023
);
3124
});
3225

3326
test('Test getMinAllowedAdvinstVersion', async () => {
3427
jest.useFakeTimers().setSystemTime(new Date('2023-09-01'));
35-
36-
mockToolCache.downloadTool.mockResolvedValue(
37-
path.resolve(__dirname, './__data__/updates.ini')
38-
);
39-
const ver = await getMinAllowedAdvinstVersion();
28+
mockToolCache.downloadTool.mockResolvedValue(testIniPath);
29+
const ver = await new AdvinstVersions().getMinAllowedAdvinstVersion();
4030
expect(ver).toBe('18.6.1');
4131
jest.useRealTimers();
4232
});
4333

4434
test('Test versionIsDeprecated', async () => {
4535
jest.useFakeTimers().setSystemTime(new Date('2023-09-01'));
36+
mockToolCache.downloadTool.mockResolvedValue(testIniPath);
4637

47-
mockToolCache.downloadTool.mockResolvedValue(
48-
path.resolve(__dirname, './__data__/updates.ini')
49-
);
50-
let [isDeprecated, minAllowedVer] = await versionIsDeprecated('16.0');
38+
const versions = new AdvinstVersions();
39+
let [isDeprecated, minAllowedVer] = await versions.versionIsDeprecated('16.0');
5140
expect(minAllowedVer).toBe('18.6.1');
5241
expect(isDeprecated).toBe(true);
5342

54-
[isDeprecated, minAllowedVer] = await versionIsDeprecated('18.9');
43+
[isDeprecated, minAllowedVer] = await versions.versionIsDeprecated('18.9');
5544
expect(minAllowedVer).toBe('18.6.1');
5645
expect(isDeprecated).toBe(false);
5746

58-
[isDeprecated, minAllowedVer] = await versionIsDeprecated('18.6.1');
47+
[isDeprecated, minAllowedVer] = await versions.versionIsDeprecated('18.6.1');
5948
expect(minAllowedVer).toBe('18.6.1');
6049
expect(isDeprecated).toBe(false);
6150

src/advinstversions.ts

Lines changed: 41 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,77 +6,62 @@ import {getVariable} from './utils';
66

77
const advinstIniUrlVar = 'advancedinstaller_ini_url';
88
const DEFAULT_ADVINST_INI_URL =
9-
'https://www.advancedinstaller.com/downloads/updates.ini';
9+
'https://www.advancedinstaller.com/downloads/updates-cicd-integration.ini';
1010

11-
export async function getLatest(): Promise<string> {
12-
const versions = await getAll();
13-
return versions[0];
14-
}
11+
export class AdvinstVersions {
12+
private _ini: ConfigIniParser | null = null;
1513

16-
export async function getAll(): Promise<string[]> {
17-
const versionsFileContent = await _getUpdatesFileContent();
14+
private async _getIni(): Promise<ConfigIniParser> {
15+
if (!this._ini) {
16+
const url = getVariable(advinstIniUrlVar) || DEFAULT_ADVINST_INI_URL;
17+
const filePath = await toolCache.downloadTool(url);
18+
const content = _readTextFileWithDetectedEncoding(filePath);
19+
const ini = new ConfigIniParser();
20+
ini.parse(content);
21+
if (ini.sections().length === 0) {
22+
throw new Error('Invalid updated config file');
23+
}
24+
this._ini = ini;
25+
}
26+
return this._ini;
27+
}
1828

19-
const ini = new ConfigIniParser();
20-
ini.parse(versionsFileContent);
21-
const sections = ini.sections();
22-
if (sections.length === 0) {
23-
throw new Error('Invalid updated config file');
29+
async getAll(): Promise<string[]> {
30+
const ini = await this._getIni();
31+
return ini.sections().map(s => ini.get(s, 'ProductVersion'));
2432
}
25-
const versions: string[] = [];
26-
for (const section of sections) {
27-
versions.push(ini.get(section, 'ProductVersion'));
33+
34+
async getLatest(): Promise<string> {
35+
return (await this.getAll())[0];
2836
}
29-
return versions;
30-
}
3137

32-
export async function getMinAllowedAdvinstVersion(): Promise<string | null> {
33-
const RELEASE_INTERVAL_MONTHS = 24;
38+
async getMinAllowedAdvinstVersion(): Promise<string | null> {
39+
const RELEASE_INTERVAL_MONTHS = 24;
40+
const minReleaseDate = new Date();
41+
minReleaseDate.setMonth(minReleaseDate.getMonth() - RELEASE_INTERVAL_MONTHS);
3442

35-
const minReleaseDate = new Date();
36-
minReleaseDate.setMonth(minReleaseDate.getMonth() - RELEASE_INTERVAL_MONTHS);
43+
const ini = await this._getIni();
44+
const section = ini.sections().find(s => {
45+
const [day, month, year] = ini.get(s, 'ReleaseDate').split('/');
46+
return minReleaseDate > new Date(`${year}-${month}-${day}`);
47+
});
3748

38-
const versionsFileContent = await _getUpdatesFileContent();
39-
const ini = new ConfigIniParser();
40-
ini.parse(versionsFileContent);
41-
const sections = ini.sections();
42-
if (sections.length === 0) {
43-
throw new Error('Invalid updated config file');
49+
return section ? ini.get(section, 'ProductVersion') : null;
4450
}
4551

46-
const r = ini.sections().find(s => {
47-
const [day, month, year] = ini.get(s, 'ReleaseDate').split('/');
48-
const releaseDate = new Date(`${year}-${month}-${day}`);
49-
return minReleaseDate > releaseDate;
50-
});
51-
52-
if (!r) {
53-
return null;
52+
async versionIsDeprecated(
53+
version: string
54+
): Promise<[boolean, string | null]> {
55+
const minAllowedVer = await this.getMinAllowedAdvinstVersion();
56+
const isDeprecated =
57+
minAllowedVer !== null && compareVersions(version, minAllowedVer) === -1;
58+
return [isDeprecated, minAllowedVer];
5459
}
55-
return ini.get(r, 'ProductVersion');
56-
}
57-
58-
export async function versionIsDeprecated(
59-
version: string
60-
): Promise<[boolean, string | null]> {
61-
const minAllowedVer = await getMinAllowedAdvinstVersion();
62-
const isDeprecated: boolean =
63-
minAllowedVer !== null && compareVersions(version, minAllowedVer) === -1;
64-
return [isDeprecated, minAllowedVer];
65-
}
66-
67-
async function _getUpdatesFileContent(): Promise<string> {
68-
const advinstIniUrl =
69-
getVariable(advinstIniUrlVar) || DEFAULT_ADVINST_INI_URL;
70-
const updatesFile: string = await toolCache.downloadTool(advinstIniUrl);
71-
return _readTextFileWithDetectedEncoding(updatesFile);
7260
}
7361

7462
function _readTextFileWithDetectedEncoding(filePath: string): string {
7563
const raw = fs.readFileSync(filePath);
76-
const encoding = _hasUtf16LeBom(raw) ? 'utf16le' : 'utf8';
64+
const encoding = raw.length >= 2 && raw[0] === 0xff && raw[1] === 0xfe ? 'utf16le' : 'utf8';
7765
return raw.toString(encoding);
7866
}
7967

80-
function _hasUtf16LeBom(raw: Buffer): boolean {
81-
return raw.length >= 2 && raw[0] === 0xff && raw[1] === 0xfe;
82-
}

src/main.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as core from '@actions/core';
2-
import {getLatest, versionIsDeprecated} from './advinstversions';
2+
import {AdvinstVersions} from './advinstversions';
33
import {ADVINST_VER_DEPRECATION_ERROR} from './messages';
44
import {AdvinstBuilder} from './advinstbuilder';
55
import {AdvinstTool} from './advinsttool';
@@ -11,14 +11,15 @@ async function run(): Promise<void> {
1111
if (!isWindows()) {
1212
throw new Error('This action is only supported on Windows platforms');
1313
}
14-
const version = core.getInput('advinst-version') || (await getLatest());
14+
const versions = new AdvinstVersions();
15+
const version = core.getInput('advinst-version') || (await versions.getLatest());
1516
core.debug(`Advinst version: ${version}`);
1617
const license = core.getInput('advinst-license');
1718
core.debug(`Advinst license: ${license}`);
1819
const enable_com = core.getInput('advinst-enable-automation');
1920
core.debug(`Advinst enable com: ${enable_com}`);
2021

21-
const [isDeprecated, minAllowedVer] = await versionIsDeprecated(version);
22+
const [isDeprecated, minAllowedVer] = await versions.versionIsDeprecated(version);
2223
if (isDeprecated) {
2324
throw new Error(
2425
util.format(ADVINST_VER_DEPRECATION_ERROR, minAllowedVer, version)

0 commit comments

Comments
 (0)