Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#13 - Allow send files after the tag/release be created. #14

Closed
wants to merge 1 commit into from
Closed
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
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,21 @@ semanticRelease {
}
```

### Enable upload release files to GitHub

The **ghToken** is mandatory.

```groovy
semanticRelease {
changeLog {
releaseAsset = { ReleaseAssets assets, String currentTag ->
assets.upload(file("build/libs/value-${currentTag}.jar").bytes, "application/zip", "run-${currentTag}.jar")
}
}
}
```


### Setup travis-ci

First, you need to [configure the environment variable GH_TOKEN in travis](http://docs.travis-ci.com/user/environment-variables/). Then you need a `.travis.yml`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,14 @@ class SemanticReleaseChangeLogService {
def type = { Commit commit ->
def pattern = /(.*?)(?:\(.+\))?:.*/
def matcher = commit.shortMessage =~ pattern
matcher ? matcher.group(1) : null
matcher ? matcher.group(1).trim() : null
}

@PackageScope
def component = { Commit commit ->
def pattern = /.*?\((.+)\):.*/
def matcher = commit.shortMessage =~ pattern
matcher ? matcher.group(1) : null
matcher ? matcher.group(1).trim() : null
}

@PackageScope
Expand Down Expand Up @@ -207,6 +207,11 @@ class SemanticReleaseChangeLogService {
repositoryUrl("compare/${previousTag}...${currentTag}")
}

@PackageScope
def releaseAsset = { ReleaseAssets assets, String currentTag ->
// waiting the custom implementation
}

@PackageScope
@Memoized
List<Commit> commits(Version previousVersion) {
Expand Down Expand Up @@ -237,6 +242,7 @@ class SemanticReleaseChangeLogService {

Release release = repo.releases().create(tag)
new Release.Smart(release).body(changeLog(commits(Version.valueOf(version.previousVersion)), version).toString())
releaseAsset(release.assets(), "$version.version")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second parameter is named currentTag, but the instead the version is passed. The question is, if version and/or tag are necessary at all. The sample code in README.md could also be written as

assets.upload(tasks.jar.outputs.files.singleFile.bytes, "application/zip", tasks.jar.archiveName)

Alternatively, the closure could be named releaseAssets (plural) instead, without parameters, expected to return a List of files. And instead of calling releaseAsset(release.assets()), it would be

releaseAssets().each { release.assets().upload(it.bytes, URLConnection.guessContentTypeFromName(it.name), it.name) }

with

semanticRelease {
    changeLog {
        releaseAssets = {
            tasks.jar.outputs.files
        }
    }
}

But that is less powerful. What do you think?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we could define a member releaseAssets of type FileCollection and create a method releaseAssets(Object):

FileCollection releaseAssets = project.files()

def releaseAssets(Object... assets) {
    releaseAssets += project.files(assets)
}

The above would require some more changes, because the ChangelogService does not know the project yet. But it would allow the user of the plugin to just write

task sourceJar ...
task javadocZip ...
semanticRelease {
    changeLog {
        releaseAssets(jar, sourceJar, javadocZip)
    }
}

because project.files can handle Task instances and automatically uses the task outputs (https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:files(java.lang.Object[]))

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason, why I am in favor of the last suggestion: the usage of jcabi-github should be an implementation-detail. That's the reason, why the setter and getter of SemanticReleaseChangeLogService.github were marked as deprecated and will be removed in 2.0.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to send other kind of files too (.war, .exe), and a way to rename it. About of the file type the method URLConnection.guessContentTypeFromName() don't have all kind of files too.

We can have a default implementation but I don't know the best way to do it.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. URLConnection.guessContentTypeFromName() doesn't know a lot of file types. E.g. interestingly it does not support jar files.

Do you know, what github uses this information for? I currently have application/octet-stream as fallback.

The possibility to rename an asset or give a description -- which does not seem to be possible with jcabi-github, but is part of the github-api (https://developer.github.com/v3/repos/releases/#upload-a-release-asset) -- is a valid one. With my changes, the only way to achive giving a different name would be to create a copy-task and use that copy instead of the original file.

Thinking about this: by calling project.files() inside the plugin code masks the fact, that this only works for tasks that produce a single file (like Jar and Zip), but not for other tasks (like Copy. By removing this code in the ChangeLogService again and changing the method to void releaseAssets(FileCollection) the code of ChangeLogService would become more clear again, but the user of the plugin would have to write a little more code.

Or there could be some overloaded methods Asset releaseAsset(AbstractArchiveTask), Asset releaseAsset(File) and a new Class Asset with methods Asset contentType(String), Asset name(String) and Asset label(String). This would allow to write

semanticRelease {
    changeLog {
        releaseAsset jar contentType 'application/zip' name 'theapplication.jar' label 'The application'
        // or
        releaseAsset(sourcesJar).contentType("application/zip").name("thesources.jar").label("the sources jar")
    }
}

By changing the methods in the ChangeLogService to Asset releaseAsset(Map params = [:], AbstractArchiveTask task), the user could write releaseAsset sourcesJar, contentType: 'application/zip', name: 'thesources.jar', label: 'the sources jar' in their build file.

}

private boolean tagExists(Repo repo, String tag) {
Expand Down