Skip to content

Commit

Permalink
Merge branch 'main' into feature/security-only-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
rhyskoedijk committed Nov 18, 2024
2 parents 04cdb09 + 7ea2955 commit 5d738e5
Show file tree
Hide file tree
Showing 39 changed files with 788 additions and 239 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "8.0.10",
"version": "9.0.0",
"commands": [
"dotnet-ef"
]
Expand Down
3 changes: 3 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ updates:
schedule:
interval: 'weekly'
time: '02:00'
groups:
dotnet-docker:
patterns: ['dotnet/*']

- package-ecosystem: 'nuget'
directory: '/'
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/cleanup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
- { ecosystem: cargo }
- { ecosystem: composer }
- { ecosystem: docker }
- { ecosystem: dotnet-sdk }
- { ecosystem: elm }
- { ecosystem: gitsubmodule }
- { ecosystem: github-actions }
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ jobs:
fetch-depth: 0 # Required for GitVersion

- name: Install GitVersion
uses: gittools/actions/gitversion/[email protected].0
uses: gittools/actions/gitversion/[email protected].1
with:
versionSpec: '6.x'

- name: Determine Version
id: gitversion
uses: gittools/actions/gitversion/[email protected].0
uses: gittools/actions/gitversion/[email protected].1
with:
useConfigFile: true

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ jobs:
fetch-depth: 0 # Required for GitVersion

- name: Install GitVersion
uses: gittools/actions/gitversion/[email protected].0
uses: gittools/actions/gitversion/[email protected].1
with:
versionSpec: '6.x'

- name: Determine Version
uses: gittools/actions/gitversion/[email protected].0
uses: gittools/actions/gitversion/[email protected].1
id: gitversion
with:
useConfigFile: true

- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
dotnet-version: '9.x'

- name: Test
run: dotnet test -c Release --collect "Code coverage"
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/updater.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
- { ecosystem: cargo }
- { ecosystem: composer }
- { ecosystem: docker }
- { ecosystem: dotnet-sdk }
- { ecosystem: elm }
- { ecosystem: gitsubmodule }
- { ecosystem: github-actions }
Expand Down Expand Up @@ -63,12 +64,12 @@ jobs:
fetch-depth: 0 # Required for GitVersion

- name: Install GitVersion
uses: gittools/actions/gitversion/[email protected].0
uses: gittools/actions/gitversion/[email protected].1
with:
versionSpec: '6.x'

- name: Determine Version
uses: gittools/actions/gitversion/[email protected].0
uses: gittools/actions/gitversion/[email protected].1
id: gitversion
with:
useConfigFile: true
Expand Down
2 changes: 2 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pretty-quick --staged
codespell
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ GEMSPECS = %w(
silent/dependabot-silent.gemspec
swift/dependabot-swift.gemspec
devcontainers/dependabot-devcontainers.gemspec
dotnet_sdk/dependabot-dotnet_sdk.gemspec
).freeze

def run_command(command)
Expand Down
8 changes: 4 additions & 4 deletions extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"devDependencies": {
"@types/jest": "29.5.14",
"@types/js-yaml": "4.0.9",
"@types/node": "22.8.1",
"@types/node": "22.9.0",
"@types/q": "1.5.8",
"jest": "29.7.0",
"ts-jest": "29.2.5",
Expand Down
12 changes: 5 additions & 7 deletions extension/tasks/dependabotV1/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"helpMarkDown": "For help please visit https://github.com/tinglesoftware/dependabot-azure-devops/issues",
"helpUrl": "https://github.com/tinglesoftware/dependabot-azure-devops/issues",
"releaseNotes": "https://github.com/tinglesoftware/dependabot-azure-devops/releases",
"category": "Utility",
"author": "Tingle Software",
"category": "Azure Pipelines",
"visibility": ["Build", "Release"],
"runsOn": ["Agent", "DeploymentGroup"],
"author": "Tingle Software",
"minimumAgentVersion": "3.232.1",
"demands": [],
"version": {
"Major": 1,
Expand All @@ -19,8 +20,7 @@
},
"deprecated": true,
"deprecationMessage": "This task version is deprecated and is no longer maintained. Please upgrade to the latest version to continue receiving fixes and features. More details: https://github.com/tinglesoftware/dependabot-azure-devops/discussions/1317.",
"instanceNameFormat": "Dependabot",
"minimumAgentVersion": "3.232.1",
"instanceNameFormat": "Dependabot update",
"groups": [
{
"name": "security_updates",
Expand Down Expand Up @@ -255,11 +255,9 @@
"helpMarkDown": "Ensure that the host ssh socket is forwarded to the container to authenticate with ssh"
}
],
"dataSourceBindings": [],
"execution": {
"Node20_1": {
"target": "index.js",
"argumentFormat": ""
"target": "index.js"
}
}
}
49 changes: 31 additions & 18 deletions extension/tasks/dependabotV2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ async function run() {
const prAuthorClient = new AzureDevOpsWebApiClient(
taskInputs.organizationUrl.toString(),
taskInputs.systemAccessToken,
taskInputs.debug,
);
const prApproverClient = taskInputs.autoApprove
? new AzureDevOpsWebApiClient(
taskInputs.organizationUrl.toString(),
taskInputs.autoApproveUserToken || taskInputs.systemAccessToken,
taskInputs.debug,
)
: null;

Expand All @@ -87,8 +89,9 @@ async function run() {
taskInputs,
prAuthorClient,
prApproverClient,
existingPullRequests,
existingBranchNames,
existingPullRequests,
taskInputs.debug,
),
taskInputs.debug,
);
Expand Down Expand Up @@ -161,24 +164,34 @@ async function run() {
}

// Run an update job for "all dependencies"; this will create new pull requests for dependencies that need updating
const dependenciesHaveVulnerabilities = dependencyNamesToUpdate.length && securityAdvisories.length;
if (!securityUpdatesOnly || dependenciesHaveVulnerabilities) {
failedTasks += handleUpdateOperationResults(
await dependabot.update(
DependabotJobBuilder.updateAllDependenciesJob(
taskInputs,
updateId,
update,
dependabotConfig.registries,
dependencyNamesToUpdate,
existingPullRequestDependenciesForPackageEcosystem,
securityAdvisories,
const openPullRequestsLimit = update['open-pull-requests-limit'];
const openPullRequestsCount = Object.entries(existingPullRequestsForPackageEcosystem).length;
const hasReachedOpenPullRequestLimit =
openPullRequestsLimit > 0 && openPullRequestsCount >= openPullRequestsLimit;
if (!hasReachedOpenPullRequestLimit) {
const dependenciesHaveVulnerabilities = dependencyNamesToUpdate.length && securityAdvisories.length;
if (!securityUpdatesOnly || dependenciesHaveVulnerabilities) {
failedTasks += handleUpdateOperationResults(
await dependabot.update(
DependabotJobBuilder.updateAllDependenciesJob(
taskInputs,
updateId,
update,
dependabotConfig.registries,
dependencyNamesToUpdate,
existingPullRequestDependenciesForPackageEcosystem,
securityAdvisories,
),
dependabotUpdaterOptions,
),
dependabotUpdaterOptions,
),
);
);
} else {
console.info('Nothing to update; dependencies are not affected by any known vulnerability');
}
} else {
console.info('Nothing to update; dependencies are not affected by any known vulnerability');
warning(
`Skipping update for ${packageEcosystem} packages as the open pull requests limit (${openPullRequestsLimit}) has already been reached`,
);
}

// If there are existing pull requests, run an update job for each one; this will resolve merge conflicts and close pull requests that are no longer needed
Expand All @@ -202,7 +215,7 @@ async function run() {
}
} else {
warning(
`Skipping update of ${numberOfPullRequestsToUpdate} existing pull request(s) as 'skipPullRequests' is set to 'true'`,
`Skipping update of ${numberOfPullRequestsToUpdate} existing ${packageEcosystem} package pull request(s) as 'skipPullRequests' is set to 'true'`,
);
}
}
Expand Down
12 changes: 5 additions & 7 deletions extension/tasks/dependabotV2/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@
"helpMarkDown": "For help please visit https://github.com/tinglesoftware/dependabot-azure-devops/issues",
"helpUrl": "https://github.com/tinglesoftware/dependabot-azure-devops/issues",
"releaseNotes": "https://github.com/tinglesoftware/dependabot-azure-devops/releases",
"category": "Utility",
"author": "Tingle Software",
"category": "Azure Pipelines",
"visibility": ["Build", "Release"],
"runsOn": ["Agent", "DeploymentGroup"],
"author": "Tingle Software",
"minimumAgentVersion": "3.232.1",
"demands": [],
"version": {
"Major": 2,
"Minor": 0,
"Patch": 0
},
"preview": true,
"instanceNameFormat": "Dependabot",
"minimumAgentVersion": "3.232.1",
"instanceNameFormat": "Dependabot update",
"groups": [
{
"name": "pull_requests",
Expand Down Expand Up @@ -229,11 +229,9 @@
"helpMarkDown": "Comma-seperated list of key/value pairs representing the enabled Dependabot experiments e.g. `experiments: 'tidy=true,vendor=true,goprivate=*'`. Available options vary depending on the package ecosystem. See [configuring experiments](https://github.com/tinglesoftware/dependabot-azure-devops/#configuring-experiments) for more details."
}
],
"dataSourceBindings": [],
"execution": {
"Node20_1": {
"target": "index.js",
"argumentFormat": ""
"target": "index.js"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { jest } from '@jest/globals';

import { VersionControlChangeType } from 'azure-devops-node-api/interfaces/TfvcInterfaces';

import { AzureDevOpsWebApiClient } from './AzureDevOpsWebApiClient';
import { ICreatePullRequest } from './interfaces/IPullRequest';
import exp = require('constants');

jest.mock('azure-devops-node-api');
jest.mock('azure-pipelines-task-lib/task');

describe('AzureDevOpsWebApiClient', () => {
const organisationApiUrl = 'https://dev.azure.com/mock-organization';
const accessToken = 'mock-access-token';
let client: AzureDevOpsWebApiClient;

beforeEach(() => {
client = new AzureDevOpsWebApiClient(organisationApiUrl, accessToken);
});

afterEach(() => {
jest.clearAllMocks();
});

describe('createPullRequest', () => {
let pr: ICreatePullRequest;

beforeEach(() => {
pr = {
project: 'project',
repository: 'repository',
source: {
branch: 'update-branch',
commit: 'commit-id',
},
target: {
branch: 'main',
},
title: 'PR Title',
description: 'PR Description',
commitMessage: 'Commit Message',
changes: [
{
path: 'file.txt',
content: 'hello world',
encoding: 'utf-8',
changeType: VersionControlChangeType.Add,
},
],
};
});

it('should create a pull request without duplicate reviewer and assignee identities', async () => {
// Arange
const mockGetUserId = jest.spyOn(client, 'getUserId').mockResolvedValue('my-user-id');
const mockResolveIdentityId = jest
.spyOn(client, 'resolveIdentityId')
.mockImplementation(async (identity?: string) => {
return identity || '';
});
const mockRestApiPost = jest
.spyOn(client as any, 'restApiPost')
.mockResolvedValueOnce({
commits: [{ commitId: 'new-commit-id' }],
})
.mockResolvedValueOnce({
pullRequestId: 1,
});
const mockRestApiPatch = jest.spyOn(client as any, 'restApiPatch').mockResolvedValueOnce({
count: 1,
});

// Act
pr.assignees = ['user1', 'user2'];
pr.reviewers = ['user1', 'user3'];
const pullRequestId = await client.createPullRequest(pr);

// Assert
expect(mockRestApiPost).toHaveBeenCalledTimes(2);
expect((mockRestApiPost.mock.calls[1] as any)[1].reviewers.length).toBe(3);
expect((mockRestApiPost.mock.calls[1] as any)[1].reviewers).toContainEqual({
id: 'user1',
isRequired: true,
isFlagged: true,
});
expect((mockRestApiPost.mock.calls[1] as any)[1].reviewers).toContainEqual({
id: 'user2',
isRequired: true,
isFlagged: true,
});
expect((mockRestApiPost.mock.calls[1] as any)[1].reviewers).toContainEqual({ id: 'user3' });
expect(pullRequestId).toBe(1);
});
});
});
Loading

0 comments on commit 5d738e5

Please sign in to comment.