Skip to content

Commit

Permalink
Set published-version github output after 'publish' task (#847)
Browse files Browse the repository at this point in the history
* Set published-version github output after 'publish' task

* Format outputs as JSON in case multiple values are provided

* Update docs
  • Loading branch information
radoslaw-panuszewski authored Oct 22, 2024
1 parent 099f892 commit 08cd3a4
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 41 deletions.
13 changes: 1 addition & 12 deletions docs/configuration/basic_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,7 @@ Version calculation rules:

### GitHub workflow context

If `release` task is executed in GitHub workflow it will generate an output variable `released-version`
that you can access later on in your workflow steps.

```
jobs:
build:
runs-on: ubuntu-latest
steps:
- id: release
run: ./gradlew release
- run: echo ${{steps.release.outputs.released-version}}
```
See [GitHub outputs](ci_servers.md#github-outputs)

## Accessing previous version

Expand Down
45 changes: 41 additions & 4 deletions docs/configuration/ci_servers.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,47 @@ This behavior is experimental and has been tested on the following CI servers:

`axion-release` has dedicated support for GitHub Actions and you don't need any custom configs to make it working.

Here's what Axion does for you under the hood:

- gets the original branch name for workflows triggered by `pull_request` -
see [versionWithBranch](version.md#versionwithbranch-default)
### GitHub outputs

To make it easier for you to chain jobs in a workflow, `axion-release` will provide some information as GitHub outputs.

| name | description |
|---------------------|---------------------------------------------|
| `released-version` | Provided after executing the `release` task |
| `published-version` | Provided after executing the `publish` task |

#### Multi-version builds

If all your Gradle modules use the same version, the output will be a single value, such as:
```
1.0.0
```

However, if each module has its own version, the output will be in JSON format, for example:
```json
{"root-project":"1.0.0","sub-project-1":"2.0.0","sub-project-2":"3.0.0"}
```
where `root-project`, `sub-project-1` and `sub-project-2` are project names from Gradle.

#### Example

```yaml
jobs:
build:
steps:
- id: release
run: ./gradlew release

# for single-version builds
- run: |
echo ${{ steps.release.outputs.released-version }}
# for multi-version builds
- run: |
echo ${{ fromJson(steps.release.outputs.released-version).root-project }}
echo ${{ fromJson(steps.release.outputs.released-version).sub-project-1 }}
echo ${{ fromJson(steps.release.outputs.released-version).sub-project-2 }}
```
## Jenkins
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,34 @@ class BaseIntegrationTest extends RepositoryBasedTest {
}

void buildFile(String contents) {
new FileTreeBuilder(temporaryFolder).file("build.gradle", """
plugins {
id 'pl.allegro.tech.build.axion-release'
}
""" + contents +
new FileTreeBuilder(temporaryFolder).file("build.gradle",
"""
plugins {
id 'pl.allegro.tech.build.axion-release'
}
project.version = scmVersion.version
scmVersion.ignoreGlobalGitConfig = true
""")
$contents
project.version = scmVersion.version
scmVersion.ignoreGlobalGitConfig = true
"""
)
}

void vanillaBuildFile(String contents) {
new FileTreeBuilder(temporaryFolder).file("build.gradle", contents)
}

void vanillaSubprojectBuildFile(String subprojectName, String contents) {
new FileTreeBuilder(temporaryFolder).dir(subprojectName) {
file("build.gradle", contents)
}
}

void vanillaSettingsFile(String contents) {
new FileTreeBuilder(temporaryFolder).file("settings.gradle", contents)
}

GradleRunner gradle() {
return GradleRunner.create()
.withProjectDir(temporaryFolder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,122 @@ class SimpleIntegrationTest extends BaseIntegrationTest {
result.task(":currentVersion").outcome == TaskOutcome.SUCCESS
}

def "should define a github output when running release task in github workflow context"() {
def "should set released-version github output after release task"(String task,
String rootProjectVersion,
String subprojectVersion,
String output) {
given:
def outputFile = File.createTempFile("github-outputs", ".tmp")
environmentVariablesRule.set("GITHUB_ACTIONS", "true")
environmentVariablesRule.set("GITHUB_OUTPUT", outputFile.getAbsolutePath())

buildFile('')
vanillaSettingsFile("""
rootProject.name = 'root-project'
include 'sub-project'
"""
)

vanillaBuildFile("""
plugins {
id 'pl.allegro.tech.build.axion-release'
}
scmVersion {
tag {
prefix = 'root-project-'
}
}
"""
)

vanillaSubprojectBuildFile("sub-project", """
plugins {
id 'pl.allegro.tech.build.axion-release'
}
scmVersion {
tag {
prefix = 'sub-project-'
}
}
"""
)

repository.tag("root-project-$rootProjectVersion")
repository.tag("sub-project-$subprojectVersion")
repository.commit(['.'], 'Some commit')

when:
runGradle('release', '-Prelease.version=1.0.0', '-Prelease.localOnly', '-Prelease.disableChecks')
runGradle(task, '-Prelease.localOnly', '-Prelease.disableChecks')

then:
def definedEnvVariables = outputFile.getText().lines().collect(toList())
definedEnvVariables.contains('released-version=1.0.0')
definedEnvVariables.contains(output)

cleanup:
environmentVariablesRule.clear("GITHUB_ACTIONS", "GITHUB_OUTPUT")

where:
task | rootProjectVersion | subprojectVersion || output
'release' | "1.0.0" | "1.0.0" || 'released-version=1.0.1'
'release' | "1.0.0" | "2.0.0" || 'released-version={"root-project":"1.0.1","sub-project":"2.0.1"}'
':release' | "1.0.0" | "2.0.0" || 'released-version=1.0.1'
':sub-project:release' | "1.0.0" | "2.0.0" || 'released-version=2.0.1'
}

def "should set published-version github output after publish task"(String task,
String rootProjectVersion,
String subprojectVersion,
String output) {
given:
def outputFile = File.createTempFile("github-outputs", ".tmp")
environmentVariablesRule.set("GITHUB_ACTIONS", "true")
environmentVariablesRule.set("GITHUB_OUTPUT", outputFile.getAbsolutePath())

vanillaSettingsFile("""
rootProject.name = 'root-project'
include 'sub-project'
"""
)

vanillaBuildFile("""
plugins {
id 'pl.allegro.tech.build.axion-release'
id 'maven-publish'
}
version = '$rootProjectVersion'
"""
)

vanillaSubprojectBuildFile("sub-project", """
plugins {
id 'pl.allegro.tech.build.axion-release'
id 'maven-publish'
}
version = '$subprojectVersion'
"""
)

when:
runGradle(task)

then:
def definedEnvVariables = outputFile.getText().lines().collect(toList())
definedEnvVariables.contains(output)

cleanup:
environmentVariablesRule.clear("GITHUB_ACTIONS", "GITHUB_OUTPUT")

where:
task | rootProjectVersion | subprojectVersion || output
'publish' | "1.0.0" | "1.0.0" || 'published-version=1.0.0'
'publish' | "1.0.0" | "2.0.0" || 'published-version={"root-project":"1.0.0","sub-project":"2.0.0"}'
':publish' | "1.0.0" | "2.0.0" || 'published-version=1.0.0'
':sub-project:publish' | "1.0.0" | "2.0.0" || 'published-version=2.0.0'
}

def "should return released version on calling cV on repo with release commit"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package pl.allegro.tech.build.axion.release

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import pl.allegro.tech.build.axion.release.domain.SnapshotDependenciesChecker
import pl.allegro.tech.build.axion.release.domain.VersionConfig
import pl.allegro.tech.build.axion.release.infrastructure.di.VersionResolutionContext
import pl.allegro.tech.build.axion.release.infrastructure.github.GithubService
import pl.allegro.tech.build.axion.release.util.FileLoader

abstract class ReleasePlugin implements Plugin<Project> {
Expand All @@ -21,7 +23,10 @@ abstract class ReleasePlugin implements Plugin<Project> {
void apply(Project project) {
FileLoader.setRoot(project.rootDir)

def versionConfig = project.extensions.create(VERSION_EXTENSION, VersionConfig, project.rootProject.layout.projectDirectory)
Provider<GithubService> githubService = project.gradle.sharedServices
.registerIfAbsent("github", GithubService) {}

VersionConfig versionConfig = project.extensions.create(VERSION_EXTENSION, VersionConfig, project.rootProject.layout.projectDirectory)

project.tasks.withType(BaseAxionTask).configureEach({
it.versionConfig = versionConfig
Expand All @@ -42,6 +47,8 @@ abstract class ReleasePlugin implements Plugin<Project> {
group = 'Release'
description = 'Performs release - creates tag and pushes it to remote.'
dependsOn(VERIFY_RELEASE_TASK)
it.projectName = project.name
it.githubService = githubService
}

project.tasks.register(CREATE_RELEASE_TASK, CreateReleaseTask) {
Expand All @@ -65,9 +72,25 @@ abstract class ReleasePlugin implements Plugin<Project> {
description = 'Prints current project version extracted from SCM.'
}

setGithubOutputsAfterPublishTask(project, githubService)

maybeDisableReleaseTasks(project, versionConfig)
}

private static setGithubOutputsAfterPublishTask(Project project, Provider<GithubService> githubService) {
String projectName = project.name
Provider<String> projectVersion = project.provider { project.version.toString() }

project.plugins.withId('maven-publish') {
project.tasks.named('publish') { task ->
task.usesService(githubService)
task.doLast {
githubService.get().setOutput('published-version', projectName, projectVersion.get())
}
}
}
}

private static void maybeDisableReleaseTasks(Project project, VersionConfig versionConfig) {
project.afterEvaluate {
def context = VersionResolutionContext.create(versionConfig, project.layout.projectDirectory)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package pl.allegro.tech.build.axion.release

import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import pl.allegro.tech.build.axion.release.domain.Releaser
import pl.allegro.tech.build.axion.release.domain.scm.ScmPushResult
import pl.allegro.tech.build.axion.release.domain.scm.ScmPushResultOutcome
import pl.allegro.tech.build.axion.release.infrastructure.di.VersionResolutionContext

import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
import pl.allegro.tech.build.axion.release.infrastructure.github.GithubService

abstract class ReleaseTask extends BaseAxionTask {

@Input
abstract Property<String> getProjectName()

@Internal
abstract Property<GithubService> getGithubService()

@TaskAction
void release() {
VersionResolutionContext context = resolutionContext()
Expand All @@ -28,13 +34,8 @@ abstract class ReleaseTask extends BaseAxionTask {
}

if (result.outcome === ScmPushResultOutcome.SUCCESS) {
if (System.getenv().containsKey('GITHUB_ACTIONS')) {
Files.write(
Paths.get(System.getenv('GITHUB_OUTPUT')),
"released-version=${versionConfig.uncached.decoratedVersion}\n".getBytes(),
StandardOpenOption.APPEND
)
}
String version = versionConfig.uncached.decoratedVersion
githubService.get().setOutput("released-version", projectName.get(), version)
}
}
}
Loading

0 comments on commit 08cd3a4

Please sign in to comment.