Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/usage/opentelemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ Renovate provides instrumentation through traces for (non-exhaustively):
- Any Git operations
- Per-manager traces when performing the `lookup` and `extract` splits
- Per-branch traces when performing the `update` split
- Cache lifecycle operations (repository cache load/save, package cache init/destroy)
- Important functions (more instrumentation be added)

As well as following [OpenTelemetry's semantic conventions](https://opentelemetry.io/docs/specs/semconv/) where possible, Renovate defines several Custom Attributes, which can be found in [`lib/instrumentation/types.ts`](https://github.com/renovatebot/renovate/blob/main/lib/instrumentation/types.ts).
Expand Down
2 changes: 1 addition & 1 deletion lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ const options: Readonly<RenovateOptions>[] = [
description:
'Change this value to override the default Renovate sidecar image.',
type: 'string',
default: 'ghcr.io/renovatebot/base-image:13.27.4',
default: 'ghcr.io/renovatebot/base-image:13.27.5',
globalOnly: true,
deprecationMsg:
'The usage of `binarySource=docker` is deprecated, and will be removed in the future',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
- uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97 #v2.1.0
- uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97 #v2.1.0
- uses: actions/checkout@1e204e # v2.1.0
- uses: actions/checkout@1e204e # some-ref-name
- uses: actions/checkout@01aecc#v2.1.0
- uses: actions/checkout@689fcce700ae7ffc576f2b029b51b2ffb66d3abd # comment containing 2.1.0
- uses: actions/checkout@689fcce700ae7ffc576f2b029b51b2ffb66d3abd # v2.1.0 additional comment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ exports[`modules/manager/github-actions/extract > extractPackageFile() > extract
"autoReplaceStringTemplate": "{{depName}}/shellcheck@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}",
"commitMessageTopic": "{{{depName}}} action",
"currentValue": "master",
"datasource": "github-tags",
"datasource": "github-digest",
"depName": "actions/bin",
"depType": "action",
"replaceString": "actions/bin/shellcheck@master",
"versioning": "docker",
"versioning": "exact",
},
{
"autoReplaceStringTemplate": "{{depName}}@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}",
Expand Down Expand Up @@ -122,11 +122,11 @@ exports[`modules/manager/github-actions/extract > extractPackageFile() > extract
"autoReplaceStringTemplate": "{{depName}}/shellcheck@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}",
"commitMessageTopic": "{{{depName}}} action",
"currentValue": "master",
"datasource": "github-tags",
"datasource": "github-digest",
"depName": "actions/bin",
"depType": "action",
"replaceString": "actions/bin/shellcheck@master",
"versioning": "docker",
"versioning": "exact",
},
{
"autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}",
Expand All @@ -142,11 +142,11 @@ exports[`modules/manager/github-actions/extract > extractPackageFile() > extract
"autoReplaceStringTemplate": "{{depName}}/cli@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}",
"commitMessageTopic": "{{{depName}}} action",
"currentValue": "master",
"datasource": "github-tags",
"datasource": "github-digest",
"depName": "actions/docker",
"depType": "action",
"replaceString": "actions/docker/cli@master",
"versioning": "docker",
"versioning": "exact",
},
{
"autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}",
Expand Down
53 changes: 52 additions & 1 deletion lib/modules/manager/github-actions/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ describe('modules/manager/github-actions/extract', () => {
expect(res?.deps).toMatchSnapshot();
expect(
res?.deps.filter((d) => d.datasource === 'github-tags'),
).toHaveLength(8);
).toHaveLength(7);
expect(
res?.deps.filter((d) => d.datasource === 'github-digest'),
).toHaveLength(1);
});

it('use github.com as registry when no settings provided', () => {
Expand Down Expand Up @@ -429,6 +432,11 @@ describe('modules/manager/github-actions/extract', () => {
currentValue: 'v2.1.0',
replaceString: 'actions/checkout@1e204e # v2.1.0',
},
{
currentDigestShort: '1e204e',
currentValue: 'some-ref-name',
replaceString: 'actions/checkout@1e204e # some-ref-name',
},
{
currentValue: '01aecc#v2.1.0',
replaceString: 'actions/checkout@01aecc#v2.1.0',
Expand Down Expand Up @@ -473,6 +481,49 @@ describe('modules/manager/github-actions/extract', () => {
expect(res!.deps[14]).not.toHaveProperty('skipReason');
});

it('extracts non-semver ref automatically', () => {
const res = extractPackageFile(
`
jobs:
build:
steps:
- uses: taiki-e/install-action@cargo-llvm-cov
`,
'workflow.yml',
);
expect(res?.deps[0]).toMatchObject({
depName: 'taiki-e/install-action',
currentValue: 'cargo-llvm-cov',
datasource: 'github-digest',
versioning: 'exact',
autoReplaceStringTemplate:
'{{depName}}@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}',
});
});

it('extracts pinned non-semver ref with digest', () => {
const res = extractPackageFile(
`
jobs:
build:
steps:
- uses: taiki-e/install-action@4b1248585248751e3b12fd020cf7ac91540ca09c # cargo-llvm-cov
`,
'workflow.yml',
);
expect(res?.deps[0]).toMatchObject({
depName: 'taiki-e/install-action',
currentValue: 'cargo-llvm-cov',
currentDigest: '4b1248585248751e3b12fd020cf7ac91540ca09c',
datasource: 'github-digest',
versioning: 'exact',
replaceString:
'taiki-e/install-action@4b1248585248751e3b12fd020cf7ac91540ca09c # cargo-llvm-cov',
autoReplaceStringTemplate:
'{{depName}}@{{#if newDigest}}{{newDigest}}{{#if newValue}} # {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}{{/unless}}',
});
});

it('extracts actions with fqdn', () => {
const res = extractPackageFile(
codeBlock`
Expand Down
25 changes: 19 additions & 6 deletions lib/modules/manager/github-actions/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { detectPlatform } from '../../../util/common.ts';
import { newlineRegex, regEx } from '../../../util/regex.ts';
import { ForgejoTagsDatasource } from '../../datasource/forgejo-tags/index.ts';
import { GiteaTagsDatasource } from '../../datasource/gitea-tags/index.ts';
import { GithubDigestDatasource } from '../../datasource/github-digest/index.ts';
import { GithubReleasesDatasource } from '../../datasource/github-releases/index.ts';
import { GithubRunnersDatasource } from '../../datasource/github-runners/index.ts';
import { GithubTagsDatasource } from '../../datasource/github-tags/index.ts';
import * as dockerVersioning from '../../versioning/docker/index.ts';
import * as exactVersioning from '../../versioning/exact/index.ts';
import * as nodeVersioning from '../../versioning/node/index.ts';
import * as npmVersioning from '../../versioning/npm/index.ts';
import { getDep } from '../dockerfile/extract.ts';
Expand All @@ -19,7 +21,7 @@ import type {
} from '../types.ts';
import { CommunityActions } from './community.ts';
import type { DockerReference, RepositoryReference } from './parse.ts';
import { isSha, isShortSha, parseUsesLine } from './parse.ts';
import { isSha, isShortSha, parseUsesLine, versionLikeRe } from './parse.ts';
import type { Steps } from './schema.ts';
import { Workflow } from './schema.ts';

Expand Down Expand Up @@ -84,7 +86,6 @@ function extractRepositoryAction(
const dep: PackageDependency = {
depName,
commitMessageTopic: '{{{depName}}} action',
datasource: GithubTagsDatasource.id,
versioning: dockerVersioning.id,
depType: 'action',
replaceString: valueString,
Expand All @@ -99,10 +100,13 @@ function extractRepositoryAction(
}

// Extend replaceString to include relevant comment portions:
// - Pinned version: include only up to the version (truncate trailing text)
// - Pinned version or ref: include only up to the matched token (truncate trailing text)
// - Ratchet exclude: include the full comment to preserve the marker
const pinComment =
commentData.pinnedVersion ??
(isSha(ref) || isShortSha(ref) ? commentData.ref : undefined);
if (
commentData.pinnedVersion &&
pinComment &&
!is.undefined(commentData.index) &&
!is.undefined(commentData.matchedString)
) {
Expand All @@ -117,15 +121,24 @@ function extractRepositoryAction(
}

if (isSha(ref)) {
dep.currentValue = commentData.pinnedVersion;
dep.currentValue = commentData.pinnedVersion ?? commentData.ref;
dep.currentDigest = ref;
} else if (isShortSha(ref)) {
dep.currentValue = commentData.pinnedVersion;
dep.currentValue = commentData.pinnedVersion ?? commentData.ref;
dep.currentDigestShort = ref;
} else {
dep.currentValue = ref;
}

const isVersionLike =
dep.currentValue && versionLikeRe.test(dep.currentValue);
if (!dep.datasource && dep.currentValue && !isVersionLike) {
dep.datasource = GithubDigestDatasource.id;
dep.versioning = exactVersioning.id;
}

dep.datasource ??= GithubTagsDatasource.id;

return dep;
}

Expand Down
4 changes: 3 additions & 1 deletion lib/modules/manager/github-actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Category } from '../../../constants/index.ts';
import { GiteaTagsDatasource } from '../../datasource/gitea-tags/index.ts';
import { GithubDigestDatasource } from '../../datasource/github-digest/index.ts';
import { GithubRunnersDatasource } from '../../datasource/github-runners/index.ts';
import { GithubTagsDatasource } from '../../datasource/github-tags/index.ts';

Expand All @@ -18,6 +19,7 @@ export const defaultConfig = {

export const supportedDatasources = [
GiteaTagsDatasource.id,
GithubTagsDatasource.id,
GithubDigestDatasource.id,
GithubRunnersDatasource.id,
GithubTagsDatasource.id,
];
22 changes: 22 additions & 0 deletions lib/modules/manager/github-actions/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,28 @@ describe('modules/manager/github-actions/parse', () => {
pinnedVersion: 'node/v20',
});
});

it('parses bare non-semver ref', () => {
const result = parseComment(' cargo-llvm-cov');
expect(result).toEqual({
index: 0,
matchedString: ' cargo-llvm-cov',
ref: 'cargo-llvm-cov',
});
});

it('parses bare branch name', () => {
const result = parseComment(' main');
expect(result).toEqual({
index: 0,
matchedString: ' main',
ref: 'main',
});
});

it('ignores multi-word comments', () => {
expect(parseComment('do not update')).toEqual({});
});
});

describe('parseQuote', () => {
Expand Down
25 changes: 17 additions & 8 deletions lib/modules/manager/github-actions/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,28 @@ export function parseActionReference(uses: string): ActionReference | null {

export interface CommentData {
pinnedVersion?: string;
ref?: string;
ratchetExclude?: boolean;
matchedString?: string;
index?: number;
}

// Matches version strings with optional prefixes, e.g.:
// - "@v1.2.3", "v1.2.3", "1.2.3"
// - "renovate: pin @v1.2.3", "tag=v1.2.3"
// - "ratchet:owner/repo@v1.2.3"
// - "stable/v1.2.3", "stable-v1.2.3"
const pinnedVersionRe = regEx(
const pinTokenRe = regEx(
/^\s*(?:(?:renovate\s*:\s*)?(?:pin\s+|tag\s*=\s*)?|(?:ratchet:[\w-]+\/[.\w-]+))?@?(?<version>([\w-]*[-/])?v?\d+(?:\.\d+(?:\.\d+)?)?)/,
);

export const versionLikeRe = regEx(/^v?\d+/);

const bareTokenRe = regEx(/^\s*(?<token>\S+)\s*$/);

export function parseComment(commentBody: string): CommentData {
const trimmed = commentBody.trim();
if (trimmed === 'ratchet:exclude') {
return { ratchetExclude: true };
}

// We use commentBody (with leading spaces) to get the correct index relative to the comment start
const match = pinnedVersionRe.exec(commentBody);
const match = pinTokenRe.exec(commentBody);
if (match?.groups?.version) {
return {
pinnedVersion: match.groups.version,
Expand All @@ -224,6 +224,15 @@ export function parseComment(commentBody: string): CommentData {
};
}

const bareMatch = bareTokenRe.exec(commentBody);
if (bareMatch?.groups?.token) {
return {
ref: bareMatch.groups.token,
matchedString: bareMatch[0],
index: bareMatch.index,
};
}

return {};
}

Expand Down Expand Up @@ -290,7 +299,7 @@ export function parseUsesLine(line: string): ParsedUsesLine | null {
);

const { value, quote } = parseQuote(rawValuePart);
// commentPart always starts with '#' since we found ' #' and sliced after the space
// commentPart always starts with '#' (see commentIndex search above)
const cleanCommentBody = commentPart.slice(1);

return {
Expand Down
23 changes: 23 additions & 0 deletions lib/modules/manager/github-actions/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ If you want to automatically pin action digests add the `helpers:pinGitHubAction
}
```

### Non-semver refs (branches and feature tags)

Renovate supports GitHub Actions that reference non-semver refs like branch names (`main`, `master`) or feature-oriented tags (`cargo-llvm-cov`).

When the action reference doesn't look like a version number (i.e., doesn't match `/^v?\d+/`), Renovate routes to the `github-digest` datasource which fetches both tags and branches.
Since these refs have no version ordering, only digest pinning updates are supported.

**Routing logic:**

- `actions/checkout@v4.2.0` → `github-tags` datasource (version updates)
- `actions/checkout@v4` → `github-tags` datasource (version updates)
- `taiki-e/install-action@cargo-llvm-cov` → `github-digest` datasource (digest pinning only)
- `actions/checkout@main` → `github-digest` datasource (digest pinning only)

When pinning, Renovate adds a comment to preserve the original ref:

```yaml
- uses: taiki-e/install-action@d8c10dae823f48238abff23fee4146b448aed2f1 # cargo-llvm-cov
```

Non-semver ref support is currently limited to GitHub-hosted actions.
Gitea and Forgejo support the same ref types, but Renovate does not yet handle them for these platforms.

### Non-support of Variables

Renovate ignores any GitHub runners which are configured in variables.
Expand Down
Loading
Loading