mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-30 17:27:26 +00:00
4add67e86e
* ci(linter): add prefer-partial-in-specs oxlint rule
Flags object literals cast to `any` (`{...} as any`) in spec/test files and steers toward `partial<T>()` from `test/util`. Enabled at error in the spec-files override so CI blocks new occurrences.
Closes #44646
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: drop unnecessary object-literal `as any` casts
The casts masked values already assignable to the expected type (migration configs accepted as Record<string, unknown>, all-optional param types, etc.); removing them restores real type checking.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: replace object-literal `as any` casts with partial<T>()
Uses partial<T>() from test/util so incomplete mock/config objects keep proper typing. Azure API mocks switch to mockResolvedValue(partial<T>()) and their inner method mocks to mockResolvedValue(), matching the sibling-file idiom.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test: suppress prefer-partial-in-specs for intentionally-invalid inputs
Some tests deliberately pass malformed or legacy data to exercise validation/error paths, where no real type fits; keep the cast with a reasoned oxlint-disable-next-line.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
172 lines
5.2 KiB
TypeScript
172 lines
5.2 KiB
TypeScript
import {
|
|
CONFIG_SECRETS_INVALID,
|
|
CONFIG_VALIDATION,
|
|
CONFIG_VARIABLES_INVALID,
|
|
} from '../constants/error-messages.ts';
|
|
import { getConfig } from './defaults.ts';
|
|
import {
|
|
applySecretsAndVariablesToConfig,
|
|
validateConfigSecretsAndVariables,
|
|
} from './secrets.ts';
|
|
|
|
describe('config/secrets', () => {
|
|
describe('validateConfigSecretsAndVariables(config)', () => {
|
|
it('works with default config', () => {
|
|
expect(() =>
|
|
validateConfigSecretsAndVariables(getConfig()),
|
|
).not.toThrow();
|
|
});
|
|
|
|
it('returns if no secrets/variables', () => {
|
|
expect(validateConfigSecretsAndVariables({})).toBeUndefined();
|
|
});
|
|
|
|
it('throws for invalid secret name', () => {
|
|
expect(() =>
|
|
validateConfigSecretsAndVariables({
|
|
secrets: { '123': 'abc' },
|
|
}),
|
|
).toThrow(CONFIG_SECRETS_INVALID);
|
|
});
|
|
|
|
it('throws for invalid variable name', () => {
|
|
expect(() =>
|
|
validateConfigSecretsAndVariables({
|
|
variables: { '123': 'abc' },
|
|
}),
|
|
).toThrow(CONFIG_VARIABLES_INVALID);
|
|
});
|
|
|
|
it('throws for secrets in repositories', () => {
|
|
expect(() =>
|
|
// oxlint-disable-next-line renovate/prefer-partial-in-specs -- intentionally invalid secret value type
|
|
validateConfigSecretsAndVariables({
|
|
repositories: [{ repository: 'x/y', secrets: { abc: 123 } }],
|
|
} as any),
|
|
).toThrow(CONFIG_SECRETS_INVALID);
|
|
});
|
|
|
|
it('throws for variables in repositories', () => {
|
|
expect(() =>
|
|
// oxlint-disable-next-line renovate/prefer-partial-in-specs -- intentionally invalid variable value type
|
|
validateConfigSecretsAndVariables({
|
|
repositories: [{ repository: 'x/y', variables: { abc: 123 } }],
|
|
} as any),
|
|
).toThrow(CONFIG_VARIABLES_INVALID);
|
|
});
|
|
});
|
|
|
|
describe('applySecretsAndVariablesToConfig(config)', () => {
|
|
it('replaces both secrets and variables', () => {
|
|
const config = {
|
|
secrets: { TOKEN: 'secret123' },
|
|
variables: { MANAGER: 'npm' },
|
|
hostRules: [
|
|
{
|
|
hostType: '{{ variables.MANAGER }}',
|
|
token: '{{ secrets.TOKEN }}',
|
|
},
|
|
],
|
|
};
|
|
const result = applySecretsAndVariablesToConfig({ config });
|
|
expect(result).toEqual({
|
|
hostRules: [{ hostType: 'npm', token: 'secret123' }],
|
|
});
|
|
});
|
|
|
|
it('replaces all secrets and variables', () => {
|
|
const config = {
|
|
secrets: { FOO: 'foo', BAR: 'bar', BAZ: 'baz' },
|
|
variables: { FOO: 'foo', BAR: 'bar', BAZ: 'baz' },
|
|
customEnvVariables: {
|
|
SECRETS: '{{ secrets.FOO }} {{ secrets.BAR }} {{ secrets.BAZ }}',
|
|
VARIABLES:
|
|
'{{ variables.FOO }} {{ variables.BAR }} {{ variables.BAZ }}',
|
|
},
|
|
};
|
|
const result = applySecretsAndVariablesToConfig({ config });
|
|
expect(result).toEqual({
|
|
customEnvVariables: {
|
|
SECRETS: 'foo bar baz',
|
|
VARIABLES: 'foo bar baz',
|
|
},
|
|
});
|
|
});
|
|
|
|
it('handles a mix of space characters around the curly braces', () => {
|
|
const config = {
|
|
secrets: { TOKEN: 'secret123' },
|
|
variables: { MANAGER: 'npm' },
|
|
hostRules: [
|
|
{
|
|
hostType: '{{variables.MANAGER }}',
|
|
token: '{{secrets.TOKEN}}',
|
|
},
|
|
],
|
|
};
|
|
const result = applySecretsAndVariablesToConfig({ config });
|
|
expect(result).toEqual({
|
|
hostRules: [{ hostType: 'npm', token: 'secret123' }],
|
|
});
|
|
});
|
|
|
|
it('does not handle non-space characters around the curly braces', () => {
|
|
const config = {
|
|
secrets: { TOKEN: 'secret123' },
|
|
variables: { MANAGER: 'npm' },
|
|
hostRules: [
|
|
{
|
|
hostType: '{{variables.MANAGER }}',
|
|
token: '{{\tsecrets.token\t}}',
|
|
},
|
|
],
|
|
};
|
|
const result = applySecretsAndVariablesToConfig({ config });
|
|
expect(result).toEqual({
|
|
hostRules: [{ hostType: 'npm', token: '{{\tsecrets.token\t}}' }],
|
|
});
|
|
});
|
|
|
|
it('preserves secrets and variables if delete flags are false', () => {
|
|
const config = {
|
|
secrets: { TOKEN: 'secret123' },
|
|
variables: { MANAGER: 'npm' },
|
|
hostRules: [
|
|
{
|
|
hostType: '{{ variables.MANAGER }}',
|
|
token: '{{ secrets.TOKEN }}',
|
|
},
|
|
],
|
|
};
|
|
const result = applySecretsAndVariablesToConfig({
|
|
config,
|
|
deleteSecrets: false,
|
|
deleteVariables: false,
|
|
});
|
|
expect(result).toEqual({
|
|
secrets: { TOKEN: 'secret123' },
|
|
variables: { MANAGER: 'npm' },
|
|
hostRules: [{ hostType: 'npm', token: 'secret123' }],
|
|
});
|
|
});
|
|
|
|
it('throws if secret is missing', () => {
|
|
const config = {
|
|
hostRules: [{ token: '{{ secrets.MISSING_SECRET }}' }],
|
|
};
|
|
expect(() => applySecretsAndVariablesToConfig({ config })).toThrow(
|
|
CONFIG_VALIDATION,
|
|
);
|
|
});
|
|
|
|
it('throws if variable is missing', () => {
|
|
const config = {
|
|
hostRules: [{ hostType: '{{ variables.MISSING_VAR }}' }],
|
|
};
|
|
expect(() => applySecretsAndVariablesToConfig({ config })).toThrow(
|
|
CONFIG_VALIDATION,
|
|
);
|
|
});
|
|
});
|
|
});
|