Skip to content

Commit

Permalink
feat(managers/ocb): add new manager for OpenTelemetryCollectorBuilder (
Browse files Browse the repository at this point in the history
…#26509)

Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
  • Loading branch information
secustor and HonkingGoose committed Jan 8, 2024
1 parent 5f24ab9 commit b14661f
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 3 deletions.
18 changes: 15 additions & 3 deletions docs/usage/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,21 @@ This is an advance field and it's recommend you seek a config review before appl

## bumpVersion

Currently this setting supports `helmv3`, `npm`, `nuget`, `maven`, `pep621`, `poetry` and `sbt` only, so raise a feature request if you have a use for it with other package managers.
Its purpose is if you want Renovate to update the `version` field within your package file any time it updates dependencies within.
Usually this is for automatic release purposes, so that you don't need to add another step after Renovate before you can release a new version.
Currently, this config option only works with these managers:

- `helmv3`
- `npm`
- `nuget`
- `maven`
- `ocb`
- `pep621`
- `poetry`
- `sbt`

Raise a feature request if you want to use this config option with other package managers.

Use `bumpVersion` if you want Renovate to update the `version` field in your package file when it updates the dependencies in that file.
This can be handy when you have automated your package's release, as you you don't need extra steps after the Renovate upgrade, you can just release a new version.

Configure this value to `"prerelease"`, `"patch"`, `"minor"` or `"major"` to have Renovate update the version in your edited package file.
e.g. if you wish Renovate to always increase the target `package.json` version with a patch update, configure this to `"patch"`.
Expand Down
2 changes: 2 additions & 0 deletions lib/modules/manager/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import * as nodenv from './nodenv';
import * as npm from './npm';
import * as nuget from './nuget';
import * as nvm from './nvm';
import * as ocb from './ocb';
import * as osgi from './osgi';
import * as pep621 from './pep621';
import * as pipCompile from './pip-compile';
Expand Down Expand Up @@ -153,6 +154,7 @@ api.set('nodenv', nodenv);
api.set('npm', npm);
api.set('nuget', nuget);
api.set('nvm', nvm);
api.set('ocb', ocb);
api.set('osgi', osgi);
api.set('pep621', pep621);
api.set('pip-compile', pipCompile);
Expand Down
74 changes: 74 additions & 0 deletions lib/modules/manager/ocb/extract.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { codeBlock } from 'common-tags';
import { extractPackageFile } from '.';

describe('modules/manager/ocb/extract', () => {
describe('extractPackageFile', () => {
it('run successfully with full example', () => {
const content = codeBlock`
dist:
name: otelcol-custom
description: Local OpenTelemetry Collector binary
module: github.com/open-telemetry/opentelemetry-collector
otelcol_version: 0.40.0
version: 1.0.0
output_path: /tmp/dist
exporters:
- gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/alibabacloudlogserviceexporter v0.86.0
- gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.86.0
receivers:
- gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.86.0
processors:
- gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.86.0
`;
const result = extractPackageFile(content, 'builder-config.yaml');
expect(result?.deps).toEqual([
{
currentValue: '0.40.0',
datasource: 'go',
depName: 'github.com/open-telemetry/opentelemetry-collector',
depType: 'collector',
extractVersion: '^v(?<version>\\S+)',
},
{
currentValue: 'v0.86.0',
datasource: 'go',
depName:
'github.com/open-telemetry/opentelemetry-collector-contrib/exporter/alibabacloudlogserviceexporter',
depType: 'exports',
},
{
currentValue: 'v0.86.0',
datasource: 'go',
depName: 'go.opentelemetry.io/collector/exporter/debugexporter',
depType: 'exports',
},
{
currentValue: 'v0.86.0',
datasource: 'go',
depName: 'go.opentelemetry.io/collector/processor/batchprocessor',
depType: 'processors',
},
]);
});

it('return null for unknown content', () => {
expect(extractPackageFile('foo', 'bar.yaml')).toBeNull();
});

it('return null for content which is not YAML', () => {
expect(
extractPackageFile(
codeBlock`
myObject:
aString: value
---
foo: bar
`,
'bar.yaml',
),
).toBeNull();
});
});
});
81 changes: 81 additions & 0 deletions lib/modules/manager/ocb/extract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import is from '@sindresorhus/is';
import { logger } from '../../../logger';
import { regEx } from '../../../util/regex';
import { parseSingleYaml } from '../../../util/yaml';
import { GoDatasource } from '../../datasource/go';
import type {
ExtractConfig,
PackageDependency,
PackageFileContent,
} from '../types';
import { type Module, type OCBConfig, OCBConfigSchema } from './schema';

export function extractPackageFile(
content: string,
packageFile: string,
_config?: ExtractConfig,
): PackageFileContent | null {
let definition: OCBConfig | null = null;
try {
const yaml = parseSingleYaml(content);
const parsed = OCBConfigSchema.safeParse(yaml);
if (!parsed.success) {
logger.trace(
{ packageFile, error: parsed.error },
'Failed to parse OCB schema',
);
return null;
}

definition = parsed.data;
} catch (error) {
logger.debug(
{ packageFile, error },
'OCB manager failed to parse file as YAML',
);
return null;
}

const deps: PackageDependency[] = [];
if (definition.dist.module && definition.dist.otelcol_version) {
deps.push({
datasource: GoDatasource.id,
depType: 'collector',
depName: definition.dist.module,
currentValue: definition.dist.otelcol_version,
extractVersion: '^v(?<version>\\S+)',
});
}

deps.push(...processModule(definition.connectors, 'connectors'));
deps.push(...processModule(definition.exporters, 'exports'));
deps.push(...processModule(definition.extension, 'extensions'));
deps.push(...processModule(definition.processors, 'processors'));

return {
packageFileVersion: definition.dist.version,
deps,
};
}

export function processModule(
module: Module,
depType: string,
): PackageDependency[] {
const deps: PackageDependency[] = [];
if (is.nullOrUndefined(module)) {
return deps;
}

for (const element of module) {
const [depName, currentValue] = element.gomod.trim().split(regEx(/\s+/));
deps.push({
datasource: GoDatasource.id,
depType,
depName,
currentValue,
});
}

return deps;
}
13 changes: 13 additions & 0 deletions lib/modules/manager/ocb/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Category } from '../../../constants';
import { GoDatasource } from '../../datasource/go';

export { extractPackageFile } from './extract';
export { bumpPackageVersion } from './update';

export const supportedDatasources = [GoDatasource.id];

export const categories: Category[] = ['golang'];

export const defaultConfig = {
fileMatch: [],
};
23 changes: 23 additions & 0 deletions lib/modules/manager/ocb/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Renovate uses this manager to update dependencies defined in the build definitions for the [OpenTelemetry Collector Builder (ocb)](https://github.com/open-telemetry/opentelemetry-collector/tree/main/cmd/builder).

By default, the `ocb` manager has no `fileMatch` patterns.
This means you must set a `fileMatch` pattern for the `ocb` manager, in order for Renovate to update your `ocb` files.
Here's a configuration example:

```json title="If your builder files are named like foo-builder.yml or builder.yaml"
{
"ocb": {
"fileMatch": ["builder.ya?ml$"]
}
}
```

Supported dependencies and their respective `depType`s are:

| Name | depType |
| -------------- | ------------ |
| base collector | `collector` |
| connectors | `connectors` |
| exports | `exports` |
| extensions | `extensions` |
| processors | `processors` |
22 changes: 22 additions & 0 deletions lib/modules/manager/ocb/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { z } from 'zod';

const Entry = z.object({
gomod: z.string(),
});

const ModuleSchema = z.array(Entry).optional();
export type Module = z.infer<typeof ModuleSchema>;

export const OCBConfigSchema = z.object({
dist: z.object({
otelcol_version: z.string().optional(),
module: z.string().optional(),
version: z.string().optional(),
}),
extension: ModuleSchema,
exporters: ModuleSchema,
receivers: ModuleSchema,
processors: ModuleSchema,
connectors: ModuleSchema,
});
export type OCBConfig = z.infer<typeof OCBConfigSchema>;
77 changes: 77 additions & 0 deletions lib/modules/manager/ocb/update.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { codeBlock } from 'common-tags';
import { bumpPackageVersion } from '.';

describe('modules/manager/ocb/update', () => {
describe('bumpPackageVersion()', () => {
it('increments with all fields', () => {
const content = codeBlock`
dist:
name: otelcol-custom
description: Local OpenTelemetry Collector binary
module: github.com/open-telemetry/opentelemetry-collector
otelcol_version: 0.40.0
version: 1.0.0
output_path: /tmp/dist
`;
const expected = content.replace('1.0.0', '1.0.1');

const { bumpedContent } = bumpPackageVersion(content, '1.0.0', 'patch');
expect(bumpedContent).toEqual(expected);
});

it('increments with double quotes', () => {
const content = codeBlock`
dist:
version: "1.0.0"
`;
const expected = content.replace('1.0.0', '1.0.1');

const { bumpedContent } = bumpPackageVersion(content, '1.0.0', 'patch');
expect(bumpedContent).toEqual(expected);
});

it('increments with single quotes', () => {
const content = codeBlock`
dist:
version: '1.0.0'
`;
const expected = content.replace('1.0.0', '1.0.1');

const { bumpedContent } = bumpPackageVersion(content, '1.0.0', 'patch');
expect(bumpedContent).toEqual(expected);
});

it('no ops', () => {
const content = codeBlock`
dist:
version: '0.0.2'
`;
const { bumpedContent } = bumpPackageVersion(content, '0.0.1', 'patch');
expect(bumpedContent).toEqual(content);
});

it('updates', () => {
const content = codeBlock`
dist:
version: '0.0.2'
`;
const { bumpedContent } = bumpPackageVersion(content, '0.0.1', 'minor');
const expected = content.replace('0.0.2', '0.1.0');
expect(bumpedContent).toEqual(expected);
});

it('returns content if bumping errors', () => {
const content = codeBlock`
dist:
version: '1.0.0'
`;
const { bumpedContent } = bumpPackageVersion(
content,
'0.0.2',
// @ts-expect-error supplying a wrong parameter to trigger an exception
true,
);
expect(bumpedContent).toEqual(content);
});
});
});
47 changes: 47 additions & 0 deletions lib/modules/manager/ocb/update.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { type ReleaseType, inc } from 'semver';
import { logger } from '../../../logger';
import { regEx } from '../../../util/regex';
import type { BumpPackageVersionResult } from '../types';

export function bumpPackageVersion(
content: string,
currentValue: string,
bumpVersion: ReleaseType,
): BumpPackageVersionResult {
logger.debug(
{ bumpVersion, currentValue },
'Checking if we should bump OCB version',
);

let bumpedContent = content;
try {
const newProjectVersion = inc(currentValue, bumpVersion);
if (!newProjectVersion) {
throw new Error('semver inc failed');
}

logger.debug(`newProjectVersion: ${newProjectVersion}`);
bumpedContent = content.replace(
regEx(/\b(?<version>version:\s+["']?)(?<currentValue>[^'"\s]*)/),
`$<version>${newProjectVersion}`,
);

if (bumpedContent === content) {
logger.debug('Version was already bumped');
} else {
logger.debug('Bumped OCB version');
}
} catch (err) {
logger.warn(
{
content,
currentValue,
bumpVersion,
manager: 'ocb',
},
'Failed to bumpVersion',
);
}

return { bumpedContent };
}

0 comments on commit b14661f

Please sign in to comment.