Skip to content

Commit

Permalink
Merge pull request #136 from evanchaoli/get_latest
Browse files Browse the repository at this point in the history
Add get_latest param.
  • Loading branch information
Rui Yang committed Jan 6, 2023
2 parents d498338 + f596b78 commit 56bef22
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 30 deletions.
85 changes: 80 additions & 5 deletions README.md
Expand Up @@ -154,7 +154,9 @@ plan:

### `check`: Report the current version number.

Detects new versions by reading the file from the specified source. If the file is empty, it returns the `initial_version`. If the file is not empty, it returns the version specified in the file.
Detects new versions by reading the file from the specified source. If the
file is empty, it returns the `initial_version`. If the file is not empty, it
returns the version specified in the file.

### `in`: Provide the version as a file, optionally bumping it.

Expand Down Expand Up @@ -205,6 +207,7 @@ because there's some new version `M`, the driver will re-apply the bump to get
* `pre_without_version`: *Optional.* By default `false`, once it's set to `true`
then PreRelease will be bumped without a version number.

* `get_latest`: *Optional.* See [Check-less Usage](#check-less-usage).

## Version Bumping Semantics

Expand All @@ -229,7 +232,10 @@ be one of:
version is reset to `1`. If the version is *not* already a pre-release, then
`pre` is added, starting at `1`.

The value of `pre` can be anything you like; the value will be `pre`-pended (_hah_) to a numeric value. For example, `pre: foo` will result in a semver of `x.y.z-foo.<number>`, `pre: alpha` becomes `x.y.z-alpha.<number>`, and `pre: my-preferred-naming-convention` becomes `x.y.z-my-preferred-naming-convention.<number>`
The value of `pre` can be anything you like; the value will be `pre`-pended (_hah_)
to a numeric value. For example, `pre: foo` will result in a semver of
`x.y.z-foo.<number>`, `pre: alpha` becomes `x.y.z-alpha.<number>`, and
`pre: my-preferred-naming-convention` becomes `x.y.z-my-preferred-naming-convention.<number>`

* `build`: *Optional.* Same as `pre` but for build labels (e.g. `build: foo`
will result in a semver of `x.y.z+foo.<number>`, `build: alpha` becomes
Expand All @@ -246,7 +252,76 @@ be one of:
* `build_without_version`: *Optional.* Same as `pre_without_version` but for
build labels.

### Running the tests
## Check-less Usage

A classic usage of semver resource is like:

```yaml
resources:
- name: version
type: semver
source:
driver: git
uri: git@github.com:concourse/concourse.git
branch: version
file: version
private_key: {{concourse-repo-private-key}}

jobs:
- name: some-job
plan:
- get: trigger-resource
trigger: true
- get: version
param: {bump: major}
- task: a-thing-that-needs-a-version
- put: version
params: {file: version/version}
```

In above classic mode, Concourse will run periodic checks against the `semver`
resource `version`. Each check will do a `git clone` as the driver is `git`.
When there are a lot of `semver` resources, checks on `semver` resources may
also bring burden to the git system as each check will invoke a `git clone`.

Given each `semver` resource requires a parameter `file` in `source`, `semver`
resources are hard to enjoy [benefits of global resources](https://concourse-ci.org/global-resources.html#benefits-of-global-resources).

To mitigate the burden of checks, if a `semver` resource is not a job trigger,
check-less mode can be used. The above sample then can be rewritten as:

```yaml
jobs:
- name: some-job
plan:
- get: trigger-resource
trigger: true
- put: version # change `get` to `put`
param:
get_latest: true # and set `get_latest: true`
get_params:
bump: major
- task: a-thing-that-needs-a-version
- put: version
params: {file: version/version}
```

You may have noticed that, original `get: version` is changed to `put: version`.
Now resource `version` is put-only, then Concourse will no longer run check on
it. Param `get_latest: true` tells the `put` step to only fetch the latest version
without bumping anything. Then the implied `get` will fetch a version as a typical
`get` step.

If your Concourse or Git (e.g. Gitlab) systems are exhausted by `semver` resources'
checks, you may consider reforming pipelines to use this check-less usage.

The cons of check-less usage are:

* you cannot use `put` step as a job trigger.
* `put` step with `get_latest: true` will always fetch the latest version, thus
you are not able to pin an old version.

## Running the tests

The tests have been embedded with the `Dockerfile`; ensuring that the testing
environment is consistent across any `docker` enabled platform. When the docker
Expand All @@ -260,7 +335,7 @@ docker build -t semver-resource --target tests -f dockerfiles/alpine/Dockerfile
docker build -t semver-resource --target tests -f dockerfiles/ubuntu/Dockerfile .
```

#### Integration tests
### Integration tests

The integration requires two AWS S3 buckets, one without versioning and another
with. The `docker build` step requires setting `--build-args` so the
Expand All @@ -287,7 +362,7 @@ docker build . -t semver-resource --target tests -f dockerfiles/ubuntu/Dockerfil
--build-arg SEMVER_TESTING_REGION="some-region"
```

### Contributing
## Contributing

Please make all pull requests to the `master` branch and ensure tests pass
locally.
4 changes: 4 additions & 0 deletions dockerfiles/alpine/Dockerfile
Expand Up @@ -5,6 +5,10 @@ FROM ${builder_image} as builder
COPY . /src
WORKDIR /src
ENV CGO_ENABLED 0

ARG goproxy
ENV GOPROXY=$goproxy

RUN go get -d ./...
RUN go build -o /assets/in ./in
RUN go build -o /assets/out ./out
Expand Down
4 changes: 4 additions & 0 deletions dockerfiles/ubuntu/Dockerfile
Expand Up @@ -5,6 +5,10 @@ FROM ${builder_image} as builder
COPY . /src
WORKDIR /src
ENV CGO_ENABLED 0

ARG goproxy
ENV GOPROXY=$goproxy

RUN go get -d ./...
RUN go build -o /assets/in ./in
RUN go build -o /assets/out ./out
Expand Down
44 changes: 20 additions & 24 deletions driver/git.go
Expand Up @@ -3,7 +3,6 @@ package driver
import (
"errors"
"fmt"
"io/ioutil"
"net/mail"
"os"
"os/exec"
Expand Down Expand Up @@ -72,10 +71,11 @@ func (driver *GitDriver) Bump(bump version.Bump) (semver.Version, error) {

newVersion = bump.Apply(currentVersion)

wrote, err := driver.writeVersion(newVersion)
var wrote bool
wrote, err = driver.writeVersion(newVersion)
if wrote {
break
}
}
}
if err != nil {
return semver.Version{}, err
Expand All @@ -101,15 +101,15 @@ func (driver *GitDriver) Set(newVersion semver.Version) error {
return err
}

wrote, err := driver.writeVersion(newVersion)
if err != nil {
return err
}

var wrote bool
wrote, err = driver.writeVersion(newVersion)
if wrote {
break
}
}
if err != nil {
return err
}

return nil
}
Expand Down Expand Up @@ -224,7 +224,7 @@ func (driver *GitDriver) setUpKey() error {
if err != nil {
if os.IsNotExist(err) {
privateKey := strings.TrimSuffix(driver.PrivateKey, "\n")
err := ioutil.WriteFile(privateKeyPath, []byte(privateKey+"\n"), 0600)
err := os.WriteFile(privateKeyPath, []byte(privateKey+"\n"), 0600)
if err != nil {
return err
}
Expand Down Expand Up @@ -253,7 +253,7 @@ func (driver *GitDriver) setUpUsernamePassword() error {
if err != nil {
if os.IsNotExist(err) {
content := fmt.Sprintf("default login %s password %s", driver.Username, driver.Password)
err := ioutil.WriteFile(netRcPath, []byte(content), 0600)
err := os.WriteFile(netRcPath, []byte(content), 0600)
if err != nil {
return err
}
Expand Down Expand Up @@ -321,20 +321,18 @@ func (driver *GitDriver) readVersion() (semver.Version, bool, error) {

const nothingToCommitString = "nothing to commit"
const falsePushString = "Everything up-to-date"
const pushRejectedString = "[rejected]"
const pushRemoteRejectedString = "[remote rejected]"

func (driver *GitDriver) writeVersion(newVersion semver.Version) (bool, error) {

path := filepath.Dir(driver.File)
if path != "/" && path != "." {
err := os.MkdirAll(filepath.Join(gitRepoDir, path), 0755)
if err != nil {
return false, err
}
}
path := filepath.Dir(driver.File)
if path != "/" && path != "." {
err := os.MkdirAll(filepath.Join(gitRepoDir, path), 0755)
if err != nil {
return false, err
}
}

err := ioutil.WriteFile(filepath.Join(gitRepoDir, driver.File), []byte(newVersion.String()+"\n"), 0644)
err := os.WriteFile(filepath.Join(gitRepoDir, driver.File), []byte(newVersion.String()+"\n"), 0644)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -374,11 +372,9 @@ func (driver *GitDriver) writeVersion(newVersion semver.Version) (bool, error) {

pushOutput, err := gitPush.CombinedOutput()

if strings.Contains(string(pushOutput), falsePushString) ||
strings.Contains(string(pushOutput), pushRejectedString) ||
strings.Contains(string(pushOutput), pushRemoteRejectedString) {
if strings.Contains(string(pushOutput), falsePushString) {
os.Stderr.Write(pushOutput)
return false, nil
return true, nil
}

if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions models/models.go
Expand Up @@ -42,6 +42,8 @@ type OutParams struct {
Build string `json:"build"`
PreWithoutVersion bool `json:"pre_without_version"`
BuildWithoutVersion bool `json:"build_without_version"`

GetLatest bool `json:"get_latest,omitempty"`
}

type CheckRequest struct {
Expand Down
8 changes: 7 additions & 1 deletion out/main.go
Expand Up @@ -33,7 +33,13 @@ func main() {
}

var newVersion semver.Version
if request.Params.File != "" {
if request.Params.GetLatest {
versions, err := driver.Check(nil)
if err != nil {
fatal("checking latest version", err)
}
newVersion = versions[0]
} else if request.Params.File != "" {
versionFile, err := os.Open(filepath.Join(sources, request.Params.File))
if err != nil {
fatal("opening version file", err)
Expand Down

0 comments on commit 56bef22

Please sign in to comment.