-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
index.ts
181 lines (167 loc) · 5.82 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import is from '@sindresorhus/is';
import { ERROR } from 'bunyan';
import fs from 'fs-extra';
import semver from 'semver';
import upath from 'upath';
import * as configParser from '../../config';
import { mergeChildConfig } from '../../config';
import { GlobalConfig } from '../../config/global';
import { resolveConfigPresets } from '../../config/presets';
import { validateConfigSecrets } from '../../config/secrets';
import type {
AllConfig,
RenovateConfig,
RenovateRepository,
} from '../../config/types';
import { CONFIG_PRESETS_INVALID } from '../../constants/error-messages';
import { pkg } from '../../expose.cjs';
import { getProblems, logger, setMeta } from '../../logger';
import * as hostRules from '../../util/host-rules';
import * as repositoryWorker from '../repository';
import { autodiscoverRepositories } from './autodiscover';
import { parseConfigs } from './config/parse';
import { globalFinalize, globalInitialize } from './initialize';
import { Limit, isLimitReached } from './limits';
export async function getRepositoryConfig(
globalConfig: RenovateConfig,
repository: RenovateRepository
): Promise<RenovateConfig> {
const repoConfig = configParser.mergeChildConfig(
globalConfig,
is.string(repository) ? { repository } : repository
);
const platform = GlobalConfig.get('platform');
repoConfig.localDir = upath.join(
repoConfig.baseDir,
`./repos/${platform}/${repoConfig.repository}`
);
await fs.ensureDir(repoConfig.localDir);
delete repoConfig.baseDir;
return configParser.filterConfig(repoConfig, 'repository');
}
function getGlobalConfig(): Promise<RenovateConfig> {
return parseConfigs(process.env, process.argv);
}
function haveReachedLimits(): boolean {
if (isLimitReached(Limit.Commits)) {
logger.info('Max commits created for this run.');
return true;
}
return false;
}
/* istanbul ignore next */
function checkEnv(): void {
const range = pkg.engines!.node!;
const rangeNext = pkg['engines-next']?.node;
if (process.release?.name !== 'node' || !process.versions?.node) {
logger.warn(
{ release: process.release, versions: process.versions },
'Unknown node environment detected.'
);
} else if (!semver.satisfies(process.versions?.node, range)) {
logger.error(
{ versions: process.versions, range },
'Unsupported node environment detected. Please update your node version.'
);
} else if (
rangeNext &&
!semver.satisfies(process.versions?.node, rangeNext)
) {
logger.warn(
{ versions: process.versions },
`Please upgrade the version of Node.js used to run Renovate to satisfy "${rangeNext}". Support for your current version will be removed in Renovate's next major release.`
);
}
}
export async function validatePresets(config: AllConfig): Promise<void> {
logger.debug('validatePresets()');
try {
await resolveConfigPresets(config);
} catch (err) /* istanbul ignore next */ {
logger.error({ err }, CONFIG_PRESETS_INVALID);
throw new Error(CONFIG_PRESETS_INVALID);
}
}
export async function resolveGlobalExtends(
globalExtends: string[]
): Promise<AllConfig> {
try {
// Make a "fake" config to pass to resolveConfigPresets and resolve globalPresets
const config = { extends: globalExtends };
const resolvedConfig = await resolveConfigPresets(config);
return resolvedConfig;
} catch (err) {
logger.error({ err }, 'Error resolving config preset');
throw new Error(CONFIG_PRESETS_INVALID);
}
}
export async function start(): Promise<number> {
let config: AllConfig;
try {
// read global config from file, env and cli args
config = await getGlobalConfig();
if (config?.globalExtends) {
// resolve global presets immediately
config = mergeChildConfig(
config,
await resolveGlobalExtends(config.globalExtends)
);
}
// initialize all submodules
config = await globalInitialize(config);
// Set platform and endpoint in case local presets are used
GlobalConfig.set({ platform: config.platform, endpoint: config.endpoint });
await validatePresets(config);
checkEnv();
// validate secrets. Will throw and abort if invalid
validateConfigSecrets(config);
// autodiscover repositories (needs to come after platform initialization)
config = await autodiscoverRepositories(config);
if (is.nonEmptyString(config.writeDiscoveredRepos)) {
const content = JSON.stringify(config.repositories);
await fs.writeFile(config.writeDiscoveredRepos, content);
logger.info(
`Written discovered repositories to ${config.writeDiscoveredRepos}`
);
return 0;
}
// Iterate through repositories sequentially
for (const repository of config.repositories!) {
if (haveReachedLimits()) {
break;
}
const repoConfig = await getRepositoryConfig(config, repository);
if (repoConfig.hostRules) {
logger.debug('Reinitializing hostRules for repo');
hostRules.clear();
repoConfig.hostRules.forEach((rule) => hostRules.add(rule));
repoConfig.hostRules = [];
}
await repositoryWorker.renovateRepository(repoConfig);
setMeta({});
}
} catch (err) /* istanbul ignore next */ {
if (err.message.startsWith('Init: ')) {
logger.fatal(err.message.substring(6));
} else {
logger.fatal({ err }, `Fatal error: ${String(err.message)}`);
}
if (!config!) {
// return early if we can't parse config options
logger.debug(`Missing config`);
return 2;
}
} finally {
await globalFinalize(config!);
logger.debug(`Renovate exiting`);
}
const loggerErrors = getProblems().filter((p) => p.level >= ERROR);
if (loggerErrors.length) {
logger.info(
{ loggerErrors },
'Renovate is exiting with a non-zero code due to the following logged errors'
);
return 1;
}
return 0;
}