mirror of
https://codeberg.org/woodpecker-plugins/go-plugin.git
synced 2024-09-08 03:38:54 +02:00
Initial implementation
This commit is contained in:
commit
60d32ee4ae
15
.woodpecker.yaml
Normal file
15
.woodpecker.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
variables:
|
||||||
|
- &golang 'golang:1.18'
|
||||||
|
|
||||||
|
pipeline:
|
||||||
|
- name: vendor
|
||||||
|
image: *golang
|
||||||
|
commands: go mod vendor
|
||||||
|
|
||||||
|
- name: lint
|
||||||
|
image: golangci/golangci-lint:v1.50-alpine
|
||||||
|
commands: golangci-lint run
|
||||||
|
|
||||||
|
- name: test
|
||||||
|
image: *golang
|
||||||
|
commands: go test --cover ./...
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2018 Drone.IO Inc.
|
||||||
|
Copyright 2020 Woodpecker-CI Team
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
71
README.md
Normal file
71
README.md
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Library for creating Woodpecker CI plugins
|
||||||
|
|
||||||
|
Provides basic structure and helpers to load Woodpecker CI environment variables while also
|
||||||
|
supporting reading Drone CI environment variables where available.
|
||||||
|
|
||||||
|
Adds logging support based on [zerolog](https://github.com/rs/zerolog) library and allows configurable
|
||||||
|
HTTP client library.
|
||||||
|
|
||||||
|
## Builtin settings
|
||||||
|
|
||||||
|
| Settings Name | Environment variable | Default | Description |
|
||||||
|
|---|---|----|---|
|
||||||
|
| `log_level` | - | `info` | Sets log level (`panic`, `fatal`, `error`, `warn`, `info`, `debug`, `trace`) |
|
||||||
|
| `skip_verify` | - | `false` | - | Skip verification of TLS certificate |
|
||||||
|
| | `SOCKS_PROXY` | *none* | SOCKS5 proxy to use for connections |
|
||||||
|
| | `SOCKS_PROXY_OFF` | *none* | Do not use SOCKS5 proxy |
|
||||||
|
|
||||||
|
## Creating plugin
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"codeberg.org/woodpecker-plugins/go-plugin"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Settings struct {
|
||||||
|
// TODO: Plugin settings
|
||||||
|
SampleFlag string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin struct {
|
||||||
|
*plugin.Plugin
|
||||||
|
Settings *Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Flags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
// TODO: Add flags
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "sample.flag",
|
||||||
|
Usage: "sample flag",
|
||||||
|
EnvVars: []string{"PLUGIN_SAMPLE_FLAG"},
|
||||||
|
Destination: &p.Settings.SampleFlag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Execute(ctx context.Context) error {
|
||||||
|
// TODO: Implement execution
|
||||||
|
log.Debug().Msg("executed")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p := &Plugin{
|
||||||
|
&Settings{}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Plugin = plugin.New(Options{
|
||||||
|
Name: "sample-plugin",
|
||||||
|
Description: "Sample plugin",
|
||||||
|
Flags: p.Flags(),
|
||||||
|
Execute: p.Execute,
|
||||||
|
})
|
||||||
|
|
||||||
|
p.Run()
|
||||||
|
}
|
||||||
|
```
|
186
commit.go
Normal file
186
commit.go
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Commit defines runtime metadata for a commit.
|
||||||
|
Commit struct {
|
||||||
|
Sha string `json:"sha,omitempty"`
|
||||||
|
Ref string `json:"ref,omitempty"`
|
||||||
|
Refspec string `json:"refspec,omitempty"`
|
||||||
|
PullRequest string `json:"pull_request,omitempty"`
|
||||||
|
SourceBranch string `json:"source_branch,omitempty"`
|
||||||
|
TargetBranch string `json:"target_branch,omitempty"`
|
||||||
|
Branch string `json:"branch,omitempty"`
|
||||||
|
Tag string `json:"tag,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Author Author `json:"author,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Author defines runtime metadata for a commit author.
|
||||||
|
Author struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
Avatar string `json:"avatar,omitempty"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func currFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.sha",
|
||||||
|
Usage: "commit SHA",
|
||||||
|
EnvVars: []string{"CI_COMMIT_SHA", "DRONE_COMMIT", "DRONE_COMMIT_SHA"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.ref",
|
||||||
|
Usage: "commit ref",
|
||||||
|
EnvVars: []string{"CI_COMMIT_REF", "DRONE_COMMIT_REF"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.refspec",
|
||||||
|
Usage: "commit refspec",
|
||||||
|
EnvVars: []string{"CI_COMMIT_REFSPEC"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.pull-request",
|
||||||
|
Usage: "commit pull request",
|
||||||
|
EnvVars: []string{"CI_COMMIT_PULL_REQUEST", "DRONE_PULL_REQUEST"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.source-branch",
|
||||||
|
Usage: "commit source branch",
|
||||||
|
EnvVars: []string{"CI_COMMIT_SOURCE_BRANCH", "DRONE_SOURCE_BRANCH"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.target-branch",
|
||||||
|
Usage: "commit target branch",
|
||||||
|
EnvVars: []string{"CI_COMMIT_TARGET_BRANCH", "DRONE_TARGET_BRANCH"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.branch",
|
||||||
|
Usage: "commit branch",
|
||||||
|
EnvVars: []string{"CI_COMMIT_BRANCH", "DRONE_BRANCH"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.tag",
|
||||||
|
Usage: "commit tag",
|
||||||
|
EnvVars: []string{"CI_COMMIT_TAG", "DRONE_TAG"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.message",
|
||||||
|
Usage: "commit message",
|
||||||
|
EnvVars: []string{"CI_COMMIT_MESSAGE", "DRONE_COMMIT_MESSAGE"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.author.name",
|
||||||
|
Usage: "commit author name",
|
||||||
|
EnvVars: []string{"CI_COMMIT_AUTHOR", "DRONE_COMMIT_AUTHOR", "DRONE_COMMIT_AUTHOR_NAME"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.author.email",
|
||||||
|
Usage: "commit author email",
|
||||||
|
EnvVars: []string{"CI_COMMIT_AUTHOR_EMAIL", "DRONE_COMMIT_AUTHOR_EMAIL"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "commit.author.avatar",
|
||||||
|
Usage: "commit author avatar",
|
||||||
|
EnvVars: []string{"CI_COMMIT_AUTHOR_AVATAR", "DRONE_COMMIT_AUTHOR_AVATAR"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func currFromContext(c *cli.Context) Commit {
|
||||||
|
return Commit{
|
||||||
|
Sha: c.String("commit.sha"),
|
||||||
|
Ref: c.String("commit.ref"),
|
||||||
|
Refspec: c.String("commit.refspec"),
|
||||||
|
PullRequest: c.String("commit.pull-request"),
|
||||||
|
SourceBranch: c.String("commit.source-branch"),
|
||||||
|
TargetBranch: c.String("commit.target-branch"),
|
||||||
|
Branch: c.String("commit.branch"),
|
||||||
|
Tag: c.String("commit.tag"),
|
||||||
|
Message: c.String("commit.message"),
|
||||||
|
Author: Author{
|
||||||
|
Name: c.String("commit.author.name"),
|
||||||
|
Email: c.String("commit.author.email"),
|
||||||
|
Avatar: c.String("commit.author.avatar"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prevFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.sha",
|
||||||
|
Usage: "previous commit SHA",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_SHA", "DRONE_COMMIT_BEFORE"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.ref",
|
||||||
|
Usage: "previous commit ref",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_REF"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.refspec",
|
||||||
|
Usage: "previous commit refspec",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_REFSPEC"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.branch",
|
||||||
|
Usage: "previous commit branch",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_BRANCH"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.message",
|
||||||
|
Usage: "previous commit message",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_MESSAGE"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.author.name",
|
||||||
|
Usage: "previous commit author name",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_AUTHOR"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.author.email",
|
||||||
|
Usage: "previous commit author email",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_AUTHOR_EMAIL"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "prev.commit.author.avatar",
|
||||||
|
Usage: "previous commit author avatar",
|
||||||
|
EnvVars: []string{"CI_PREV_COMMIT_AUTHOR_AVATAR"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prevFromContext(c *cli.Context) Commit {
|
||||||
|
return Commit{
|
||||||
|
Sha: c.String("prev.commit.sha"),
|
||||||
|
Ref: c.String("prev.commit.ref"),
|
||||||
|
Refspec: c.String("prev.commit.refspec"),
|
||||||
|
Branch: c.String("prev.commit.branch"),
|
||||||
|
Message: c.String("prev.commit.message"),
|
||||||
|
Author: Author{
|
||||||
|
Name: c.String("prev.commit.author.name"),
|
||||||
|
Email: c.String("prev.commit.author.email"),
|
||||||
|
Avatar: c.String("prev.commit.author.avatar"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
38
flags.go
Normal file
38
flags.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Flags has the cli.Flags for the Woodpecker plugin.
|
||||||
|
func Flags() []cli.Flag {
|
||||||
|
flags := make([]cli.Flag, 0, 30)
|
||||||
|
|
||||||
|
// Pipeline flags
|
||||||
|
flags = append(flags, repositoryFlags()...)
|
||||||
|
flags = append(flags, pipelineFlags()...)
|
||||||
|
flags = append(flags, currFlags()...)
|
||||||
|
flags = append(flags, prevFlags()...)
|
||||||
|
flags = append(flags, stepFlags()...)
|
||||||
|
flags = append(flags, systemFlags()...)
|
||||||
|
|
||||||
|
// Plugin flags
|
||||||
|
flags = append(flags, loggingFlags()...)
|
||||||
|
flags = append(flags, httpClientFlags()...)
|
||||||
|
|
||||||
|
return flags
|
||||||
|
}
|
23
go.mod
Normal file
23
go.mod
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
module codeberg.org/woodpecker-plugins/go-plugin
|
||||||
|
|
||||||
|
go 1.19
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/joho/godotenv v1.4.0
|
||||||
|
github.com/rs/zerolog v1.28.0
|
||||||
|
github.com/stretchr/testify v1.8.1
|
||||||
|
github.com/urfave/cli/v2 v2.23.7
|
||||||
|
golang.org/x/net v0.5.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
|
golang.org/x/sys v0.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
43
go.sum
Normal file
43
go.sum
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||||
|
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
|
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
||||||
|
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
|
||||||
|
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
|
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||||
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||||
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
102
http.go
Normal file
102
http.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func httpClientFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "transport.skip-verify",
|
||||||
|
Usage: "skip ssl verify",
|
||||||
|
EnvVars: []string{"PLUGIN_SKIP_VERIFY"},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "transport.socks-proxy",
|
||||||
|
Usage: "socks proxy address",
|
||||||
|
EnvVars: []string{"SOCKS_PROXY"},
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "transport.socks-proxy-off",
|
||||||
|
Usage: "socks proxy ignored",
|
||||||
|
EnvVars: []string{"SOCKS_PROXY_OFF"},
|
||||||
|
Hidden: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HTTPClientFromContext(ctx *cli.Context) *http.Client {
|
||||||
|
var (
|
||||||
|
skip = ctx.Bool("transport.skip-verify")
|
||||||
|
socks = ctx.String("transport.socks-proxy")
|
||||||
|
socksoff = ctx.Bool("transport.socks-proxy-off")
|
||||||
|
)
|
||||||
|
|
||||||
|
certs, err := x509.SystemCertPool()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("failed to find system CA certs")
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
RootCAs: certs,
|
||||||
|
InsecureSkipVerify: skip,
|
||||||
|
}
|
||||||
|
|
||||||
|
transport := &http.Transport{
|
||||||
|
TLSClientConfig: tlsConfig,
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
IdleConnTimeout: 90 * time.Second,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
DualStack: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(socks) != 0 && !socksoff {
|
||||||
|
proxyDialer, err := proxy.SOCKS5("tcp", socks, nil, dialer)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("failed to create socks proxy")
|
||||||
|
}
|
||||||
|
if contextDialer, ok := proxyDialer.(proxy.ContextDialer); ok {
|
||||||
|
transport.DialContext = contextDialer.DialContext
|
||||||
|
} else {
|
||||||
|
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
return proxyDialer.Dial(network, addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transport.DialContext = dialer.DialContext
|
||||||
|
}
|
||||||
|
|
||||||
|
return &http.Client{
|
||||||
|
Transport: transport,
|
||||||
|
}
|
||||||
|
}
|
47
logger.go
Normal file
47
logger.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loggingFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "log-level",
|
||||||
|
Usage: "log level",
|
||||||
|
EnvVars: []string{"PLUGIN_LOG_LEVEL"},
|
||||||
|
Value: "info",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupConsoleLogger sets up the console logger.
|
||||||
|
func SetupConsoleLogger(c *cli.Context) error {
|
||||||
|
level := c.String("log-level")
|
||||||
|
lvl, err := zerolog.ParseLevel(level)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Msgf("unknown logging level: %s", level)
|
||||||
|
}
|
||||||
|
zerolog.SetGlobalLevel(lvl)
|
||||||
|
if zerolog.GlobalLevel() <= zerolog.DebugLevel {
|
||||||
|
log.Logger = log.With().Caller().Logger()
|
||||||
|
log.Log().Msgf("LogLevel = %s", zerolog.GlobalLevel().String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
41
metadata.go
Normal file
41
metadata.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Metadata defines runtime metadata.
|
||||||
|
type Metadata struct {
|
||||||
|
Repository Repository `json:"repo,omitempty"`
|
||||||
|
Pipeline Pipeline `json:"curr,omitempty"`
|
||||||
|
Curr Commit `json:"commit,omitempty"`
|
||||||
|
Prev Commit `json:"prev,omitempty"`
|
||||||
|
Step Step `json:"step,omitempty"`
|
||||||
|
System System `json:"sys,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MetadataFromContext creates a Metadata from the cli.Context.
|
||||||
|
func MetadataFromContext(ctx *cli.Context) Metadata {
|
||||||
|
return Metadata{
|
||||||
|
Repository: repositoryFromContext(ctx),
|
||||||
|
Pipeline: pipelineFromContext(ctx),
|
||||||
|
Curr: currFromContext(ctx),
|
||||||
|
Prev: prevFromContext(ctx),
|
||||||
|
Step: stepFromContext(ctx),
|
||||||
|
System: systemFromContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
117
metadata_test.go
Normal file
117
metadata_test.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testMetadata() map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"CI": "woodpecker",
|
||||||
|
// Repository
|
||||||
|
"CI_REPO": "woodpecker-ci/woodpecker",
|
||||||
|
"CI_REPO_NAME": "woodpecker",
|
||||||
|
"CI_REPO_OWNER": "woodpecker-ci",
|
||||||
|
"CI_REPO_SCM": "git",
|
||||||
|
"CI_REPO_LINK": "https://github.com/woodpecker-ci/woodpecker",
|
||||||
|
"CI_REPO_CLONE_URL": "https://github.com/woodpecker-ci/woodpecker.git",
|
||||||
|
"CI_REPO_DEFAULT_BRANCH": "main",
|
||||||
|
"CI_REPO_PRIVATE": "false",
|
||||||
|
// Commit
|
||||||
|
"CI_COMMIT_SHA": "a1b2c3d4",
|
||||||
|
"CI_COMMIT_REF": "refs/heads/main",
|
||||||
|
"CI_COMMIT_REFSPEC": "refs/heads/main",
|
||||||
|
"CI_COMMIT_BRANCH": "main",
|
||||||
|
"CI_COMMIT_MESSAGE": "test commit",
|
||||||
|
"CI_COMMIT_AUTHOR": "John Doe",
|
||||||
|
"CI_COMMIT_AUTHOR_EMAIL": "john@example.com",
|
||||||
|
"CI_COMMIT_AUTHOR_AVATAR": "https://avatars.githubusercontent.com/u/1234567?v=4",
|
||||||
|
"CI_COMMIT_LINK": "https://github.com/woodpecker-ci/woodpecker/commit/a1b2c3d4",
|
||||||
|
// Build
|
||||||
|
"CI_PIPELINE_NUMBER": "1",
|
||||||
|
"CI_PIPELINE_EVENT": "push",
|
||||||
|
"CI_PIPELINE_LINK": "https://ci.woodpecker-ci.org/woodpecker-ci/woodpecker/1",
|
||||||
|
"CI_PIPELINE_STATUS": "running",
|
||||||
|
"CI_PIPELINE_CREATED": "1611234567",
|
||||||
|
"CI_PIPELINE_STARTED": "1611234567",
|
||||||
|
// Step
|
||||||
|
"CI_STEP_NUMBER": "1",
|
||||||
|
"CI_STEP_NAME": "test",
|
||||||
|
"CI_STEP_STATUS": "running",
|
||||||
|
"CI_STEP_STARTED": "1611234567",
|
||||||
|
// System
|
||||||
|
"CI_SYSTEM_NAME": "woodpecker",
|
||||||
|
"CI_SYSTEM_LINK": "https://ci.woodpecker-ci.org",
|
||||||
|
"CI_SYSTEM_VERSION": "1.0.0",
|
||||||
|
"CI_SYSTEM_HOST": "woodpecker-ci.org",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMetadata(t *testing.T) {
|
||||||
|
for k, v := range testMetadata() {
|
||||||
|
os.Setenv(k, v)
|
||||||
|
defer os.Unsetenv(k)
|
||||||
|
}
|
||||||
|
plugin := New(Options{
|
||||||
|
Execute: func(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
err := plugin.app.Run([]string{"test"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Repository
|
||||||
|
assert.Equal(t, "woodpecker", plugin.Metadata.Repository.Name)
|
||||||
|
assert.Equal(t, "woodpecker-ci", plugin.Metadata.Repository.Owner)
|
||||||
|
assert.Equal(t, "https://github.com/woodpecker-ci/woodpecker", plugin.Metadata.Repository.Link)
|
||||||
|
assert.Equal(t, "https://github.com/woodpecker-ci/woodpecker.git", plugin.Metadata.Repository.CloneURL)
|
||||||
|
assert.Equal(t, "main", plugin.Metadata.Repository.Branch)
|
||||||
|
assert.False(t, plugin.Metadata.Repository.Private)
|
||||||
|
|
||||||
|
// Commit
|
||||||
|
assert.Equal(t, "a1b2c3d4", plugin.Metadata.Curr.Sha)
|
||||||
|
assert.Equal(t, "refs/heads/main", plugin.Metadata.Curr.Ref)
|
||||||
|
assert.Equal(t, "refs/heads/main", plugin.Metadata.Curr.Refspec)
|
||||||
|
assert.Equal(t, "main", plugin.Metadata.Curr.Branch)
|
||||||
|
assert.Equal(t, "test commit", plugin.Metadata.Curr.Message)
|
||||||
|
assert.Equal(t, "John Doe", plugin.Metadata.Curr.Author.Name)
|
||||||
|
assert.Equal(t, "john@example.com", plugin.Metadata.Curr.Author.Email)
|
||||||
|
assert.Equal(t, "https://avatars.githubusercontent.com/u/1234567?v=4", plugin.Metadata.Curr.Author.Avatar)
|
||||||
|
|
||||||
|
// Pipeline
|
||||||
|
assert.Equal(t, int64(1), plugin.Metadata.Pipeline.Number)
|
||||||
|
assert.Equal(t, "push", plugin.Metadata.Pipeline.Event)
|
||||||
|
assert.Equal(t, "https://ci.woodpecker-ci.org/woodpecker-ci/woodpecker/1", plugin.Metadata.Pipeline.Link)
|
||||||
|
assert.Equal(t, "running", plugin.Metadata.Pipeline.Status)
|
||||||
|
assert.Equal(t, time.Unix(1611234567, 0), plugin.Metadata.Pipeline.Created)
|
||||||
|
assert.Equal(t, time.Unix(1611234567, 0), plugin.Metadata.Pipeline.Started)
|
||||||
|
|
||||||
|
// Step
|
||||||
|
assert.Equal(t, 1, plugin.Metadata.Step.Number)
|
||||||
|
assert.Equal(t, time.Unix(1611234567, 0), plugin.Metadata.Step.Started)
|
||||||
|
|
||||||
|
// System
|
||||||
|
assert.Equal(t, "woodpecker", plugin.Metadata.System.Name)
|
||||||
|
assert.Equal(t, "https://ci.woodpecker-ci.org", plugin.Metadata.System.Link)
|
||||||
|
assert.Equal(t, "1.0.0", plugin.Metadata.System.Version)
|
||||||
|
assert.Equal(t, "woodpecker-ci.org", plugin.Metadata.System.Host)
|
||||||
|
}
|
125
pipeline.go
Normal file
125
pipeline.go
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pipeline defines runtime metadata for a pipeline.
|
||||||
|
type Pipeline struct {
|
||||||
|
Number int64 `json:"number,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
Event string `json:"event,omitempty"`
|
||||||
|
Link string `json:"link,omitempty"`
|
||||||
|
DeployTarget string `json:"target,omitempty"`
|
||||||
|
Created time.Time `json:"created,omitempty"`
|
||||||
|
Started time.Time `json:"started,omitempty"`
|
||||||
|
Finished time.Time `json:"finished,omitempty"`
|
||||||
|
Parent int64 `json:"parent,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func pipelineFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "pipeline.number",
|
||||||
|
Usage: "pipeline number",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_NUMBER",
|
||||||
|
"DRONE_BUILD_NUMBER",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "pipeline.status",
|
||||||
|
Usage: "pipeline status",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_STATUS",
|
||||||
|
"DRONE_BUILD_STATUS",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "pipeline.event",
|
||||||
|
Usage: "pipeline event",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_EVENT",
|
||||||
|
"DRONE_BUILD_EVENT",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "pipeline.link",
|
||||||
|
Usage: "pipeline link",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_LINK",
|
||||||
|
"DRONE_BUILD_LINK",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "pipeline.deploy-target",
|
||||||
|
Usage: "pipeline deployment target",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_DEPLOY_TARGET",
|
||||||
|
"DRONE_DEPLOY_TO",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "pipeline.created",
|
||||||
|
Usage: "pipeline creation time",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_CREATED",
|
||||||
|
"DRONE_BUILD_CREATED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "pipeline.started",
|
||||||
|
Usage: "pipeline start time",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_STARTED",
|
||||||
|
"DRONE_BUILD_STARTED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "pipeline.finished",
|
||||||
|
Usage: "pipeline finish time",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_FINISHED",
|
||||||
|
"DRONE_BUILD_FINISHED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "pipeline.parent",
|
||||||
|
Usage: "pipeline parent",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_PIPELINE_PARENT",
|
||||||
|
"DRONE_BUILD_PARENT",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pipelineFromContext(c *cli.Context) Pipeline {
|
||||||
|
return Pipeline{
|
||||||
|
Number: c.Int64("pipeline.number"),
|
||||||
|
Status: c.String("pipeline.status"),
|
||||||
|
Event: c.String("pipeline.event"),
|
||||||
|
Link: c.String("pipeline.link"),
|
||||||
|
DeployTarget: c.String("pipeline.deploy-target"),
|
||||||
|
Created: time.Unix(c.Int64("pipeline.created"), 0),
|
||||||
|
Started: time.Unix(c.Int64("pipeline.started"), 0),
|
||||||
|
Finished: time.Unix(c.Int64("pipeline.finished"), 0),
|
||||||
|
Parent: c.Int64("pipeline.parent"),
|
||||||
|
}
|
||||||
|
}
|
101
plugin.go
Normal file
101
plugin.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options defines the options for the plugin.
|
||||||
|
type Options struct {
|
||||||
|
// Name of the plugin.
|
||||||
|
Name string
|
||||||
|
// Description of the plugin.
|
||||||
|
Description string
|
||||||
|
// Version of the plugin.
|
||||||
|
Version string
|
||||||
|
// Flags of the plugin.
|
||||||
|
Flags []cli.Flag
|
||||||
|
// Execute function of the plugin.
|
||||||
|
Execute ExecuteFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin defines the plugin instance.
|
||||||
|
type Plugin struct {
|
||||||
|
app *cli.App
|
||||||
|
execute ExecuteFunc
|
||||||
|
client *http.Client
|
||||||
|
// Metadata of the current pipeline.
|
||||||
|
Metadata Metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExecuteFunc defines the function that is executed by the plugin.
|
||||||
|
type ExecuteFunc func(ctx context.Context) error
|
||||||
|
|
||||||
|
// New plugin instance.
|
||||||
|
func New(opt Options) *Plugin {
|
||||||
|
if _, err := os.Stat("/run/woodpecker/env"); err == nil {
|
||||||
|
_ = godotenv.Overload("/run/woodpecker/env")
|
||||||
|
}
|
||||||
|
|
||||||
|
app := &cli.App{
|
||||||
|
Name: opt.Name,
|
||||||
|
Description: opt.Description,
|
||||||
|
Version: opt.Version,
|
||||||
|
Flags: append(opt.Flags, Flags()...),
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin := &Plugin{
|
||||||
|
app: app,
|
||||||
|
execute: opt.Execute,
|
||||||
|
}
|
||||||
|
plugin.app.Action = plugin.action
|
||||||
|
|
||||||
|
return plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) action(ctx *cli.Context) error {
|
||||||
|
if err := SetupConsoleLogger(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Metadata = MetadataFromContext(ctx)
|
||||||
|
p.client = HTTPClientFromContext(ctx)
|
||||||
|
|
||||||
|
if p.execute == nil {
|
||||||
|
panic("plugin execute function is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.execute(ctx.Context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPClient returns the http.Client instance.
|
||||||
|
func (p *Plugin) HTTPClient() *http.Client {
|
||||||
|
return p.client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the plugin.
|
||||||
|
func (p *Plugin) Run() {
|
||||||
|
if err := p.app.Run(os.Args); err != nil {
|
||||||
|
log.Error().Err(err).Msg("execution failed")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
36
plugin_test.go
Normal file
36
plugin_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPlugin(t *testing.T) {
|
||||||
|
var executed bool
|
||||||
|
p := New(Options{
|
||||||
|
Name: "test",
|
||||||
|
Execute: func(ctx context.Context) error {
|
||||||
|
executed = true
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
err := p.app.Run([]string{"test"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, executed)
|
||||||
|
}
|
93
repo.go
Normal file
93
repo.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Repository defines runtime metadata for a repository.
|
||||||
|
type Repository struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Owner string `json:"owner,omitempty"`
|
||||||
|
Link string `json:"link,omitempty"`
|
||||||
|
CloneURL string `json:"clone_url,omitempty"`
|
||||||
|
Private bool `json:"private,omitempty"`
|
||||||
|
Branch string `json:"default_branch,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func repositoryFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo.name",
|
||||||
|
Usage: "repo name",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_REPO_NAME",
|
||||||
|
"DRONE_REPO_NAME",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo.owner",
|
||||||
|
Usage: "repo owner",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_REPO_OWNER",
|
||||||
|
"DRONE_REPO_OWNER",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo.link",
|
||||||
|
Usage: "repo link",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_REPO_LINK",
|
||||||
|
"DRONE_REPO_LINK",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo.clone-url",
|
||||||
|
Usage: "repo clone url",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_REPO_CLONE_URL",
|
||||||
|
"DRONE_GIT_HTTP_URL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "repo.private",
|
||||||
|
Usage: "repo private",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_REPO_PRIVATE",
|
||||||
|
"DRONE_REPO_PRIVATE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo.default-branch",
|
||||||
|
Usage: "repo default branch",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_REPO_DEFAULT_BRANCH",
|
||||||
|
"DRONE_REPO_BRANCH",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func repositoryFromContext(c *cli.Context) Repository {
|
||||||
|
return Repository{
|
||||||
|
Name: c.String("repo.name"),
|
||||||
|
Owner: c.String("repo.owner"),
|
||||||
|
Link: c.String("repo.link"),
|
||||||
|
CloneURL: c.String("repo.clone-url"),
|
||||||
|
Private: c.Bool("repo.private"),
|
||||||
|
Branch: c.String("repo.default-branch"),
|
||||||
|
}
|
||||||
|
}
|
63
step.go
Normal file
63
step.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Step defines runtime metadata for a step.
|
||||||
|
type Step struct {
|
||||||
|
Number int `json:"number,omitempty"`
|
||||||
|
Started time.Time `json:"started,omitempty"`
|
||||||
|
Finished time.Time `json:"finished,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func stepFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "step.number",
|
||||||
|
Usage: "step number",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_STEP_NUMBER",
|
||||||
|
"DRONE_STEP_NUMBER",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "step.started",
|
||||||
|
Usage: "step start time",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_STEP_STARTED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "step.finished",
|
||||||
|
Usage: "step finish time",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_STEP_FINISHED",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stepFromContext(c *cli.Context) Step {
|
||||||
|
return Step{
|
||||||
|
Number: c.Int("step.number"),
|
||||||
|
Started: time.Unix(c.Int64("step.started"), 0),
|
||||||
|
Finished: time.Unix(c.Int64("step.finished"), 0),
|
||||||
|
}
|
||||||
|
}
|
93
system.go
Normal file
93
system.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2023 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// System defines runtime metadata for a ci/cd system.
|
||||||
|
type System struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Host string `json:"host,omitempty"`
|
||||||
|
Link string `json:"link,omitempty"`
|
||||||
|
Platform string `json:"arch,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func systemFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "system.name",
|
||||||
|
Usage: "system name",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_SYSTEM_NAME",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "system.host",
|
||||||
|
Usage: "system host",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_SYSTEM_HOST",
|
||||||
|
"DRONE_SYSTEM_HOST",
|
||||||
|
"DRONE_SYSTEM_HOSTNAME",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "system.link",
|
||||||
|
Usage: "system link",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_SYSTEM_LINK",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "system.arch",
|
||||||
|
Usage: "system arch",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_SYSTEM_PLATFORM",
|
||||||
|
"DRONE_STAGE_ARCH",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "system.version",
|
||||||
|
Usage: "system version",
|
||||||
|
EnvVars: []string{
|
||||||
|
"CI_SYSTEM_VERSION",
|
||||||
|
"DRONE_SYSTEM_VERSION",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func systemFromContext(ctx *cli.Context) System {
|
||||||
|
link := ctx.String("system.link")
|
||||||
|
host := ctx.String("system.host")
|
||||||
|
if link == "" && host != "" {
|
||||||
|
// Alternative link format used by Drone.
|
||||||
|
proto := os.Getenv("DRONE_SYSTEM_PROTO")
|
||||||
|
if proto != "" {
|
||||||
|
link = proto + "://" + host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return System{
|
||||||
|
Name: ctx.String("system.name"),
|
||||||
|
Host: host,
|
||||||
|
Link: link,
|
||||||
|
Platform: ctx.String("system.arch"),
|
||||||
|
Version: ctx.String("system.version"),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user