Skip to content

Commit

Permalink
Merge pull request #139 from pangaeatech/add_outputs
Browse files Browse the repository at this point in the history
Added directory, package-ecosystem and target_branch to output
  • Loading branch information
Nishnha committed Feb 11, 2022
2 parents ffa0846 + aa297d4 commit 9fd8ff4
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 28 deletions.
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -37,6 +37,12 @@ Subsequent actions will have access to the following outputs:
- The highest semver change being made by this PR, e.g. `version-update:semver-major`. For all possible values, see [the `ignore` documentation](https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates#ignore).
- `steps.dependabot-metadata.outputs.updated-dependencies-json`
- A JSON string containing the full information about each updated Dependency.
- `steps.dependabot-metadata.outputs.directory`
- The `directory` configuration that was used by dependabot for this updated Dependency.
- `steps.dependabot-metadata.outputs.package-ecosystem`
- The `package-ecosystem` configuration that was used by dependabot for this updated Dependency.
- `steps.dependabot-metadata.outputs.target_branch`
- The `target_branch` configuration that was used by dependabot for this updated Dependency.

**Note:** These outputs will only be populated if the target Pull Request was opened by Dependabot and contains
**only** Dependabot-created commits.
Expand Down
6 changes: 6 additions & 0 deletions action.yml
Expand Up @@ -16,6 +16,12 @@ outputs:
description: 'The highest semver change being made by this PR, e.g. "version-update:semver-major"'
updated-dependencies-json:
description: 'A JSON string containing the full information about each updated Dependency.'
directory:
description: 'The `directory` configuration that was used by dependabot for this updated Dependency.'
package-ecosystem:
description: 'The `package-ecosystem` configuration that was used by dependabot for this updated Dependency.'
target_branch:
description: 'The `target_branch` configuration that was used by dependabot for this updated Dependency.'
runs:
using: 'node12'
main: 'dist/index.js'
40 changes: 36 additions & 4 deletions dist/index.js

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

62 changes: 52 additions & 10 deletions src/dependabot/output.test.ts
Expand Up @@ -14,7 +14,10 @@ test('when given a single dependency it sets its values', async () => {
{
dependencyName: 'coffee-rails',
dependencyType: 'direct:production',
updateType: 'version-update:semver-minor'
updateType: 'version-update:semver-minor',
directory: 'wwwroot',
packageEcosystem: 'nuget',
targetBranch: 'main'
}
]

Expand All @@ -29,29 +32,44 @@ test('when given a single dependency it sets its values', async () => {
expect(core.setOutput).toBeCalledWith('dependency-names', 'coffee-rails')
expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:production')
expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-minor')
expect(core.setOutput).toBeCalledWith('directory', 'wwwroot')
expect(core.setOutput).toBeCalledWith('package-ecosystem', 'nuget')
expect(core.setOutput).toBeCalledWith('target_branch', 'main')
})

test('when given a multiple dependencies, it uses the highest values for types', async () => {
const updatedDependencies = [
{
dependencyName: 'rspec',
dependencyType: 'direct:development',
updateType: 'version-update:semver-minor'
updateType: 'version-update:semver-minor',
directory: '',
packageEcosystem: '',
targetBranch: ''
},
{
dependencyName: 'coffee-rails',
dependencyType: 'indirect',
updateType: 'version-update:semver-minor'
updateType: 'version-update:semver-minor',
directory: '',
packageEcosystem: '',
targetBranch: ''
},
{
dependencyName: 'coffeescript',
dependencyType: 'indirect',
updateType: 'version-update:semver-major'
updateType: 'version-update:semver-major',
directory: '',
packageEcosystem: '',
targetBranch: ''
},
{
dependencyName: 'rspec-coffeescript',
dependencyType: 'indirect',
updateType: 'version-update:semver-patch'
updateType: 'version-update:semver-patch',
directory: '',
packageEcosystem: '',
targetBranch: ''
}
]

Expand All @@ -62,14 +80,20 @@ test('when given a multiple dependencies, it uses the highest values for types',
expect(core.setOutput).toBeCalledWith('dependency-names', 'rspec, coffee-rails, coffeescript, rspec-coffeescript')
expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:development')
expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-major')
expect(core.setOutput).toBeCalledWith('directory', '')
expect(core.setOutput).toBeCalledWith('package-ecosystem', '')
expect(core.setOutput).toBeCalledWith('target_branch', '')
})

test('when the dependency has no update type', async () => {
const updatedDependencies = [
{
dependencyName: 'coffee-rails',
dependencyType: 'direct:production',
updateType: ''
updateType: '',
directory: '',
packageEcosystem: '',
targetBranch: ''
}
]

Expand All @@ -84,29 +108,44 @@ test('when the dependency has no update type', async () => {
expect(core.setOutput).toBeCalledWith('dependency-names', 'coffee-rails')
expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:production')
expect(core.setOutput).toBeCalledWith('update-type', null)
expect(core.setOutput).toBeCalledWith('directory', '')
expect(core.setOutput).toBeCalledWith('package-ecosystem', '')
expect(core.setOutput).toBeCalledWith('target_branch', '')
})

test('when given a multiple dependencies, and some do not have update types', async () => {
const updatedDependencies = [
{
dependencyName: 'rspec',
dependencyType: 'direct:development',
updateType: ''
updateType: '',
directory: '',
packageEcosystem: '',
targetBranch: ''
},
{
dependencyName: 'coffee-rails',
dependencyType: 'indirect',
updateType: 'version-update:semver-minor'
updateType: 'version-update:semver-minor',
directory: '',
packageEcosystem: '',
targetBranch: ''
},
{
dependencyName: 'coffeescript',
dependencyType: 'indirect',
updateType: ''
updateType: '',
directory: '',
packageEcosystem: '',
targetBranch: ''
},
{
dependencyName: 'rspec-coffeescript',
dependencyType: 'indirect',
updateType: 'version-update:semver-patch'
updateType: 'version-update:semver-patch',
directory: '',
packageEcosystem: '',
targetBranch: ''
}
]

Expand All @@ -117,4 +156,7 @@ test('when given a multiple dependencies, and some do not have update types', as
expect(core.setOutput).toBeCalledWith('dependency-names', 'rspec, coffee-rails, coffeescript, rspec-coffeescript')
expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:development')
expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-minor')
expect(core.setOutput).toBeCalledWith('directory', '')
expect(core.setOutput).toBeCalledWith('package-ecosystem', '')
expect(core.setOutput).toBeCalledWith('target_branch', '')
})
11 changes: 11 additions & 0 deletions src/dependabot/output.ts
Expand Up @@ -20,16 +20,27 @@ export function set (updatedDependencies: Array<updatedDependency>): void {
const dependencyType = maxDependencyTypes(updatedDependencies)
const updateType = maxSemver(updatedDependencies)

const firstDependency = updatedDependencies[0]
const directory = firstDependency?.directory
const ecosystem = firstDependency?.packageEcosystem
const target = firstDependency?.targetBranch

core.startGroup(`Outputting metadata for ${Pluralize('updated dependency', updatedDependencies.length, true)}`)
core.info(`outputs.dependency-names: ${dependencyNames}`)
core.info(`outputs.dependency-type: ${dependencyType}`)
core.info(`outputs.update-type: ${updateType}`)
core.info(`outputs.directory: ${directory}`)
core.info(`outputs.package-ecosystem: ${ecosystem}`)
core.info(`outputs.target_branch: ${target}`)
core.endGroup()

core.setOutput('updated-dependencies-json', updatedDependencies)
core.setOutput('dependency-names', dependencyNames)
core.setOutput('dependency-type', dependencyType)
core.setOutput('update-type', updateType)
core.setOutput('directory', directory)
core.setOutput('package-ecosystem', ecosystem)
core.setOutput('target_branch', target)
}

function maxDependencyTypes (updatedDependencies: Array<updatedDependency>): string {
Expand Down
22 changes: 17 additions & 5 deletions src/dependabot/update_metadata.test.ts
@@ -1,7 +1,7 @@
import * as updateMetadata from './update_metadata'

test('it returns an empty array for a blank string', async () => {
expect(updateMetadata.parse('')).toEqual([])
expect(updateMetadata.parse('', 'dependabot/nuget/feature1', 'main')).toEqual([])
})

test('it returns an empty array for commit message with no dependabot yaml fragment', async () => {
Expand All @@ -12,7 +12,7 @@ test('it returns an empty array for commit message with no dependabot yaml fragm
Signed-off-by: dependabot[bot] <support@github.com>`

expect(updateMetadata.parse(commitMessage)).toEqual([])
expect(updateMetadata.parse(commitMessage, 'dependabot/nuget/feature1', 'main')).toEqual([])
})

test('it returns the updated dependency information when there is a yaml fragment', async () => {
Expand All @@ -31,13 +31,16 @@ test('it returns the updated dependency information when there is a yaml fragmen
'\n' +
'Signed-off-by: dependabot[bot] <support@github.com>'

const updatedDependencies = updateMetadata.parse(commitMessage)
const updatedDependencies = updateMetadata.parse(commitMessage, 'dependabot/nuget/feature1', 'main')

expect(updatedDependencies).toHaveLength(1)

expect(updatedDependencies[0].dependencyName).toEqual('coffee-rails')
expect(updatedDependencies[0].dependencyType).toEqual('direct:production')
expect(updatedDependencies[0].updateType).toEqual('version-update:semver-minor')
expect(updatedDependencies[0].directory).toEqual('/')
expect(updatedDependencies[0].packageEcosystem).toEqual('nuget')
expect(updatedDependencies[0].targetBranch).toEqual('main')
})

test('it supports multiple dependencies within a single fragment', async () => {
Expand All @@ -59,17 +62,23 @@ test('it supports multiple dependencies within a single fragment', async () => {
'\n' +
'Signed-off-by: dependabot[bot] <support@github.com>'

const updatedDependencies = updateMetadata.parse(commitMessage)
const updatedDependencies = updateMetadata.parse(commitMessage, 'dependabot/nuget/api/main/feature1', 'main')

expect(updatedDependencies).toHaveLength(2)

expect(updatedDependencies[0].dependencyName).toEqual('coffee-rails')
expect(updatedDependencies[0].dependencyType).toEqual('direct:production')
expect(updatedDependencies[0].updateType).toEqual('version-update:semver-minor')
expect(updatedDependencies[0].directory).toEqual('api/main')
expect(updatedDependencies[0].packageEcosystem).toEqual('nuget')
expect(updatedDependencies[0].targetBranch).toEqual('main')

expect(updatedDependencies[1].dependencyName).toEqual('coffeescript')
expect(updatedDependencies[1].dependencyType).toEqual('indirect')
expect(updatedDependencies[1].updateType).toEqual('version-update:semver-patch')
expect(updatedDependencies[1].directory).toEqual('api/main')
expect(updatedDependencies[1].packageEcosystem).toEqual('nuget')
expect(updatedDependencies[1].targetBranch).toEqual('main')
})

test('it only returns information within the first fragment if there are multiple yaml documents', async () => {
Expand All @@ -95,11 +104,14 @@ test('it only returns information within the first fragment if there are multipl
'\n' +
'Signed-off-by: dependabot[bot] <support@github.com>'

const updatedDependencies = updateMetadata.parse(commitMessage)
const updatedDependencies = updateMetadata.parse(commitMessage, 'dependabot|nuget|api|feature1', 'main')

expect(updatedDependencies).toHaveLength(1)

expect(updatedDependencies[0].dependencyName).toEqual('coffee-rails')
expect(updatedDependencies[0].dependencyType).toEqual('direct:production')
expect(updatedDependencies[0].updateType).toEqual('version-update:semver-minor')
expect(updatedDependencies[0].directory).toEqual('api')
expect(updatedDependencies[0].packageEcosystem).toEqual('nuget')
expect(updatedDependencies[0].targetBranch).toEqual('main')
})
17 changes: 14 additions & 3 deletions src/dependabot/update_metadata.ts
Expand Up @@ -4,20 +4,31 @@ export interface updatedDependency {
dependencyName: string,
dependencyType: string,
updateType: string,
directory: string,
packageEcosystem: string,
targetBranch: string
}

export function parse (commitMessage: string): Array<updatedDependency> {
export function parse (commitMessage: string, branchName: string, mainBranch: string): Array<updatedDependency> {
const yamlFragment = commitMessage.match(/^-{3}\n(?<dependencies>[\S|\s]*?)\n^\.{3}\n/m)

if (yamlFragment?.groups) {
if (yamlFragment?.groups && branchName.startsWith('dependabot')) {
const data = YAML.parse(yamlFragment.groups.dependencies)

// Since we are on the `dependabot` branch (9 letters), the 10th letter in the branch name is the delimiter
const delim = branchName[10]
const chunks = branchName.split(delim)
const dirname = chunks.slice(2, -1).join(delim) || '/'

if (data['updated-dependencies']) {
return data['updated-dependencies'].map(dependency => {
return {
dependencyName: dependency['dependency-name'],
dependencyType: dependency['dependency-type'],
updateType: dependency['update-type']
updateType: dependency['update-type'],
directory: dirname,
packageEcosystem: chunks[1],
targetBranch: mainBranch
}
})
}
Expand Down

0 comments on commit 9fd8ff4

Please sign in to comment.