Migrated to 0.5 structure and updated documentation
This commit is contained in:
parent
187cb0b1f2
commit
c097b9bbfa
40
.drone.yml
40
.drone.yml
@ -1,39 +1,29 @@
|
|||||||
build:
|
workspace:
|
||||||
image: golang:1.5
|
base: /go
|
||||||
|
|
||||||
|
pipeline:
|
||||||
|
test:
|
||||||
|
image: golang:1.6
|
||||||
environment:
|
environment:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
commands:
|
commands:
|
||||||
- make deps
|
- go vet
|
||||||
- make vet
|
- go test -cover -coverprofile=coverage.out
|
||||||
- make build
|
- go build -ldflags "-s -w -X main.build=$DRONE_BUILD_NUMBER" -a -tags netgo
|
||||||
- make test
|
|
||||||
|
|
||||||
publish:
|
latest:
|
||||||
coverage:
|
image: docker
|
||||||
|
repo: plugins/github-release
|
||||||
|
tags: [ "latest", "1.0", "1" ]
|
||||||
when:
|
when:
|
||||||
branch: master
|
branch: master
|
||||||
docker:
|
event: push
|
||||||
username: $$DOCKER_USER
|
|
||||||
password: $$DOCKER_PASS
|
|
||||||
email: $$DOCKER_EMAIL
|
|
||||||
repo: plugins/drone-github-release
|
|
||||||
tag: latest
|
|
||||||
when:
|
|
||||||
branch: master
|
|
||||||
docker:
|
|
||||||
username: $$DOCKER_USER
|
|
||||||
password: $$DOCKER_PASS
|
|
||||||
email: $$DOCKER_EMAIL
|
|
||||||
repo: plugins/drone-github-release
|
|
||||||
tag: develop
|
|
||||||
when:
|
|
||||||
branch: develop
|
|
||||||
|
|
||||||
plugin:
|
plugin:
|
||||||
name: GitHub Release
|
name: GitHub Release
|
||||||
desc: Publish files and artifacts to GitHub Releases
|
desc: Publish files and artifacts to GitHub Releases
|
||||||
type: publish
|
type: publish
|
||||||
image: plugins/drone-github-release
|
image: plugins/github-release
|
||||||
labels:
|
labels:
|
||||||
- github
|
- github
|
||||||
- release
|
- release
|
||||||
|
1
.drone.yml.sig
Normal file
1
.drone.yml.sig
Normal file
@ -0,0 +1 @@
|
|||||||
|
eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9nbwoKcGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBnb2xhbmc6MS42CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBDR09fRU5BQkxFRD0wCiAgICBjb21tYW5kczoKICAgICAgLSBnbyB2ZXQKICAgICAgLSBnbyB0ZXN0IC1jb3ZlciAtY292ZXJwcm9maWxlPWNvdmVyYWdlLm91dAogICAgICAtIGdvIGJ1aWxkIC1sZGZsYWdzICItcyAtdyAtWCBtYWluLmJ1aWxkPSREUk9ORV9CVUlMRF9OVU1CRVIiIC1hIC10YWdzIG5ldGdvCgogIGxhdGVzdDoKICAgIGltYWdlOiBkb2NrZXIKICAgIHJlcG86IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICAgIHRhZ3M6IFsgImxhdGVzdCIsICIxLjAiLCAiMSIgXQogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKICAgICAgZXZlbnQ6IHB1c2gKCnBsdWdpbjoKICBuYW1lOiBHaXRIdWIgUmVsZWFzZQogIGRlc2M6IFB1Ymxpc2ggZmlsZXMgYW5kIGFydGlmYWN0cyB0byBHaXRIdWIgUmVsZWFzZXMKICB0eXBlOiBwdWJsaXNoCiAgaW1hZ2U6IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICBsYWJlbHM6CiAgICAtIGdpdGh1YgogICAgLSByZWxlYXNlCg.5FZW1Auk18CljY9LW5P82r9RM_spPCYMYg82PFj2irM
|
71
DOCS.md
71
DOCS.md
@ -1,30 +1,61 @@
|
|||||||
Use this plugin for publishing files and artifacts to GitHub releases. You
|
Use this plugin for publishing files and artifacts to GitHub releases. Be aware
|
||||||
can override the default configuration with the following parameters:
|
that you can use this plugin only for tags, GitHub doesn't support the release
|
||||||
|
of branches.
|
||||||
|
|
||||||
* `api_key` - GitHub oauth token with public_repo or repo permission
|
## Config
|
||||||
* `files` - Files to upload to GitHub Release, globs are allowed
|
|
||||||
* `file_exists` - What to do if an file asset already exists, supported values: **overwrite** (default), **skip** and **fail**
|
|
||||||
* `checksum` - Checksum takes hash methods to include in your GitHub release for the files specified. Supported hash methods include md5, sha1, sha256, sha512, adler32, and crc32.
|
|
||||||
* `draft` - create a draft release if set to true
|
|
||||||
* `base_url` - GitHub base URL, only required for GHE
|
|
||||||
* `upload_url` - GitHub upload URL, only required for GHE
|
|
||||||
|
|
||||||
Sample configuration:
|
The following parameters are used to configure the plugin:
|
||||||
|
|
||||||
```yaml
|
* **api_key** - GitHub oauth token with public_repo or repo permission
|
||||||
publish:
|
* **files** - files to upload to GitHub Release, globs are allowed
|
||||||
github_release:
|
* **file_exists** - what to do if an file asset already exists, supported values: **overwrite** (default), **skip** and **fail**
|
||||||
api_key: my_github_api_key
|
* **checksum** - checksum takes hash methods to include in your GitHub release for the files specified. Supported hash methods include md5, sha1, sha256, sha512, adler32, and crc32.
|
||||||
files: dist/*
|
* **draft** - create a draft release if set to true
|
||||||
checksum: sha1
|
* **base_url** - GitHub base URL, only required for GHE
|
||||||
|
* **upload_url** - GitHub upload URL, only required for GHE
|
||||||
|
|
||||||
|
The following secret values can be set to configure the plugin.
|
||||||
|
|
||||||
|
* **GITHUB_RELEASE_API_KEY** - corresponds to **api_key**
|
||||||
|
* **GITHUB_RELEASE_BASE_URL** - corresponds to **base_url**
|
||||||
|
* **GITHUB_RELEASE_UPLOAD_URL** - corresponds to **upload_url**
|
||||||
|
|
||||||
|
It is highly recommended to put the **GITHUB_RELEASE_API_KEY** into a secret so
|
||||||
|
it is not exposed to users. This can be done using the drone-cli.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
drone secret add --image=plugins/github-release \
|
||||||
|
octocat/hello-world GITHUB_RELEASE_API_KEY my_github_api_key
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
Then sign the YAML file after all secrets are added.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
drone sign octocat/hello-world
|
||||||
|
```
|
||||||
|
|
||||||
|
See [secrets](http://readme.drone.io/0.5/usage/secrets/) for additional
|
||||||
|
information on secrets
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
The following is a sample configuration in your .drone.yml file:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
publish:
|
pipeline:
|
||||||
github_release:
|
github_release:
|
||||||
api_key: my_github_api_key
|
image: plugins/github-release
|
||||||
|
files: dist/*
|
||||||
|
when:
|
||||||
|
event: tag
|
||||||
|
```
|
||||||
|
|
||||||
|
An example for generating checksums and upload additional files:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
pipeline:
|
||||||
|
github_release:
|
||||||
|
image: plugins/github-release
|
||||||
files:
|
files:
|
||||||
- dist/*
|
- dist/*
|
||||||
- bin/binary.exe
|
- bin/binary.exe
|
||||||
@ -35,4 +66,6 @@ publish:
|
|||||||
- sha512
|
- sha512
|
||||||
- adler32
|
- adler32
|
||||||
- crc32
|
- crc32
|
||||||
|
when:
|
||||||
|
event: tag
|
||||||
```
|
```
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
# Docker image for the Drone GitHub Release plugin
|
FROM alpine:3.4
|
||||||
#
|
|
||||||
# cd $GOPATH/src/github.com/drone-plugins/drone-github-release
|
|
||||||
# make deps build docker
|
|
||||||
|
|
||||||
FROM alpine:3.3
|
|
||||||
|
|
||||||
RUN apk update && \
|
RUN apk update && \
|
||||||
apk add \
|
apk add \
|
||||||
|
132
README.md
132
README.md
@ -1,117 +1,53 @@
|
|||||||
# drone-github-release
|
# drone-github-release
|
||||||
|
|
||||||
[![Build Status](http://beta.drone.io/api/badges/drone-plugins/drone-github-release/status.svg)](http://beta.drone.io/drone-plugins/drone-github-release)
|
[![Build Status](http://beta.drone.io/api/badges/drone-plugins/drone-github-release/status.svg)](http://beta.drone.io/drone-plugins/drone-github-release)
|
||||||
[![Coverage Status](https://aircover.co/badges/drone-plugins/drone-github-release/coverage.svg)](https://aircover.co/drone-plugins/drone-github-release)
|
[![Go Doc](https://godoc.org/github.com/drone-plugins/drone-github-release?status.svg)](http://godoc.org/github.com/drone-plugins/drone-github-release)
|
||||||
[![](https://badge.imagelayers.io/plugins/drone-github-release:latest.svg)](https://imagelayers.io/?images=plugins/drone-github-release:latest 'Get your own badge on imagelayers.io')
|
[![Go Report](https://goreportcard.com/badge/github.com/drone-plugins/drone-github-release)](https://goreportcard.com/report/github.com/drone-plugins/drone-github-release)
|
||||||
|
[![Join the chat at https://gitter.im/drone/drone](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/drone/drone)
|
||||||
|
|
||||||
Drone plugin to publish files and artifacts to GitHub Release. For the usage information and a listing of the available options please take a look at [the docs](DOCS.md).
|
Drone plugin to publish files and artifacts to GitHub Release. For the usage
|
||||||
|
information and a listing of the available options please take a look at
|
||||||
|
[the docs](DOCS.md).
|
||||||
|
|
||||||
## Binary
|
## Build
|
||||||
|
|
||||||
Build the binary using `make`:
|
Build the binary with the following commands:
|
||||||
|
|
||||||
```
|
```
|
||||||
make deps build
|
go build
|
||||||
```
|
go test
|
||||||
|
|
||||||
### Example
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./drone-github-release <<EOF
|
|
||||||
{
|
|
||||||
"repo": {
|
|
||||||
"clone_url": "git://github.com/drone/drone",
|
|
||||||
"owner": "drone",
|
|
||||||
"name": "drone",
|
|
||||||
"full_name": "drone/drone"
|
|
||||||
},
|
|
||||||
"system": {
|
|
||||||
"link_url": "https://beta.drone.io"
|
|
||||||
},
|
|
||||||
"build": {
|
|
||||||
"number": 22,
|
|
||||||
"status": "success",
|
|
||||||
"started_at": 1421029603,
|
|
||||||
"finished_at": 1421029813,
|
|
||||||
"message": "Update the Readme",
|
|
||||||
"author": "johnsmith",
|
|
||||||
"author_email": "john.smith@gmail.com"
|
|
||||||
"event": "push",
|
|
||||||
"branch": "master",
|
|
||||||
"commit": "436b7a6e2abaddfd35740527353e78a227ddcb2c",
|
|
||||||
"ref": "refs/heads/master"
|
|
||||||
},
|
|
||||||
"workspace": {
|
|
||||||
"root": "/drone/src",
|
|
||||||
"path": "/drone/src/github.com/drone/drone"
|
|
||||||
},
|
|
||||||
"vargs": {
|
|
||||||
"api_key": "your_api_key",
|
|
||||||
"files": [
|
|
||||||
"dist/*.txt",
|
|
||||||
"dist/other-file"
|
|
||||||
],
|
|
||||||
"checksum": [
|
|
||||||
"sha1",
|
|
||||||
"sha256",
|
|
||||||
"sha512"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
Build the container using `make`:
|
Build the docker image with the following commands:
|
||||||
|
|
||||||
```
|
```
|
||||||
make deps docker
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo
|
||||||
|
docker build --rm=true -t plugins/github-release .
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example
|
Please note incorrectly building the image for the correct x64 linux and with
|
||||||
|
GCO disabled will result in an error when running the Docker image:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker: Error response from daemon: Container command
|
||||||
|
'/bin/drone-github-release' not found or does not exist..
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Execute from the working directory:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker run -i plugins/drone-github-release <<EOF
|
docker run --rm \
|
||||||
{
|
-e DRONE_BUILD_EVENT=tag \
|
||||||
"repo": {
|
-e DRONE_REPO_OWNER=octocat \
|
||||||
"clone_url": "git://github.com/drone/drone",
|
-e DRONE_REPO_NAME=foo \
|
||||||
"owner": "drone",
|
-e DRONE_COMMIT_REF=refs/heads/master \
|
||||||
"name": "drone",
|
-e PLUGIN_API_KEY=${HOME}/.ssh/id_rsa \
|
||||||
"full_name": "drone/drone"
|
-e PLUGIN_FILES=master \
|
||||||
},
|
-v $(pwd):$(pwd) \
|
||||||
"system": {
|
-w $(pwd) \
|
||||||
"link_url": "https://beta.drone.io"
|
plugins/github-release
|
||||||
},
|
|
||||||
"build": {
|
|
||||||
"number": 22,
|
|
||||||
"status": "success",
|
|
||||||
"started_at": 1421029603,
|
|
||||||
"finished_at": 1421029813,
|
|
||||||
"message": "Update the Readme",
|
|
||||||
"author": "johnsmith",
|
|
||||||
"author_email": "john.smith@gmail.com"
|
|
||||||
"event": "push",
|
|
||||||
"branch": "master",
|
|
||||||
"commit": "436b7a6e2abaddfd35740527353e78a227ddcb2c",
|
|
||||||
"ref": "refs/heads/master"
|
|
||||||
},
|
|
||||||
"workspace": {
|
|
||||||
"root": "/drone/src",
|
|
||||||
"path": "/drone/src/github.com/drone/drone"
|
|
||||||
},
|
|
||||||
"vargs": {
|
|
||||||
"api_key": "your_api_key",
|
|
||||||
"files": [
|
|
||||||
"dist/*.txt",
|
|
||||||
"dist/other-file"
|
|
||||||
],
|
|
||||||
"checksum": [
|
|
||||||
"sha1",
|
|
||||||
"sha256",
|
|
||||||
"sha512"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
```
|
```
|
||||||
|
38
checksum.go
38
checksum.go
@ -1,38 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"fmt"
|
|
||||||
"hash/adler32"
|
|
||||||
"hash/crc32"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func checksum(r io.Reader, method string) (string, error) {
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch method {
|
|
||||||
case "md5":
|
|
||||||
return fmt.Sprintf("%x", md5.Sum(b)), nil
|
|
||||||
case "sha1":
|
|
||||||
return fmt.Sprintf("%x", sha1.Sum(b)), nil
|
|
||||||
case "sha256":
|
|
||||||
return fmt.Sprintf("%x", sha256.Sum256(b)), nil
|
|
||||||
case "sha512":
|
|
||||||
return fmt.Sprintf("%x", sha512.Sum512(b)), nil
|
|
||||||
case "adler32":
|
|
||||||
return strconv.FormatUint(uint64(adler32.Checksum(b)), 10), nil
|
|
||||||
case "crc32":
|
|
||||||
return strconv.FormatUint(uint64(crc32.ChecksumIEEE(b)), 10), nil
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("hashing method %s is not supported", method)
|
|
||||||
}
|
|
||||||
}
|
|
364
main.go
364
main.go
@ -2,276 +2,120 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone-go/drone"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/drone/drone-go/plugin"
|
"github.com/joho/godotenv"
|
||||||
"github.com/google/go-github/github"
|
"github.com/urfave/cli"
|
||||||
"golang.org/x/oauth2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var build = "0" // build number set at compile-time
|
||||||
buildCommit string
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Printf("Drone GitHub Release Plugin built from %s\n", buildCommit)
|
app := cli.NewApp()
|
||||||
|
app.Name = "github-release plugin"
|
||||||
|
app.Usage = "github-release plugin"
|
||||||
|
app.Action = run
|
||||||
|
app.Version = fmt.Sprintf("1.0.%s", build)
|
||||||
|
app.Flags = []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "api-key",
|
||||||
|
Usage: "api key to access github api",
|
||||||
|
EnvVar: "PLUGIN_API_KEY,GITHUB_RELEASE_API_KEY",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "files",
|
||||||
|
Usage: "list of files to upload",
|
||||||
|
EnvVar: "PLUGIN_FILES,GITHUB_RELEASE_FILES",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "file-exists",
|
||||||
|
Value: "overwrite",
|
||||||
|
Usage: "what to do if file already exist",
|
||||||
|
EnvVar: "PLUGIN_FILE_EXISTS,GITHUB_RELEASE_FILE_EXISTS",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "checksum",
|
||||||
|
Usage: "generate specific checksums",
|
||||||
|
EnvVar: "PLUGIN_CHECKSUM,GITHUB_RELEASE_CHECKSUM",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "draft",
|
||||||
|
Usage: "create a draft release",
|
||||||
|
EnvVar: "PLUGIN_DRAFT,GITHUB_RELEASE_DRAFT",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "base-url",
|
||||||
|
Value: "https://api.github.com/",
|
||||||
|
Usage: "api url, needs to be changed for ghe",
|
||||||
|
EnvVar: "PLUGIN_BASE_URL,GITHUB_RELEASE_BASE_URL",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "upload-url",
|
||||||
|
Value: "https://uploads.github.com/",
|
||||||
|
Usage: "upload url, needs to be changed for ghe",
|
||||||
|
EnvVar: "PLUGIN_UPLOAD_URL,GITHUB_RELEASE_UPLOAD_URL",
|
||||||
|
},
|
||||||
|
|
||||||
workspace := drone.Workspace{}
|
cli.StringFlag{
|
||||||
repo := drone.Repo{}
|
Name: "repo.owner",
|
||||||
build := drone.Build{}
|
Usage: "repository owner",
|
||||||
vargs := Params{}
|
EnvVar: "DRONE_REPO_OWNER",
|
||||||
|
},
|
||||||
plugin.Param("workspace", &workspace)
|
cli.StringFlag{
|
||||||
plugin.Param("repo", &repo)
|
Name: "repo.name",
|
||||||
plugin.Param("build", &build)
|
Usage: "repository name",
|
||||||
plugin.Param("vargs", &vargs)
|
EnvVar: "DRONE_REPO_NAME",
|
||||||
plugin.MustParse()
|
},
|
||||||
|
cli.StringFlag{
|
||||||
if build.Event != "tag" {
|
Name: "build.event",
|
||||||
fmt.Printf("The GitHub Release plugin is only available for tags\n")
|
Value: "push",
|
||||||
os.Exit(0)
|
Usage: "build event",
|
||||||
|
EnvVar: "DRONE_BUILD_EVENT",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "commit.ref",
|
||||||
|
Value: "refs/heads/master",
|
||||||
|
Usage: "git commit ref",
|
||||||
|
EnvVar: "DRONE_COMMIT_REF",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "env-file",
|
||||||
|
Usage: "source env file",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if vargs.FileExists == "" {
|
if err := app.Run(os.Args); err != nil {
|
||||||
vargs.FileExists = "overwrite"
|
logrus.Fatal(err)
|
||||||
}
|
|
||||||
if !fileExistsValues[vargs.FileExists] {
|
|
||||||
fmt.Printf("invalid value for file_exists: use [empty], overwrite, skip or fail")
|
|
||||||
}
|
|
||||||
|
|
||||||
if vargs.BaseURL == "" {
|
|
||||||
vargs.BaseURL = "https://api.github.com/"
|
|
||||||
} else if !strings.HasSuffix(vargs.BaseURL, "/") {
|
|
||||||
vargs.BaseURL = vargs.BaseURL + "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
if vargs.UploadURL == "" {
|
|
||||||
vargs.UploadURL = "https://uploads.github.com/"
|
|
||||||
} else if !strings.HasSuffix(vargs.UploadURL, "/") {
|
|
||||||
vargs.UploadURL = vargs.UploadURL + "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
if vargs.APIKey == "" {
|
|
||||||
fmt.Printf("You must provide an API key\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if workspace.Path != "" {
|
|
||||||
os.Chdir(workspace.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
var files []string
|
|
||||||
for _, glob := range vargs.Files.Slice() {
|
|
||||||
globed, err := filepath.Glob(glob)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to glob %s\n", glob)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if globed != nil {
|
|
||||||
files = append(files, globed...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if vargs.Checksum.Len() > 0 {
|
|
||||||
var err error
|
|
||||||
files, err = writeChecksums(files, vargs.Checksum.Slice())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
baseURL, err := url.Parse(vargs.BaseURL)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to parse base URL\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadURL, err := url.Parse(vargs.UploadURL)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to parse upload URL\n")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: vargs.APIKey})
|
|
||||||
tc := oauth2.NewClient(oauth2.NoContext, ts)
|
|
||||||
|
|
||||||
client := github.NewClient(tc)
|
|
||||||
client.BaseURL = baseURL
|
|
||||||
client.UploadURL = uploadURL
|
|
||||||
|
|
||||||
rc := releaseClient{
|
|
||||||
Client: client,
|
|
||||||
Owner: repo.Owner,
|
|
||||||
Repo: repo.Name,
|
|
||||||
Tag: filepath.Base(build.Ref),
|
|
||||||
Draft: vargs.Draft,
|
|
||||||
FileExists: vargs.FileExists,
|
|
||||||
}
|
|
||||||
|
|
||||||
release, err := rc.buildRelease()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rc.uploadFiles(*release.ID, files); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileExistsValues = map[string]bool{
|
func run(c *cli.Context) error {
|
||||||
"overwrite": true,
|
if c.String("env-file") != "" {
|
||||||
"fail": true,
|
_ = godotenv.Load(c.String("env-file"))
|
||||||
"skip": true,
|
}
|
||||||
}
|
|
||||||
|
plugin := Plugin{
|
||||||
// Release holds ties the drone env data and github client together.
|
Repo: Repo{
|
||||||
type releaseClient struct {
|
Owner: c.String("repo.owner"),
|
||||||
*github.Client
|
Name: c.String("repo.name"),
|
||||||
Owner string
|
},
|
||||||
Repo string
|
Build: Build{
|
||||||
Tag string
|
Event: c.String("build.event"),
|
||||||
Draft bool
|
},
|
||||||
FileExists string
|
Commit: Commit{
|
||||||
}
|
Ref: c.String("commit.sha"),
|
||||||
|
},
|
||||||
func (rc *releaseClient) buildRelease() (*github.RepositoryRelease, error) {
|
Config: Config{
|
||||||
|
APIKey: c.String("api-key"),
|
||||||
// first attempt to get a release by that tag
|
Files: c.StringSlice("api-key"),
|
||||||
release, err := rc.getRelease()
|
FileExists: c.String("file-exists"),
|
||||||
if err != nil && release == nil {
|
Checksum: c.StringSlice("checksum"),
|
||||||
fmt.Println(err)
|
Draft: c.Bool("draft"),
|
||||||
} else if release != nil {
|
BaseURL: c.String("base-url"),
|
||||||
return release, nil
|
UploadURL: c.String("upload-url"),
|
||||||
}
|
},
|
||||||
|
}
|
||||||
// if no release was found by that tag, create a new one
|
|
||||||
release, err = rc.newRelease()
|
return plugin.Exec()
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to retrieve or create a release: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return release, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *releaseClient) getRelease() (*github.RepositoryRelease, error) {
|
|
||||||
release, _, err := rc.Client.Repositories.GetReleaseByTag(rc.Owner, rc.Repo, rc.Tag)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Release %s not found", rc.Tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Successfully retrieved %s release\n", rc.Tag)
|
|
||||||
return release, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *releaseClient) newRelease() (*github.RepositoryRelease, error) {
|
|
||||||
rr := &github.RepositoryRelease{
|
|
||||||
TagName: github.String(rc.Tag),
|
|
||||||
Draft: &rc.Draft,
|
|
||||||
}
|
|
||||||
release, _, err := rc.Client.Repositories.CreateRelease(rc.Owner, rc.Repo, rr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to create release: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Successfully created %s release\n", rc.Tag)
|
|
||||||
return release, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *releaseClient) uploadFiles(id int, files []string) error {
|
|
||||||
assets, _, err := rc.Client.Repositories.ListReleaseAssets(rc.Owner, rc.Repo, id, &github.ListOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to fetch existing assets: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var uploadFiles []string
|
|
||||||
files:
|
|
||||||
for _, file := range files {
|
|
||||||
for _, asset := range assets {
|
|
||||||
if *asset.Name == path.Base(file) {
|
|
||||||
switch rc.FileExists {
|
|
||||||
case "overwrite":
|
|
||||||
// do nothing
|
|
||||||
case "fail":
|
|
||||||
return fmt.Errorf("Asset file %s already exists", path.Base(file))
|
|
||||||
case "skip":
|
|
||||||
fmt.Printf("Skipping pre-existing %s artifact\n", *asset.Name)
|
|
||||||
continue files
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("Internal error, unkown file_exist value %s", rc.FileExists)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uploadFiles = append(uploadFiles, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range uploadFiles {
|
|
||||||
handle, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Failed to read %s artifact: %s", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, asset := range assets {
|
|
||||||
if *asset.Name == path.Base(file) {
|
|
||||||
if _, err := rc.Client.Repositories.DeleteReleaseAsset(rc.Owner, rc.Repo, *asset.ID); err != nil {
|
|
||||||
return fmt.Errorf("Failed to delete %s artifact: %s", file, err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully deleted old %s artifact\n", *asset.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uo := &github.UploadOptions{Name: path.Base(file)}
|
|
||||||
if _, _, err = rc.Client.Repositories.UploadReleaseAsset(rc.Owner, rc.Repo, id, uo, handle); err != nil {
|
|
||||||
return fmt.Errorf("Failed to upload %s artifact: %s", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Successfully uploaded %s artifact\n", file)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeChecksums(files, methods []string) ([]string, error) {
|
|
||||||
|
|
||||||
checksums := make(map[string][]string)
|
|
||||||
for _, method := range methods {
|
|
||||||
for _, file := range files {
|
|
||||||
handle, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Failed to read %s artifact: %s", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := checksum(handle, method)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
checksums[method] = append(checksums[method], hash, file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for method, results := range checksums {
|
|
||||||
filename := method + "sum.txt"
|
|
||||||
f, err := os.Create(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(results); i += 2 {
|
|
||||||
hash := results[i]
|
|
||||||
file := results[i+1]
|
|
||||||
if _, err := f.WriteString(fmt.Sprintf("%s %s\n", hash, file)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
files = append(files, filename)
|
|
||||||
}
|
|
||||||
return files, nil
|
|
||||||
}
|
}
|
||||||
|
134
plugin.go
Normal file
134
plugin.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/go-github/github"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Repo struct {
|
||||||
|
Owner string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
Build struct {
|
||||||
|
Event string
|
||||||
|
}
|
||||||
|
|
||||||
|
Commit struct {
|
||||||
|
Ref string
|
||||||
|
}
|
||||||
|
|
||||||
|
Config struct {
|
||||||
|
APIKey string
|
||||||
|
Files []string
|
||||||
|
FileExists string
|
||||||
|
Checksum []string
|
||||||
|
Draft bool
|
||||||
|
BaseURL string
|
||||||
|
UploadURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin struct {
|
||||||
|
Repo Repo
|
||||||
|
Build Build
|
||||||
|
Commit Commit
|
||||||
|
Config Config
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p Plugin) Exec() error {
|
||||||
|
var (
|
||||||
|
files []string
|
||||||
|
)
|
||||||
|
|
||||||
|
if p.Build.Event != "tag" {
|
||||||
|
return fmt.Errorf("The GitHub Release plugin is only available for tags")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Config.APIKey == "" {
|
||||||
|
return fmt.Errorf("You must provide an API key")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fileExistsValues[p.Config.FileExists] {
|
||||||
|
return fmt.Errorf("Invalid value for file_exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasSuffix(p.Config.BaseURL, "/") {
|
||||||
|
p.Config.BaseURL = p.Config.BaseURL + "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasSuffix(p.Config.UploadURL, "/") {
|
||||||
|
p.Config.UploadURL = p.Config.UploadURL + "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, glob := range p.Config.Files {
|
||||||
|
globed, err := filepath.Glob(glob)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to glob %s. %s", glob, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if globed != nil {
|
||||||
|
files = append(files, globed...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Config.Checksum) > 0 {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
files, err = writeChecksums(files, p.Config.Checksum)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to write checksums. %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
baseURL, err := url.Parse(p.Config.BaseURL)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse base URL. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadURL, err := url.Parse(p.Config.UploadURL)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to parse upload URL. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: p.Config.APIKey})
|
||||||
|
tc := oauth2.NewClient(oauth2.NoContext, ts)
|
||||||
|
|
||||||
|
client := github.NewClient(tc)
|
||||||
|
|
||||||
|
client.BaseURL = baseURL
|
||||||
|
client.UploadURL = uploadURL
|
||||||
|
|
||||||
|
rc := releaseClient{
|
||||||
|
Client: client,
|
||||||
|
Owner: p.Repo.Owner,
|
||||||
|
Repo: p.Repo.Name,
|
||||||
|
Tag: filepath.Base(p.Commit.Ref),
|
||||||
|
Draft: p.Config.Draft,
|
||||||
|
FileExists: p.Config.FileExists,
|
||||||
|
}
|
||||||
|
|
||||||
|
release, err := rc.buildRelease()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to create the release. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rc.uploadFiles(*release.ID, files); err != nil {
|
||||||
|
return fmt.Errorf("Failed to upload the files. %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
125
release.go
Normal file
125
release.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/google/go-github/github"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Release holds ties the drone env data and github client together.
|
||||||
|
type releaseClient struct {
|
||||||
|
*github.Client
|
||||||
|
Owner string
|
||||||
|
Repo string
|
||||||
|
Tag string
|
||||||
|
Draft bool
|
||||||
|
FileExists string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *releaseClient) buildRelease() (*github.RepositoryRelease, error) {
|
||||||
|
// first attempt to get a release by that tag
|
||||||
|
release, err := rc.getRelease()
|
||||||
|
|
||||||
|
if err != nil && release == nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
} else if release != nil {
|
||||||
|
return release, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no release was found by that tag, create a new one
|
||||||
|
release, err = rc.newRelease()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to retrieve or create a release: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return release, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *releaseClient) getRelease() (*github.RepositoryRelease, error) {
|
||||||
|
release, _, err := rc.Client.Repositories.GetReleaseByTag(rc.Owner, rc.Repo, rc.Tag)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Release %s not found", rc.Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully retrieved %s release\n", rc.Tag)
|
||||||
|
return release, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *releaseClient) newRelease() (*github.RepositoryRelease, error) {
|
||||||
|
rr := &github.RepositoryRelease{
|
||||||
|
TagName: github.String(rc.Tag),
|
||||||
|
Draft: &rc.Draft,
|
||||||
|
}
|
||||||
|
|
||||||
|
release, _, err := rc.Client.Repositories.CreateRelease(rc.Owner, rc.Repo, rr)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to create release: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully created %s release\n", rc.Tag)
|
||||||
|
return release, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *releaseClient) uploadFiles(id int, files []string) error {
|
||||||
|
assets, _, err := rc.Client.Repositories.ListReleaseAssets(rc.Owner, rc.Repo, id, &github.ListOptions{})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to fetch existing assets: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var uploadFiles []string
|
||||||
|
|
||||||
|
files:
|
||||||
|
for _, file := range files {
|
||||||
|
for _, asset := range assets {
|
||||||
|
if *asset.Name == path.Base(file) {
|
||||||
|
switch rc.FileExists {
|
||||||
|
case "overwrite":
|
||||||
|
// do nothing
|
||||||
|
case "fail":
|
||||||
|
return fmt.Errorf("Asset file %s already exists", path.Base(file))
|
||||||
|
case "skip":
|
||||||
|
fmt.Printf("Skipping pre-existing %s artifact\n", *asset.Name)
|
||||||
|
continue files
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Internal error, unkown file_exist value %s", rc.FileExists)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFiles = append(uploadFiles, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range uploadFiles {
|
||||||
|
handle, err := os.Open(file)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to read %s artifact: %s", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, asset := range assets {
|
||||||
|
if *asset.Name == path.Base(file) {
|
||||||
|
if _, err := rc.Client.Repositories.DeleteReleaseAsset(rc.Owner, rc.Repo, *asset.ID); err != nil {
|
||||||
|
return fmt.Errorf("Failed to delete %s artifact: %s", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully deleted old %s artifact\n", *asset.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uo := &github.UploadOptions{Name: path.Base(file)}
|
||||||
|
|
||||||
|
if _, _, err = rc.Client.Repositories.UploadReleaseAsset(rc.Owner, rc.Repo, id, uo, handle); err != nil {
|
||||||
|
return fmt.Errorf("Failed to upload %s artifact: %s", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully uploaded %s artifact\n", file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
14
types.go
14
types.go
@ -1,14 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "github.com/drone/drone-go/drone"
|
|
||||||
|
|
||||||
// Params are the parameters that the GitHub Release plugin can parse.
|
|
||||||
type Params struct {
|
|
||||||
BaseURL string `json:"base_url"`
|
|
||||||
UploadURL string `json:"upload_url"`
|
|
||||||
APIKey string `json:"api_key"`
|
|
||||||
Files drone.StringSlice `json:"files"`
|
|
||||||
Checksum drone.StringSlice `json:"checksum"`
|
|
||||||
Draft bool `json:"draft"`
|
|
||||||
FileExists string `json:"file_exists"`
|
|
||||||
}
|
|
103
utils.go
Normal file
103
utils.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/sha512"
|
||||||
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
|
"hash/crc32"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fileExistsValues = map[string]bool{
|
||||||
|
"overwrite": true,
|
||||||
|
"fail": true,
|
||||||
|
"skip": true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func execute(cmd *exec.Cmd) error {
|
||||||
|
fmt.Println("+", strings.Join(cmd.Args, " "))
|
||||||
|
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func checksum(r io.Reader, method string) (string, error) {
|
||||||
|
b, err := ioutil.ReadAll(r)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch method {
|
||||||
|
case "md5":
|
||||||
|
return fmt.Sprintf("%x", md5.Sum(b)), nil
|
||||||
|
case "sha1":
|
||||||
|
return fmt.Sprintf("%x", sha1.Sum(b)), nil
|
||||||
|
case "sha256":
|
||||||
|
return fmt.Sprintf("%x", sha256.Sum256(b)), nil
|
||||||
|
case "sha512":
|
||||||
|
return fmt.Sprintf("%x", sha512.Sum512(b)), nil
|
||||||
|
case "adler32":
|
||||||
|
return strconv.FormatUint(uint64(adler32.Checksum(b)), 10), nil
|
||||||
|
case "crc32":
|
||||||
|
return strconv.FormatUint(uint64(crc32.ChecksumIEEE(b)), 10), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Hashing method %s is not supported", method)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeChecksums(files, methods []string) ([]string, error) {
|
||||||
|
checksums := make(map[string][]string)
|
||||||
|
|
||||||
|
for _, method := range methods {
|
||||||
|
for _, file := range files {
|
||||||
|
handle, err := os.Open(file)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Failed to read %s artifact: %s", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hash, err := checksum(handle, method)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
checksums[method] = append(checksums[method], hash, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for method, results := range checksums {
|
||||||
|
filename := method + "sum.txt"
|
||||||
|
f, err := os.Create(filename)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(results); i += 2 {
|
||||||
|
hash := results[i]
|
||||||
|
file := results[i+1]
|
||||||
|
|
||||||
|
if _, err := f.WriteString(fmt.Sprintf("%s %s\n", hash, file)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
files = append(files, filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
return files, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user