renovate 42.68.4 → 42.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,70 @@
1
+ interface QuotedValue {
2
+ value: string;
3
+ quote: string;
4
+ }
5
+ export declare function parseQuote(input: string): QuotedValue;
6
+ /**
7
+ * Docker container:
8
+ * - `docker://image:tag`
9
+ * - `docker://image@digest`
10
+ * - `docker://image:tag@digest`
11
+ */
12
+ export interface DockerReference {
13
+ kind: 'docker';
14
+ image: string;
15
+ tag?: string;
16
+ digest?: string;
17
+ originalRef: string;
18
+ }
19
+ /**
20
+ * Local file or directory:
21
+ * - `./path/to/action`
22
+ * - `./.github/workflows/main.yml`
23
+ */
24
+ export interface LocalReference {
25
+ kind: 'local';
26
+ path: string;
27
+ }
28
+ /**
29
+ * Repository:
30
+ * - `owner/repo[/path]@ref`
31
+ * - `https://host/owner/repo[/path]@ref`
32
+ */
33
+ export interface RepositoryReference {
34
+ kind: 'repository';
35
+ hostname: string;
36
+ isExplicitHostname: boolean;
37
+ owner: string;
38
+ repo: string;
39
+ path?: string;
40
+ ref: string;
41
+ }
42
+ export type ActionReference = DockerReference | LocalReference | RepositoryReference;
43
+ export interface ParsedUsesLine {
44
+ /** The whitespace before "uses:" */
45
+ indentation: string;
46
+ /** The `uses:` (and optional `-`) part */
47
+ usesPrefix: string;
48
+ /** The raw value part, potentially quoted (e.g. `actions/checkout@v2`) */
49
+ replaceString: string;
50
+ /** Whitespace between value and `#` */
51
+ commentPrecedingWhitespace: string;
52
+ /** The full comment including `#` */
53
+ commentString: string;
54
+ actionRef: ActionReference | null;
55
+ commentData: CommentData;
56
+ /** The quote char used (' or " or empty) */
57
+ quote: string;
58
+ }
59
+ export declare function isSha(str: string): boolean;
60
+ export declare function isShortSha(str: string): boolean;
61
+ export declare function parseActionReference(uses: string): ActionReference | null;
62
+ export interface CommentData {
63
+ pinnedVersion?: string;
64
+ ratchetExclude?: boolean;
65
+ matchedString?: string;
66
+ index?: number;
67
+ }
68
+ export declare function parseComment(commentBody: string): CommentData;
69
+ export declare function parseUsesLine(line: string): ParsedUsesLine | null;
70
+ export {};
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseQuote = parseQuote;
4
+ exports.isSha = isSha;
5
+ exports.isShortSha = isShortSha;
6
+ exports.parseActionReference = parseActionReference;
7
+ exports.parseComment = parseComment;
8
+ exports.parseUsesLine = parseUsesLine;
9
+ const tslib_1 = require("tslib");
10
+ const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
11
+ const regex_1 = require("../../../util/regex");
12
+ function splitFirstFrom(str, sep, start) {
13
+ const idx = str.indexOf(sep, start);
14
+ if (idx === -1) {
15
+ return null;
16
+ }
17
+ return [str.slice(0, idx), str.slice(idx + sep.length)];
18
+ }
19
+ function splitFirst(str, sep) {
20
+ return splitFirstFrom(str, sep, 0);
21
+ }
22
+ function parseQuote(input) {
23
+ const trimmed = input.trim();
24
+ const first = trimmed[0];
25
+ const last = trimmed[trimmed.length - 1];
26
+ if (trimmed.length >= 2 &&
27
+ first === last &&
28
+ (first === '"' || first === "'")) {
29
+ return { value: trimmed.slice(1, -1), quote: first };
30
+ }
31
+ return { value: trimmed, quote: '' };
32
+ }
33
+ const shaRe = (0, regex_1.regEx)(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);
34
+ const shaShortRe = (0, regex_1.regEx)(/^[a-f0-9]{6,7}$/);
35
+ function isSha(str) {
36
+ return shaRe.test(str);
37
+ }
38
+ function isShortSha(str) {
39
+ return shaShortRe.test(str);
40
+ }
41
+ const DOCKER_PREFIX = 'docker://';
42
+ function parseDockerReference(input) {
43
+ const originalRef = input.slice(DOCKER_PREFIX.length);
44
+ if (!originalRef) {
45
+ return null;
46
+ }
47
+ const digestParts = splitFirst(originalRef, '@');
48
+ if (digestParts) {
49
+ const [image, digest] = digestParts;
50
+ return { kind: 'docker', image, digest, originalRef };
51
+ }
52
+ // Find tag: look for first colon after last slash (to avoid matching port in registry)
53
+ const lastSlashIndex = originalRef.lastIndexOf('/');
54
+ const searchStart = lastSlashIndex === -1 ? 0 : lastSlashIndex + 1;
55
+ const tagParts = splitFirstFrom(originalRef, ':', searchStart);
56
+ if (tagParts) {
57
+ const [image, tag] = tagParts;
58
+ return { kind: 'docker', image, tag, originalRef };
59
+ }
60
+ return { kind: 'docker', image: originalRef, originalRef };
61
+ }
62
+ const repositoryActionRegex = (0, regex_1.regEx)(/^(?:https:\/\/(?<hostname>[^/]+)\/)?(?<owner>[^/]+)\/(?<repo>[^/]+)(?:\/(?<path>.+?))?@(?<ref>.+)$/);
63
+ function parseRepositoryReference(input) {
64
+ const match = repositoryActionRegex.exec(input);
65
+ if (!match?.groups) {
66
+ return null;
67
+ }
68
+ const { owner, repo, path, ref } = match.groups;
69
+ let { hostname } = match.groups;
70
+ let isExplicitHostname = true;
71
+ if (is_1.default.undefined(hostname)) {
72
+ hostname = 'github.com';
73
+ isExplicitHostname = false;
74
+ }
75
+ return {
76
+ kind: 'repository',
77
+ hostname,
78
+ isExplicitHostname,
79
+ owner,
80
+ repo,
81
+ path,
82
+ ref,
83
+ };
84
+ }
85
+ function parseActionReference(uses) {
86
+ if (!uses) {
87
+ return null;
88
+ }
89
+ if (uses.startsWith(DOCKER_PREFIX)) {
90
+ return parseDockerReference(uses);
91
+ }
92
+ if (uses.startsWith('./') || uses.startsWith('../')) {
93
+ return { kind: 'local', path: uses };
94
+ }
95
+ return parseRepositoryReference(uses);
96
+ }
97
+ // Matches version strings with optional prefixes, e.g.:
98
+ // - "@v1.2.3", "v1.2.3", "1.2.3"
99
+ // - "renovate: pin @v1.2.3", "tag=v1.2.3"
100
+ // - "ratchet:owner/repo@v1.2.3"
101
+ // - "stable/v1.2.3", "stable-v1.2.3"
102
+ const pinnedVersionRe = (0, regex_1.regEx)(/^\s*(?:(?:renovate\s*:\s*)?(?:pin\s+|tag\s*=\s*)?|(?:ratchet:[\w-]+\/[.\w-]+))?@?(?<version>([\w-]*[-/])?v?\d+(?:\.\d+(?:\.\d+)?)?)/);
103
+ function parseComment(commentBody) {
104
+ const trimmed = commentBody.trim();
105
+ if (trimmed === 'ratchet:exclude') {
106
+ return { ratchetExclude: true };
107
+ }
108
+ // We use commentBody (with leading spaces) to get the correct index relative to the comment start
109
+ const match = pinnedVersionRe.exec(commentBody);
110
+ if (match?.groups?.version) {
111
+ return {
112
+ pinnedVersion: match.groups.version,
113
+ matchedString: match[0],
114
+ index: match.index,
115
+ };
116
+ }
117
+ return {};
118
+ }
119
+ const usesLineRegex = (0, regex_1.regEx)(/^(?<prefix>\s+(?:-\s+)?uses\s*:\s*)(?<remainder>.+)$/);
120
+ function parseUsesLine(line) {
121
+ const match = usesLineRegex.exec(line);
122
+ if (!match?.groups) {
123
+ return null;
124
+ }
125
+ const { prefix, remainder } = match.groups;
126
+ if (remainder.startsWith('#')) {
127
+ return null;
128
+ }
129
+ const indentation = prefix.slice(0, prefix.indexOf('uses'));
130
+ // We look for ' #' to determine where the comment starts.
131
+ // This is a safe heuristic for valid "uses" values which cannot contain spaces.
132
+ const commentIndex = remainder.indexOf(' #');
133
+ // No comment case
134
+ if (commentIndex === -1) {
135
+ const { value, quote } = parseQuote(remainder);
136
+ return {
137
+ indentation,
138
+ usesPrefix: prefix,
139
+ replaceString: remainder.trim(),
140
+ commentPrecedingWhitespace: '',
141
+ commentString: '',
142
+ actionRef: parseActionReference(value),
143
+ commentData: {},
144
+ quote,
145
+ };
146
+ }
147
+ // Has comment: split value and comment
148
+ const rawValuePart = remainder.slice(0, commentIndex);
149
+ const commentPart = remainder.slice(commentIndex + 1); // starts at #
150
+ // Calculate whitespace between value and #
151
+ const partBeforeHash = remainder.slice(0, commentIndex + 1);
152
+ const commentPrecedingWhitespace = partBeforeHash.slice(partBeforeHash.trimEnd().length);
153
+ const { value, quote } = parseQuote(rawValuePart);
154
+ // commentPart always starts with '#' since we found ' #' and sliced after the space
155
+ const cleanCommentBody = commentPart.slice(1);
156
+ return {
157
+ indentation,
158
+ usesPrefix: prefix,
159
+ replaceString: rawValuePart.trim(),
160
+ commentPrecedingWhitespace,
161
+ commentString: commentPart,
162
+ actionRef: parseActionReference(value),
163
+ commentData: parseComment(cleanCommentBody),
164
+ quote,
165
+ };
166
+ }
167
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../../lib/modules/manager/github-actions/parse.ts"],"names":[],"mappings":"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","sourcesContent":["import is from '@sindresorhus/is';\nimport { regEx } from '../../../util/regex';\n\nfunction splitFirstFrom(\n str: string,\n sep: string,\n start: number,\n): [string, string] | null {\n const idx = str.indexOf(sep, start);\n if (idx === -1) {\n return null;\n }\n return [str.slice(0, idx), str.slice(idx + sep.length)];\n}\n\nfunction splitFirst(str: string, sep: string): [string, string] | null {\n return splitFirstFrom(str, sep, 0);\n}\n\ninterface QuotedValue {\n value: string;\n quote: string;\n}\n\nexport function parseQuote(input: string): QuotedValue {\n const trimmed = input.trim();\n const first = trimmed[0];\n const last = trimmed[trimmed.length - 1];\n\n if (\n trimmed.length >= 2 &&\n first === last &&\n (first === '\"' || first === \"'\")\n ) {\n return { value: trimmed.slice(1, -1), quote: first };\n }\n\n return { value: trimmed, quote: '' };\n}\n\n/**\n * Docker container:\n * - `docker://image:tag`\n * - `docker://image@digest`\n * - `docker://image:tag@digest`\n */\nexport interface DockerReference {\n kind: 'docker';\n image: string;\n tag?: string;\n digest?: string;\n originalRef: string;\n}\n\n/**\n * Local file or directory:\n * - `./path/to/action`\n * - `./.github/workflows/main.yml`\n */\nexport interface LocalReference {\n kind: 'local';\n path: string;\n}\n\n/**\n * Repository:\n * - `owner/repo[/path]@ref`\n * - `https://host/owner/repo[/path]@ref`\n */\nexport interface RepositoryReference {\n kind: 'repository';\n\n hostname: string;\n isExplicitHostname: boolean;\n\n owner: string;\n repo: string;\n path?: string;\n\n ref: string;\n}\n\nexport type ActionReference =\n | DockerReference\n | LocalReference\n | RepositoryReference;\n\nexport interface ParsedUsesLine {\n /** The whitespace before \"uses:\" */\n indentation: string;\n\n /** The `uses:` (and optional `-`) part */\n usesPrefix: string;\n\n /** The raw value part, potentially quoted (e.g. `actions/checkout@v2`) */\n replaceString: string;\n\n /** Whitespace between value and `#` */\n commentPrecedingWhitespace: string;\n\n /** The full comment including `#` */\n commentString: string;\n\n actionRef: ActionReference | null;\n commentData: CommentData;\n\n /** The quote char used (' or \" or empty) */\n quote: string;\n}\n\nconst shaRe = regEx(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);\nconst shaShortRe = regEx(/^[a-f0-9]{6,7}$/);\n\nexport function isSha(str: string): boolean {\n return shaRe.test(str);\n}\n\nexport function isShortSha(str: string): boolean {\n return shaShortRe.test(str);\n}\n\nconst DOCKER_PREFIX = 'docker://';\n\nfunction parseDockerReference(input: string): DockerReference | null {\n const originalRef = input.slice(DOCKER_PREFIX.length);\n if (!originalRef) {\n return null;\n }\n\n const digestParts = splitFirst(originalRef, '@');\n if (digestParts) {\n const [image, digest] = digestParts;\n return { kind: 'docker', image, digest, originalRef };\n }\n\n // Find tag: look for first colon after last slash (to avoid matching port in registry)\n const lastSlashIndex = originalRef.lastIndexOf('/');\n const searchStart = lastSlashIndex === -1 ? 0 : lastSlashIndex + 1;\n const tagParts = splitFirstFrom(originalRef, ':', searchStart);\n\n if (tagParts) {\n const [image, tag] = tagParts;\n return { kind: 'docker', image, tag, originalRef };\n }\n\n return { kind: 'docker', image: originalRef, originalRef };\n}\n\nconst repositoryActionRegex = regEx(\n /^(?:https:\\/\\/(?<hostname>[^/]+)\\/)?(?<owner>[^/]+)\\/(?<repo>[^/]+)(?:\\/(?<path>.+?))?@(?<ref>.+)$/,\n);\n\nfunction parseRepositoryReference(input: string): RepositoryReference | null {\n const match = repositoryActionRegex.exec(input);\n if (!match?.groups) {\n return null;\n }\n\n const { owner, repo, path, ref } = match.groups;\n\n let { hostname } = match.groups;\n let isExplicitHostname = true;\n if (is.undefined(hostname)) {\n hostname = 'github.com';\n isExplicitHostname = false;\n }\n\n return {\n kind: 'repository',\n hostname,\n isExplicitHostname,\n owner,\n repo,\n path,\n ref,\n };\n}\n\nexport function parseActionReference(uses: string): ActionReference | null {\n if (!uses) {\n return null;\n }\n\n if (uses.startsWith(DOCKER_PREFIX)) {\n return parseDockerReference(uses);\n }\n\n if (uses.startsWith('./') || uses.startsWith('../')) {\n return { kind: 'local', path: uses };\n }\n\n return parseRepositoryReference(uses);\n}\n\nexport interface CommentData {\n pinnedVersion?: string;\n ratchetExclude?: boolean;\n matchedString?: string;\n index?: number;\n}\n\n// Matches version strings with optional prefixes, e.g.:\n// - \"@v1.2.3\", \"v1.2.3\", \"1.2.3\"\n// - \"renovate: pin @v1.2.3\", \"tag=v1.2.3\"\n// - \"ratchet:owner/repo@v1.2.3\"\n// - \"stable/v1.2.3\", \"stable-v1.2.3\"\nconst pinnedVersionRe = regEx(\n /^\\s*(?:(?:renovate\\s*:\\s*)?(?:pin\\s+|tag\\s*=\\s*)?|(?:ratchet:[\\w-]+\\/[.\\w-]+))?@?(?<version>([\\w-]*[-/])?v?\\d+(?:\\.\\d+(?:\\.\\d+)?)?)/,\n);\n\nexport function parseComment(commentBody: string): CommentData {\n const trimmed = commentBody.trim();\n if (trimmed === 'ratchet:exclude') {\n return { ratchetExclude: true };\n }\n\n // We use commentBody (with leading spaces) to get the correct index relative to the comment start\n const match = pinnedVersionRe.exec(commentBody);\n if (match?.groups?.version) {\n return {\n pinnedVersion: match.groups.version,\n matchedString: match[0],\n index: match.index,\n };\n }\n\n return {};\n}\n\nconst usesLineRegex = regEx(\n /^(?<prefix>\\s+(?:-\\s+)?uses\\s*:\\s*)(?<remainder>.+)$/,\n);\n\nexport function parseUsesLine(line: string): ParsedUsesLine | null {\n const match = usesLineRegex.exec(line);\n if (!match?.groups) {\n return null;\n }\n\n const { prefix, remainder } = match.groups;\n\n if (remainder.startsWith('#')) {\n return null;\n }\n\n const indentation = prefix.slice(0, prefix.indexOf('uses'));\n\n // We look for ' #' to determine where the comment starts.\n // This is a safe heuristic for valid \"uses\" values which cannot contain spaces.\n const commentIndex = remainder.indexOf(' #');\n\n // No comment case\n if (commentIndex === -1) {\n const { value, quote } = parseQuote(remainder);\n return {\n indentation,\n usesPrefix: prefix,\n replaceString: remainder.trim(),\n commentPrecedingWhitespace: '',\n commentString: '',\n actionRef: parseActionReference(value),\n commentData: {},\n quote,\n };\n }\n\n // Has comment: split value and comment\n const rawValuePart = remainder.slice(0, commentIndex);\n const commentPart = remainder.slice(commentIndex + 1); // starts at #\n\n // Calculate whitespace between value and #\n const partBeforeHash = remainder.slice(0, commentIndex + 1);\n const commentPrecedingWhitespace = partBeforeHash.slice(\n partBeforeHash.trimEnd().length,\n );\n\n const { value, quote } = parseQuote(rawValuePart);\n // commentPart always starts with '#' since we found ' #' and sliced after the space\n const cleanCommentBody = commentPart.slice(1);\n\n return {\n indentation,\n usesPrefix: prefix,\n replaceString: rawValuePart.trim(),\n commentPrecedingWhitespace,\n commentString: commentPart,\n actionRef: parseActionReference(value),\n commentData: parseComment(cleanCommentBody),\n quote,\n };\n}\n"]}
@@ -1,3 +1,3 @@
1
1
  import type { ExecResult, RawExecOptions } from './types';
2
- export declare function exec(cmd: string, opts: RawExecOptions): Promise<ExecResult>;
2
+ export declare function exec(theCmd: string, opts: RawExecOptions): Promise<ExecResult>;
3
3
  export declare const rawExec: (cmd: string, opts: RawExecOptions) => Promise<ExecResult>;
@@ -4,6 +4,7 @@ exports.rawExec = void 0;
4
4
  exports.exec = exec;
5
5
  const is_1 = require("@sindresorhus/is");
6
6
  const execa_1 = require("execa");
7
+ const shlex_1 = require("shlex");
7
8
  const instrumentation_1 = require("../../instrumentation");
8
9
  const env_1 = require("../env");
9
10
  const sanitize_1 = require("../sanitize");
@@ -65,15 +66,27 @@ function registerDataListeners(readable, dataListeners) {
65
66
  readable.on('data', listener);
66
67
  }
67
68
  }
68
- function exec(cmd, opts) {
69
+ function exec(theCmd, opts) {
69
70
  return new Promise((resolve, reject) => {
71
+ let cmd = theCmd;
72
+ let args = [];
70
73
  const maxBuffer = opts.maxBuffer ?? 10 * 1024 * 1024; // Set default max buffer size to 10MB
71
- const cp = (0, execa_1.execa)(cmd, {
74
+ // don't use shell by default, as it leads to potential security issues
75
+ const shell = opts.shell ?? false;
76
+ // if we're not in shell mode, we need to provide the command and arguments
77
+ if (shell === false) {
78
+ const parts = (0, shlex_1.split)(cmd);
79
+ if (parts) {
80
+ cmd = parts[0];
81
+ args = parts.slice(1);
82
+ }
83
+ }
84
+ const cp = (0, execa_1.execa)(cmd, args, {
72
85
  ...opts,
73
86
  // force detached on non WIN platforms
74
87
  // https://github.com/nodejs/node/issues/21825#issuecomment-611328888
75
88
  detached: process.platform !== 'win32',
76
- shell: typeof opts.shell === 'string' ? opts.shell : true, // force shell
89
+ shell,
77
90
  });
78
91
  // handle streams
79
92
  const [stdout, stderr] = initStreamListeners(cp, {
@@ -92,14 +105,14 @@ function exec(cmd, opts) {
92
105
  }
93
106
  if (signal) {
94
107
  kill(cp, signal);
95
- reject(new exec_error_1.ExecError(`Command failed: ${cmd}\nInterrupted by ${signal}`, {
108
+ reject(new exec_error_1.ExecError(`Command failed: ${cp.spawnargs.join(' ')}\nInterrupted by ${signal}`, {
96
109
  ...rejectInfo(),
97
110
  signal,
98
111
  }));
99
112
  return;
100
113
  }
101
114
  if (code !== 0) {
102
- reject(new exec_error_1.ExecError(`Command failed: ${cmd}\n${stringify(stderr)}`, {
115
+ reject(new exec_error_1.ExecError(`Command failed: ${cp.spawnargs.join(' ')}\n${stringify(stderr)}`, {
103
116
  ...rejectInfo(),
104
117
  exitCode: code,
105
118
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../lib/util/exec/common.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport type { Readable } from 'node:stream';\nimport { isNullOrUndefined } from '@sindresorhus/is';\nimport { execa } from 'execa';\nimport { instrument } from '../../instrumentation';\nimport { getEnv } from '../env';\nimport { sanitize } from '../sanitize';\nimport type { ExecErrorData } from './exec-error';\nimport { ExecError } from './exec-error';\nimport type { DataListener, ExecResult, RawExecOptions } from './types';\n\n// https://man7.org/linux/man-pages/man7/signal.7.html#NAME\n// Non TERM/CORE signals\n// The following is step 3. in https://github.com/renovatebot/renovate/issues/16197#issuecomment-1171423890\nconst NONTERM = [\n 'SIGCHLD',\n 'SIGCLD',\n 'SIGCONT',\n 'SIGSTOP',\n 'SIGTSTP',\n 'SIGTTIN',\n 'SIGTTOU',\n 'SIGURG',\n 'SIGWINCH',\n];\n\nconst encoding = 'utf8';\n\nfunction stringify(list: Buffer[]): string {\n return Buffer.concat(list).toString(encoding);\n}\n\nfunction initStreamListeners(\n cp: ChildProcess,\n opts: RawExecOptions & { maxBuffer: number },\n): [Buffer[], Buffer[]] {\n const stdout: Buffer[] = [];\n const stderr: Buffer[] = [];\n let stdoutLen = 0;\n let stderrLen = 0;\n\n registerDataListeners(cp.stdout, opts.outputListeners?.stdout);\n registerDataListeners(cp.stderr, opts.outputListeners?.stderr);\n\n cp.stdout?.on('data', (chunk: Buffer) => {\n // process.stdout.write(data.toString());\n const len = Buffer.byteLength(chunk, encoding);\n stdoutLen += len;\n if (stdoutLen > opts.maxBuffer) {\n cp.emit('error', new Error('stdout maxBuffer exceeded'));\n } else {\n stdout.push(chunk);\n }\n });\n\n cp.stderr?.on('data', (chunk: Buffer) => {\n // process.stderr.write(data.toString());\n const len = Buffer.byteLength(chunk, encoding);\n stderrLen += len;\n if (stderrLen > opts.maxBuffer) {\n cp.emit('error', new Error('stderr maxBuffer exceeded'));\n } else {\n stderr.push(chunk);\n }\n });\n return [stdout, stderr];\n}\n\nfunction registerDataListeners(\n readable: Readable | null,\n dataListeners: DataListener[] | undefined,\n): void {\n if (isNullOrUndefined(readable) || isNullOrUndefined(dataListeners)) {\n return;\n }\n\n for (const listener of dataListeners) {\n readable.on('data', listener);\n }\n}\n\nexport function exec(cmd: string, opts: RawExecOptions): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const maxBuffer = opts.maxBuffer ?? 10 * 1024 * 1024; // Set default max buffer size to 10MB\n const cp = execa(cmd, {\n ...opts,\n // force detached on non WIN platforms\n // https://github.com/nodejs/node/issues/21825#issuecomment-611328888\n detached: process.platform !== 'win32',\n shell: typeof opts.shell === 'string' ? opts.shell : true, // force shell\n });\n\n // handle streams\n const [stdout, stderr] = initStreamListeners(cp, {\n ...opts,\n maxBuffer,\n });\n\n // handle process events\n void cp.on('error', (error) => {\n kill(cp, 'SIGTERM');\n // rethrowing, use originally emitted error message\n reject(new ExecError(error.message, rejectInfo(), error));\n });\n\n void cp.on('exit', (code: number, signal: NodeJS.Signals) => {\n if (NONTERM.includes(signal)) {\n return;\n }\n if (signal) {\n kill(cp, signal);\n reject(\n new ExecError(`Command failed: ${cmd}\\nInterrupted by ${signal}`, {\n ...rejectInfo(),\n signal,\n }),\n );\n return;\n }\n if (code !== 0) {\n reject(\n new ExecError(`Command failed: ${cmd}\\n${stringify(stderr)}`, {\n ...rejectInfo(),\n exitCode: code,\n }),\n );\n return;\n }\n resolve({\n stderr: stringify(stderr),\n stdout: stringify(stdout),\n });\n });\n\n function rejectInfo(): ExecErrorData {\n return {\n cmd: cp.spawnargs.join(' '),\n options: opts,\n stdout: stringify(stdout),\n stderr: stringify(stderr),\n };\n }\n });\n}\n\nfunction kill(cp: ChildProcess, signal: NodeJS.Signals): boolean {\n try {\n if (cp.pid && getEnv().RENOVATE_X_EXEC_GPID_HANDLE) {\n /**\n * If `pid` is negative, but not `-1`, signal shall be sent to all processes\n * (excluding an unspecified set of system processes),\n * whose process group ID (pgid) is equal to the absolute value of pid,\n * and for which the process has permission to send a signal.\n */\n return process.kill(-cp.pid, signal);\n } else {\n // destroying stdio is needed for unref to work\n // https://nodejs.org/api/child_process.html#subprocessunref\n // https://github.com/nodejs/node/blob/4d5ff25a813fd18939c9f76b17e36291e3ea15c3/lib/child_process.js#L412-L426\n cp.stderr?.destroy();\n cp.stdout?.destroy();\n cp.unref();\n return cp.kill(signal);\n }\n } catch {\n // cp is a single node tree, therefore -pid is invalid as there is no such pgid,\n return false;\n }\n}\n\nexport const rawExec: (\n cmd: string,\n opts: RawExecOptions,\n) => Promise<ExecResult> = (cmd: string, opts: RawExecOptions) =>\n instrument(`rawExec: ${sanitize(cmd)}`, () => exec(cmd, opts));\n"]}
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../lib/util/exec/common.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ChildProcess } from 'node:child_process';\nimport type { Readable } from 'node:stream';\nimport { isNullOrUndefined } from '@sindresorhus/is';\nimport { execa } from 'execa';\nimport { split } from 'shlex';\nimport { instrument } from '../../instrumentation';\nimport { getEnv } from '../env';\nimport { sanitize } from '../sanitize';\nimport type { ExecErrorData } from './exec-error';\nimport { ExecError } from './exec-error';\nimport type { DataListener, ExecResult, RawExecOptions } from './types';\n\n// https://man7.org/linux/man-pages/man7/signal.7.html#NAME\n// Non TERM/CORE signals\n// The following is step 3. in https://github.com/renovatebot/renovate/issues/16197#issuecomment-1171423890\nconst NONTERM = [\n 'SIGCHLD',\n 'SIGCLD',\n 'SIGCONT',\n 'SIGSTOP',\n 'SIGTSTP',\n 'SIGTTIN',\n 'SIGTTOU',\n 'SIGURG',\n 'SIGWINCH',\n];\n\nconst encoding = 'utf8';\n\nfunction stringify(list: Buffer[]): string {\n return Buffer.concat(list).toString(encoding);\n}\n\nfunction initStreamListeners(\n cp: ChildProcess,\n opts: RawExecOptions & { maxBuffer: number },\n): [Buffer[], Buffer[]] {\n const stdout: Buffer[] = [];\n const stderr: Buffer[] = [];\n let stdoutLen = 0;\n let stderrLen = 0;\n\n registerDataListeners(cp.stdout, opts.outputListeners?.stdout);\n registerDataListeners(cp.stderr, opts.outputListeners?.stderr);\n\n cp.stdout?.on('data', (chunk: Buffer) => {\n // process.stdout.write(data.toString());\n const len = Buffer.byteLength(chunk, encoding);\n stdoutLen += len;\n if (stdoutLen > opts.maxBuffer) {\n cp.emit('error', new Error('stdout maxBuffer exceeded'));\n } else {\n stdout.push(chunk);\n }\n });\n\n cp.stderr?.on('data', (chunk: Buffer) => {\n // process.stderr.write(data.toString());\n const len = Buffer.byteLength(chunk, encoding);\n stderrLen += len;\n if (stderrLen > opts.maxBuffer) {\n cp.emit('error', new Error('stderr maxBuffer exceeded'));\n } else {\n stderr.push(chunk);\n }\n });\n return [stdout, stderr];\n}\n\nfunction registerDataListeners(\n readable: Readable | null,\n dataListeners: DataListener[] | undefined,\n): void {\n if (isNullOrUndefined(readable) || isNullOrUndefined(dataListeners)) {\n return;\n }\n\n for (const listener of dataListeners) {\n readable.on('data', listener);\n }\n}\n\nexport function exec(\n theCmd: string,\n opts: RawExecOptions,\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n let cmd = theCmd;\n let args: string[] = [];\n const maxBuffer = opts.maxBuffer ?? 10 * 1024 * 1024; // Set default max buffer size to 10MB\n\n // don't use shell by default, as it leads to potential security issues\n const shell = opts.shell ?? false;\n // if we're not in shell mode, we need to provide the command and arguments\n if (shell === false) {\n const parts = split(cmd);\n if (parts) {\n cmd = parts[0];\n args = parts.slice(1);\n }\n }\n\n const cp = execa(cmd, args, {\n ...opts,\n // force detached on non WIN platforms\n // https://github.com/nodejs/node/issues/21825#issuecomment-611328888\n detached: process.platform !== 'win32',\n shell,\n });\n\n // handle streams\n const [stdout, stderr] = initStreamListeners(cp, {\n ...opts,\n maxBuffer,\n });\n\n // handle process events\n void cp.on('error', (error) => {\n kill(cp, 'SIGTERM');\n // rethrowing, use originally emitted error message\n reject(new ExecError(error.message, rejectInfo(), error));\n });\n\n void cp.on('exit', (code: number, signal: NodeJS.Signals) => {\n if (NONTERM.includes(signal)) {\n return;\n }\n if (signal) {\n kill(cp, signal);\n reject(\n new ExecError(\n `Command failed: ${cp.spawnargs.join(' ')}\\nInterrupted by ${signal}`,\n {\n ...rejectInfo(),\n signal,\n },\n ),\n );\n return;\n }\n if (code !== 0) {\n reject(\n new ExecError(\n `Command failed: ${cp.spawnargs.join(' ')}\\n${stringify(stderr)}`,\n {\n ...rejectInfo(),\n exitCode: code,\n },\n ),\n );\n return;\n }\n resolve({\n stderr: stringify(stderr),\n stdout: stringify(stdout),\n });\n });\n\n function rejectInfo(): ExecErrorData {\n return {\n cmd: cp.spawnargs.join(' '),\n options: opts,\n stdout: stringify(stdout),\n stderr: stringify(stderr),\n };\n }\n });\n}\n\nfunction kill(cp: ChildProcess, signal: NodeJS.Signals): boolean {\n try {\n if (cp.pid && getEnv().RENOVATE_X_EXEC_GPID_HANDLE) {\n /**\n * If `pid` is negative, but not `-1`, signal shall be sent to all processes\n * (excluding an unspecified set of system processes),\n * whose process group ID (pgid) is equal to the absolute value of pid,\n * and for which the process has permission to send a signal.\n */\n return process.kill(-cp.pid, signal);\n } else {\n // destroying stdio is needed for unref to work\n // https://nodejs.org/api/child_process.html#subprocessunref\n // https://github.com/nodejs/node/blob/4d5ff25a813fd18939c9f76b17e36291e3ea15c3/lib/child_process.js#L412-L426\n cp.stderr?.destroy();\n cp.stdout?.destroy();\n cp.unref();\n return cp.kill(signal);\n }\n } catch {\n // cp is a single node tree, therefore -pid is invalid as there is no such pgid,\n return false;\n }\n}\n\nexport const rawExec: (\n cmd: string,\n opts: RawExecOptions,\n) => Promise<ExecResult> = (cmd: string, opts: RawExecOptions) =>\n instrument(`rawExec: ${sanitize(cmd)}`, () => exec(cmd, opts));\n"]}
@@ -44,4 +44,5 @@ export interface ExecOptions {
44
44
  ignoreStdout?: boolean;
45
45
  maxBuffer?: number | undefined;
46
46
  timeout?: number | undefined;
47
+ shell?: boolean | string | undefined;
47
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../lib/util/exec/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Options as ExecaOptions } from 'execa';\n\nexport interface ToolConstraint {\n toolName: string;\n constraint?: string | null;\n}\n\nexport interface ToolConfig {\n datasource: string;\n extractVersion?: string;\n packageName: string;\n hash?: boolean;\n versioning: string;\n}\n\nexport type Opt<T> = T | null | undefined;\n\nexport type VolumesPair = [string, string];\nexport type VolumeOption = Opt<string | VolumesPair>;\n\nexport interface DockerOptions {\n volumes?: Opt<VolumeOption[]>;\n envVars?: Opt<Opt<string>[]>;\n cwd?: Opt<string>;\n}\n\nexport type DataListener = (chunk: any) => void;\nexport interface OutputListeners {\n stdout?: DataListener[];\n stderr?: DataListener[];\n}\n\nexport interface RawExecOptions extends ExecaOptions {\n maxBuffer?: number | undefined;\n cwd?: string;\n outputListeners?: OutputListeners;\n}\n\nexport interface ExecResult {\n stdout: string;\n stderr: string;\n}\n\nexport type ExtraEnv<T = unknown> = Record<string, T>;\n\nexport interface ExecOptions {\n cwd?: string;\n cwdFile?: string;\n env?: Opt<ExtraEnv>;\n extraEnv?: Opt<ExtraEnv>;\n docker?: Opt<DockerOptions>;\n toolConstraints?: Opt<ToolConstraint[]>;\n preCommands?: Opt<string[]>;\n ignoreStdout?: boolean;\n // Following are pass-through to child process\n maxBuffer?: number | undefined;\n timeout?: number | undefined;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../lib/util/exec/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Options as ExecaOptions } from 'execa';\n\nexport interface ToolConstraint {\n toolName: string;\n constraint?: string | null;\n}\n\nexport interface ToolConfig {\n datasource: string;\n extractVersion?: string;\n packageName: string;\n hash?: boolean;\n versioning: string;\n}\n\nexport type Opt<T> = T | null | undefined;\n\nexport type VolumesPair = [string, string];\nexport type VolumeOption = Opt<string | VolumesPair>;\n\nexport interface DockerOptions {\n volumes?: Opt<VolumeOption[]>;\n envVars?: Opt<Opt<string>[]>;\n cwd?: Opt<string>;\n}\n\nexport type DataListener = (chunk: any) => void;\nexport interface OutputListeners {\n stdout?: DataListener[];\n stderr?: DataListener[];\n}\n\nexport interface RawExecOptions extends ExecaOptions {\n maxBuffer?: number | undefined;\n cwd?: string;\n outputListeners?: OutputListeners;\n}\n\nexport interface ExecResult {\n stdout: string;\n stderr: string;\n}\n\nexport type ExtraEnv<T = unknown> = Record<string, T>;\n\nexport interface ExecOptions {\n cwd?: string;\n cwdFile?: string;\n env?: Opt<ExtraEnv>;\n extraEnv?: Opt<ExtraEnv>;\n docker?: Opt<DockerOptions>;\n toolConstraints?: Opt<ToolConstraint[]>;\n preCommands?: Opt<string[]>;\n ignoreStdout?: boolean;\n // Following are pass-through to child process\n maxBuffer?: number | undefined;\n timeout?: number | undefined;\n shell?: boolean | string | undefined;\n}\n"]}
@@ -82,6 +82,9 @@ async function postUpgradeCommandsExecutor(filteredUpgradeCommands, config) {
82
82
  try {
83
83
  logger_1.logger.trace({ cmd: compiledCmd }, 'Executing post-upgrade task');
84
84
  const execOpts = {
85
+ // WARNING to self-hosted administrators: always run post-upgrade commands with `shell` mode on, which has the risk of arbitrary environment variable access or additional command execution
86
+ // It is very likely this will be susceptible to these risks, even if you allowlist (via `allowedCommands`), as there may be special characters included in the given commands that can be leveraged here
87
+ shell: global_1.GlobalConfig.get('allowShellExecutorForPostUpgradeCommands', true),
85
88
  cwd: (0, is_1.isNonEmptyString)(workingDir)
86
89
  ? workingDir
87
90
  : global_1.GlobalConfig.get('localDir'),
@@ -1 +1 @@
1
- {"version":3,"file":"execute-post-upgrade-commands.js","sourceRoot":"","sources":["../../../../../lib/workers/repository/update/branch/execute-post-upgrade-commands.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'crypto';\n// TODO #22198\nimport { isArray, isNonEmptyArray, isNonEmptyString } from '@sindresorhus/is';\nimport upath from 'upath';\nimport { mergeChildConfig } from '../../../../config';\nimport { GlobalConfig } from '../../../../config/global';\nimport { addMeta, logger } from '../../../../logger';\nimport type { ArtifactError } from '../../../../modules/manager/types';\nimport { coerceArray } from '../../../../util/array';\nimport { exec } from '../../../../util/exec';\nimport type { ExecOptions } from '../../../../util/exec/types';\nimport {\n ensureLocalDir,\n localPathIsFile,\n outputCacheFile,\n privateCacheDir,\n readLocalFile,\n writeLocalFile,\n} from '../../../../util/fs';\nimport { getRepoStatus } from '../../../../util/git';\nimport { getGitEnvironmentVariables } from '../../../../util/git/auth';\nimport type { FileChange } from '../../../../util/git/types';\nimport { minimatch } from '../../../../util/minimatch';\nimport { regEx } from '../../../../util/regex';\nimport { sanitize } from '../../../../util/sanitize';\nimport { compile } from '../../../../util/template';\nimport type { BranchConfig, BranchUpgradeConfig } from '../../../types';\n\nexport interface PostUpgradeCommandsExecutionResult {\n updatedArtifacts: FileChange[];\n artifactErrors: ArtifactError[];\n}\n\nexport async function postUpgradeCommandsExecutor(\n filteredUpgradeCommands: BranchUpgradeConfig[],\n config: BranchConfig,\n): Promise<PostUpgradeCommandsExecutionResult> {\n let updatedArtifacts = [...(config.updatedArtifacts ?? [])];\n const artifactErrors = [...(config.artifactErrors ?? [])];\n const allowedCommands = GlobalConfig.get('allowedCommands');\n\n for (const upgrade of filteredUpgradeCommands) {\n addMeta({ dep: upgrade.depName });\n logger.trace(\n {\n tasks: upgrade.postUpgradeTasks,\n allowedCommands,\n },\n `Checking for post-upgrade tasks`,\n );\n const commands = upgrade.postUpgradeTasks?.commands;\n const dataFileTemplate = upgrade.postUpgradeTasks?.dataFileTemplate;\n const fileFilters = upgrade.postUpgradeTasks?.fileFilters ?? ['**/*'];\n if (isNonEmptyArray(commands)) {\n // Persist updated files in file system so any executed commands can see them\n const previouslyModifiedFiles =\n config.updatedPackageFiles!.concat(updatedArtifacts);\n for (const file of previouslyModifiedFiles) {\n const canWriteFile = await localPathIsFile(file.path);\n if (file.type === 'addition' && !file.isSymlink && canWriteFile) {\n let contents: Buffer | null;\n if (typeof file.contents === 'string') {\n contents = Buffer.from(file.contents);\n } else {\n contents = file.contents;\n }\n // TODO #22198\n await writeLocalFile(file.path, contents!);\n }\n }\n\n let dataFilePath: string | null = null;\n if (dataFileTemplate) {\n const dataFileContent = sanitize(\n compile(dataFileTemplate, mergeChildConfig(config, upgrade)),\n );\n logger.debug(\n { dataFileTemplate },\n 'Processed post-upgrade commands data file template.',\n );\n\n const dataFileName = `post-upgrade-data-file-${crypto.randomBytes(8).toString('hex')}.tmp`;\n dataFilePath = upath.join(privateCacheDir(), dataFileName);\n\n try {\n await outputCacheFile(dataFilePath, dataFileContent);\n\n logger.debug(\n { dataFilePath, dataFileContent },\n 'Created post-upgrade commands data file.',\n );\n } catch (error) {\n artifactErrors.push({\n stderr: sanitize(\n `Failed to create post-upgrade commands data file at ${dataFilePath}, reason: ${error.message}`,\n ),\n });\n\n dataFilePath = null;\n }\n }\n\n const workingDirTemplate = upgrade.postUpgradeTasks?.workingDirTemplate;\n let workingDir: string | null = null;\n\n if (workingDirTemplate) {\n workingDir = sanitize(\n compile(workingDirTemplate, mergeChildConfig(config, upgrade)),\n );\n await ensureLocalDir(workingDir);\n logger.trace(\n { workingDirTemplate },\n 'Processed post-upgrade commands working directory template.',\n );\n }\n\n for (const cmd of commands) {\n const compiledCmd = compile(cmd, mergeChildConfig(config, upgrade));\n if (compiledCmd !== cmd) {\n logger.debug(\n { rawCmd: cmd, compiledCmd },\n 'Post-upgrade command has been compiled',\n );\n }\n if (\n allowedCommands!.some((pattern) => regEx(pattern).test(compiledCmd))\n ) {\n try {\n logger.trace({ cmd: compiledCmd }, 'Executing post-upgrade task');\n\n const execOpts: ExecOptions = {\n cwd: isNonEmptyString(workingDir)\n ? workingDir\n : GlobalConfig.get('localDir'),\n extraEnv: getGitEnvironmentVariables(),\n };\n if (dataFilePath) {\n execOpts.env = {\n RENOVATE_POST_UPGRADE_COMMAND_DATA_FILE: dataFilePath,\n };\n }\n const execResult = await exec(compiledCmd, execOpts);\n\n logger.debug(\n { cmd: compiledCmd, ...execResult },\n 'Executed post-upgrade task',\n );\n } catch (error) {\n artifactErrors.push({\n lockFile: upgrade.packageFile,\n stderr: sanitize(error.message),\n });\n }\n } else {\n logger.warn(\n {\n cmd: compiledCmd,\n allowedCommands,\n },\n 'Post-upgrade task did not match any on allowedCommands list',\n );\n artifactErrors.push({\n lockFile: upgrade.packageFile,\n stderr: sanitize(\n `Post-upgrade command '${compiledCmd}' has not been added to the allowed list in allowedCommands`,\n ),\n });\n }\n }\n\n const status = await getRepoStatus();\n\n logger.trace({ status }, 'git status after post-upgrade tasks');\n\n logger.debug(\n {\n addedCount: status.not_added?.length,\n modifiedCount: status.modified?.length,\n deletedCount: status.deleted?.length,\n renamedCount: status.renamed?.length,\n },\n 'git status counts after post-upgrade tasks',\n );\n\n const addedOrModifiedFiles = [\n ...coerceArray(status.not_added),\n ...coerceArray(status.modified),\n ...coerceArray(status.renamed?.map((x) => x.to)),\n ];\n const changedFiles = [\n ...addedOrModifiedFiles,\n ...coerceArray(status.deleted),\n ...coerceArray(status.renamed?.map((x) => x.from)),\n ];\n\n // Check for files which were previously deleted but have been re-added without modification\n const previouslyDeletedFiles = updatedArtifacts.filter(\n (ua) => ua.type === 'deletion',\n );\n for (const previouslyDeletedFile of previouslyDeletedFiles) {\n /* v8 ignore if -- TODO: needs test */\n if (!changedFiles.includes(previouslyDeletedFile.path)) {\n logger.debug(\n { file: previouslyDeletedFile.path },\n 'Previously deleted file has been restored without modification',\n );\n updatedArtifacts = updatedArtifacts.filter(\n (ua) =>\n !(\n ua.type === 'deletion' && ua.path === previouslyDeletedFile.path\n ),\n );\n }\n }\n\n logger.trace({ addedOrModifiedFiles }, 'Added or modified files');\n logger.debug(\n `Checking ${addedOrModifiedFiles.length} added or modified files for post-upgrade changes`,\n );\n\n const fileExcludes: string[] = [];\n if (config.npmrc) {\n fileExcludes.push('.npmrc');\n }\n\n for (const relativePath of addedOrModifiedFiles) {\n if (\n fileExcludes.some((pattern) =>\n minimatch(pattern, { dot: true }).match(relativePath),\n )\n ) {\n continue;\n }\n\n let fileMatched = false;\n for (const pattern of fileFilters) {\n if (minimatch(pattern, { dot: true }).match(relativePath)) {\n fileMatched = true;\n logger.debug(\n { file: relativePath, pattern },\n 'Post-upgrade file saved',\n );\n const existingContent = await readLocalFile(relativePath);\n const existingUpdatedArtifacts = updatedArtifacts.find(\n (ua) => ua.path === relativePath,\n );\n if (existingUpdatedArtifacts?.type === 'addition') {\n existingUpdatedArtifacts.contents = existingContent;\n } else {\n updatedArtifacts.push({\n type: 'addition',\n path: relativePath,\n contents: existingContent,\n });\n }\n // If the file is deleted by a previous post-update command, remove the deletion from updatedArtifacts\n updatedArtifacts = updatedArtifacts.filter(\n (ua) => !(ua.type === 'deletion' && ua.path === relativePath),\n );\n }\n }\n if (!fileMatched) {\n logger.debug(\n { file: relativePath },\n 'Post-upgrade file did not match any file filters',\n );\n }\n }\n\n for (const relativePath of coerceArray(status.deleted)) {\n for (const pattern of fileFilters) {\n if (minimatch(pattern, { dot: true }).match(relativePath)) {\n if (\n !updatedArtifacts.some(\n (ua) => ua.path === relativePath && ua.type === 'deletion',\n )\n ) {\n logger.debug(\n { file: relativePath, pattern },\n 'Post-upgrade file removed',\n );\n updatedArtifacts.push({\n type: 'deletion',\n path: relativePath,\n });\n }\n // If the file is created or modified by a previous post-update command, remove the modification from updatedArtifacts\n updatedArtifacts = updatedArtifacts.filter(\n (ua) => !(ua.type === 'addition' && ua.path === relativePath),\n );\n }\n }\n }\n }\n }\n return { updatedArtifacts, artifactErrors };\n}\n\nexport default async function executePostUpgradeCommands(\n config: BranchConfig,\n): Promise<PostUpgradeCommandsExecutionResult | null> {\n const hasChangedFiles =\n (isArray(config.updatedPackageFiles) &&\n config.updatedPackageFiles.length > 0) ||\n (isArray(config.updatedArtifacts) && config.updatedArtifacts.length > 0);\n\n if (!hasChangedFiles) {\n /* Only run post-upgrade tasks if there are changes to package files... */\n logger.debug('No changes to package files, skipping post-upgrade tasks');\n return null;\n }\n\n const branchUpgradeCommands: BranchUpgradeConfig[] = [\n {\n manager: config.manager,\n depName: config.upgrades.map(({ depName }) => depName).join(' '),\n branchName: config.branchName,\n postUpgradeTasks:\n config.postUpgradeTasks!.executionMode === 'branch'\n ? config.postUpgradeTasks\n : undefined,\n },\n ];\n\n const updateUpgradeCommands: BranchUpgradeConfig[] = config.upgrades.filter(\n ({ postUpgradeTasks }) =>\n !postUpgradeTasks?.executionMode ||\n postUpgradeTasks.executionMode === 'update',\n );\n\n const { updatedArtifacts, artifactErrors } =\n await postUpgradeCommandsExecutor(updateUpgradeCommands, config);\n return postUpgradeCommandsExecutor(branchUpgradeCommands, {\n ...config,\n updatedArtifacts,\n artifactErrors,\n });\n}\n"]}
1
+ {"version":3,"file":"execute-post-upgrade-commands.js","sourceRoot":"","sources":["../../../../../lib/workers/repository/update/branch/execute-post-upgrade-commands.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'crypto';\n// TODO #22198\nimport { isArray, isNonEmptyArray, isNonEmptyString } from '@sindresorhus/is';\nimport upath from 'upath';\nimport { mergeChildConfig } from '../../../../config';\nimport { GlobalConfig } from '../../../../config/global';\nimport { addMeta, logger } from '../../../../logger';\nimport type { ArtifactError } from '../../../../modules/manager/types';\nimport { coerceArray } from '../../../../util/array';\nimport { exec } from '../../../../util/exec';\nimport type { ExecOptions } from '../../../../util/exec/types';\nimport {\n ensureLocalDir,\n localPathIsFile,\n outputCacheFile,\n privateCacheDir,\n readLocalFile,\n writeLocalFile,\n} from '../../../../util/fs';\nimport { getRepoStatus } from '../../../../util/git';\nimport { getGitEnvironmentVariables } from '../../../../util/git/auth';\nimport type { FileChange } from '../../../../util/git/types';\nimport { minimatch } from '../../../../util/minimatch';\nimport { regEx } from '../../../../util/regex';\nimport { sanitize } from '../../../../util/sanitize';\nimport { compile } from '../../../../util/template';\nimport type { BranchConfig, BranchUpgradeConfig } from '../../../types';\n\nexport interface PostUpgradeCommandsExecutionResult {\n updatedArtifacts: FileChange[];\n artifactErrors: ArtifactError[];\n}\n\nexport async function postUpgradeCommandsExecutor(\n filteredUpgradeCommands: BranchUpgradeConfig[],\n config: BranchConfig,\n): Promise<PostUpgradeCommandsExecutionResult> {\n let updatedArtifacts = [...(config.updatedArtifacts ?? [])];\n const artifactErrors = [...(config.artifactErrors ?? [])];\n const allowedCommands = GlobalConfig.get('allowedCommands');\n\n for (const upgrade of filteredUpgradeCommands) {\n addMeta({ dep: upgrade.depName });\n logger.trace(\n {\n tasks: upgrade.postUpgradeTasks,\n allowedCommands,\n },\n `Checking for post-upgrade tasks`,\n );\n const commands = upgrade.postUpgradeTasks?.commands;\n const dataFileTemplate = upgrade.postUpgradeTasks?.dataFileTemplate;\n const fileFilters = upgrade.postUpgradeTasks?.fileFilters ?? ['**/*'];\n if (isNonEmptyArray(commands)) {\n // Persist updated files in file system so any executed commands can see them\n const previouslyModifiedFiles =\n config.updatedPackageFiles!.concat(updatedArtifacts);\n for (const file of previouslyModifiedFiles) {\n const canWriteFile = await localPathIsFile(file.path);\n if (file.type === 'addition' && !file.isSymlink && canWriteFile) {\n let contents: Buffer | null;\n if (typeof file.contents === 'string') {\n contents = Buffer.from(file.contents);\n } else {\n contents = file.contents;\n }\n // TODO #22198\n await writeLocalFile(file.path, contents!);\n }\n }\n\n let dataFilePath: string | null = null;\n if (dataFileTemplate) {\n const dataFileContent = sanitize(\n compile(dataFileTemplate, mergeChildConfig(config, upgrade)),\n );\n logger.debug(\n { dataFileTemplate },\n 'Processed post-upgrade commands data file template.',\n );\n\n const dataFileName = `post-upgrade-data-file-${crypto.randomBytes(8).toString('hex')}.tmp`;\n dataFilePath = upath.join(privateCacheDir(), dataFileName);\n\n try {\n await outputCacheFile(dataFilePath, dataFileContent);\n\n logger.debug(\n { dataFilePath, dataFileContent },\n 'Created post-upgrade commands data file.',\n );\n } catch (error) {\n artifactErrors.push({\n stderr: sanitize(\n `Failed to create post-upgrade commands data file at ${dataFilePath}, reason: ${error.message}`,\n ),\n });\n\n dataFilePath = null;\n }\n }\n\n const workingDirTemplate = upgrade.postUpgradeTasks?.workingDirTemplate;\n let workingDir: string | null = null;\n\n if (workingDirTemplate) {\n workingDir = sanitize(\n compile(workingDirTemplate, mergeChildConfig(config, upgrade)),\n );\n await ensureLocalDir(workingDir);\n logger.trace(\n { workingDirTemplate },\n 'Processed post-upgrade commands working directory template.',\n );\n }\n\n for (const cmd of commands) {\n const compiledCmd = compile(cmd, mergeChildConfig(config, upgrade));\n if (compiledCmd !== cmd) {\n logger.debug(\n { rawCmd: cmd, compiledCmd },\n 'Post-upgrade command has been compiled',\n );\n }\n if (\n allowedCommands!.some((pattern) => regEx(pattern).test(compiledCmd))\n ) {\n try {\n logger.trace({ cmd: compiledCmd }, 'Executing post-upgrade task');\n\n const execOpts: ExecOptions = {\n // WARNING to self-hosted administrators: always run post-upgrade commands with `shell` mode on, which has the risk of arbitrary environment variable access or additional command execution\n // It is very likely this will be susceptible to these risks, even if you allowlist (via `allowedCommands`), as there may be special characters included in the given commands that can be leveraged here\n shell: GlobalConfig.get(\n 'allowShellExecutorForPostUpgradeCommands',\n true,\n ),\n\n cwd: isNonEmptyString(workingDir)\n ? workingDir\n : GlobalConfig.get('localDir'),\n extraEnv: getGitEnvironmentVariables(),\n };\n if (dataFilePath) {\n execOpts.env = {\n RENOVATE_POST_UPGRADE_COMMAND_DATA_FILE: dataFilePath,\n };\n }\n const execResult = await exec(compiledCmd, execOpts);\n\n logger.debug(\n { cmd: compiledCmd, ...execResult },\n 'Executed post-upgrade task',\n );\n } catch (error) {\n artifactErrors.push({\n lockFile: upgrade.packageFile,\n stderr: sanitize(error.message),\n });\n }\n } else {\n logger.warn(\n {\n cmd: compiledCmd,\n allowedCommands,\n },\n 'Post-upgrade task did not match any on allowedCommands list',\n );\n artifactErrors.push({\n lockFile: upgrade.packageFile,\n stderr: sanitize(\n `Post-upgrade command '${compiledCmd}' has not been added to the allowed list in allowedCommands`,\n ),\n });\n }\n }\n\n const status = await getRepoStatus();\n\n logger.trace({ status }, 'git status after post-upgrade tasks');\n\n logger.debug(\n {\n addedCount: status.not_added?.length,\n modifiedCount: status.modified?.length,\n deletedCount: status.deleted?.length,\n renamedCount: status.renamed?.length,\n },\n 'git status counts after post-upgrade tasks',\n );\n\n const addedOrModifiedFiles = [\n ...coerceArray(status.not_added),\n ...coerceArray(status.modified),\n ...coerceArray(status.renamed?.map((x) => x.to)),\n ];\n const changedFiles = [\n ...addedOrModifiedFiles,\n ...coerceArray(status.deleted),\n ...coerceArray(status.renamed?.map((x) => x.from)),\n ];\n\n // Check for files which were previously deleted but have been re-added without modification\n const previouslyDeletedFiles = updatedArtifacts.filter(\n (ua) => ua.type === 'deletion',\n );\n for (const previouslyDeletedFile of previouslyDeletedFiles) {\n /* v8 ignore if -- TODO: needs test */\n if (!changedFiles.includes(previouslyDeletedFile.path)) {\n logger.debug(\n { file: previouslyDeletedFile.path },\n 'Previously deleted file has been restored without modification',\n );\n updatedArtifacts = updatedArtifacts.filter(\n (ua) =>\n !(\n ua.type === 'deletion' && ua.path === previouslyDeletedFile.path\n ),\n );\n }\n }\n\n logger.trace({ addedOrModifiedFiles }, 'Added or modified files');\n logger.debug(\n `Checking ${addedOrModifiedFiles.length} added or modified files for post-upgrade changes`,\n );\n\n const fileExcludes: string[] = [];\n if (config.npmrc) {\n fileExcludes.push('.npmrc');\n }\n\n for (const relativePath of addedOrModifiedFiles) {\n if (\n fileExcludes.some((pattern) =>\n minimatch(pattern, { dot: true }).match(relativePath),\n )\n ) {\n continue;\n }\n\n let fileMatched = false;\n for (const pattern of fileFilters) {\n if (minimatch(pattern, { dot: true }).match(relativePath)) {\n fileMatched = true;\n logger.debug(\n { file: relativePath, pattern },\n 'Post-upgrade file saved',\n );\n const existingContent = await readLocalFile(relativePath);\n const existingUpdatedArtifacts = updatedArtifacts.find(\n (ua) => ua.path === relativePath,\n );\n if (existingUpdatedArtifacts?.type === 'addition') {\n existingUpdatedArtifacts.contents = existingContent;\n } else {\n updatedArtifacts.push({\n type: 'addition',\n path: relativePath,\n contents: existingContent,\n });\n }\n // If the file is deleted by a previous post-update command, remove the deletion from updatedArtifacts\n updatedArtifacts = updatedArtifacts.filter(\n (ua) => !(ua.type === 'deletion' && ua.path === relativePath),\n );\n }\n }\n if (!fileMatched) {\n logger.debug(\n { file: relativePath },\n 'Post-upgrade file did not match any file filters',\n );\n }\n }\n\n for (const relativePath of coerceArray(status.deleted)) {\n for (const pattern of fileFilters) {\n if (minimatch(pattern, { dot: true }).match(relativePath)) {\n if (\n !updatedArtifacts.some(\n (ua) => ua.path === relativePath && ua.type === 'deletion',\n )\n ) {\n logger.debug(\n { file: relativePath, pattern },\n 'Post-upgrade file removed',\n );\n updatedArtifacts.push({\n type: 'deletion',\n path: relativePath,\n });\n }\n // If the file is created or modified by a previous post-update command, remove the modification from updatedArtifacts\n updatedArtifacts = updatedArtifacts.filter(\n (ua) => !(ua.type === 'addition' && ua.path === relativePath),\n );\n }\n }\n }\n }\n }\n return { updatedArtifacts, artifactErrors };\n}\n\nexport default async function executePostUpgradeCommands(\n config: BranchConfig,\n): Promise<PostUpgradeCommandsExecutionResult | null> {\n const hasChangedFiles =\n (isArray(config.updatedPackageFiles) &&\n config.updatedPackageFiles.length > 0) ||\n (isArray(config.updatedArtifacts) && config.updatedArtifacts.length > 0);\n\n if (!hasChangedFiles) {\n /* Only run post-upgrade tasks if there are changes to package files... */\n logger.debug('No changes to package files, skipping post-upgrade tasks');\n return null;\n }\n\n const branchUpgradeCommands: BranchUpgradeConfig[] = [\n {\n manager: config.manager,\n depName: config.upgrades.map(({ depName }) => depName).join(' '),\n branchName: config.branchName,\n postUpgradeTasks:\n config.postUpgradeTasks!.executionMode === 'branch'\n ? config.postUpgradeTasks\n : undefined,\n },\n ];\n\n const updateUpgradeCommands: BranchUpgradeConfig[] = config.upgrades.filter(\n ({ postUpgradeTasks }) =>\n !postUpgradeTasks?.executionMode ||\n postUpgradeTasks.executionMode === 'update',\n );\n\n const { updatedArtifacts, artifactErrors } =\n await postUpgradeCommandsExecutor(updateUpgradeCommands, config);\n return postUpgradeCommandsExecutor(branchUpgradeCommands, {\n ...config,\n updatedArtifacts,\n artifactErrors,\n });\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "renovate",
3
3
  "description": "Automated dependency updates. Flexible so you don't need to be.",
4
- "version": "42.68.4",
4
+ "version": "42.69.0",
5
5
  "type": "commonjs",
6
6
  "bin": {
7
7
  "renovate": "dist/renovate.js",
@@ -1,7 +1,7 @@
1
1
  {
2
- "title": "JSON schema for Renovate 42.68.4 config files (https://renovatebot.com/)",
2
+ "title": "JSON schema for Renovate 42.69.0 config files (https://renovatebot.com/)",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
- "x-renovate-version": "42.68.4",
4
+ "x-renovate-version": "42.69.0",
5
5
  "allowComments": true,
6
6
  "type": "object",
7
7
  "properties": {
@@ -47,6 +47,11 @@
47
47
  "type": "boolean",
48
48
  "default": false
49
49
  },
50
+ "allowShellExecutorForPostUpgradeCommands": {
51
+ "description": "Deprecated: This configuration option is only intended to be used with 'global' configuration when self-hosting, not used in a repository configuration file. Renovate likely won't use the configuration, and these fields will be removed from the repository configuration documentation in Renovate v43 (https://github.com/renovatebot/renovate/issues/38728)\n\nWhether to run commands for `postUpgradeTasks` inside a shell. This has security implications, as it means that they can call out to other commands or access shell variables. It is difficult to craft an `allowedCommands` regex to restrict this.",
52
+ "type": "boolean",
53
+ "default": true
54
+ },
50
55
  "allowedCommands": {
51
56
  "description": "Deprecated: This configuration option is only intended to be used with 'global' configuration when self-hosting, not used in a repository configuration file. Renovate likely won't use the configuration, and these fields will be removed from the repository configuration documentation in Renovate v43 (https://github.com/renovatebot/renovate/issues/38728)\n\nA list of regular expressions that decide which commands are allowed in post-upgrade tasks.",
52
57
  "type": "array",