Skip to content

Commit

Permalink
Merge pull request #1 from codfish/outputs
Browse files Browse the repository at this point in the history
feat: add new output variables
  • Loading branch information
codfish authored Aug 29, 2019
2 parents af4cb2d + a9dfada commit 1b6c3dc
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 79 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ jobs:

- name: semantic-release
if: github.ref == 'refs/heads/master'
id: semantic
uses: ./
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: test output
run: |
echo "$OUTPUTS"
echo new release? $NEW_RELEASE_PUBLISHED
env:
NEW_RELEASE_PUBLISHED: ${{ steps.semantic.outputs.new-release-published }}
OUTPUTS: ${{ toJson(steps.semantic.outputs) }}
197 changes: 153 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,118 @@
> your repo. Exports [environment variables](#outputs) for you to use in subsequent actions
> containing version numbers.
## Why
## Usage

It would have been fairly easy to run this as a "host action," aka something that simply runs
directly on the VM.
See [action.yml](action.yml)

- Use major version
([recommended by GitHub](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)):
`uses: codfish/semantic-release-action@v1`
- Use latest version: `uses: codfish/semantic-release-action@master`
- Use specific version: `uses: codfish/[email protected]`

Basic Usage:

```yml
steps:
- name: Semantic Release
run: npx semantic-release
- uses: actions/checkout@master

- uses: codfish/semantic-release-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```
If you're just publishing an node package, then this could still work well for you. The problem I
found with this is when I was in projects where I had subsequent steps/actions in which I wanted to
know whether a new version was cut.
Using output variables set by `semantic-release-action`:

> **Use Case:** For instance, in an application where I'm using `semantic-release` to manage GitHub
> releases, but also building and pushing docker images. Dockerhub has a
> [nice GitHub integration](https://docs.docker.com/docker-hub/builds/) to handle this for us, but
> some other registries do not. If I need to cut a new release, then update a docker registry by
> adding a new tagged build, I'll want to run `semantic-release` and then build a docker image, tag
> it with a version and push it up. In my case I like to push up tags for `latest`, the semver (i.e.
> `1.8.3`), and just the major the version (i.e. `1`).
```yml
steps:
- uses: actions/checkout@master
I want to know 1) if semantic-release cut a new version and 2) what the version is.
# you'll need to add an `id` in order to access output variables
- uses: codfish/semantic-release-action@master
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

There's a number of ways to handle this, but the most elegant way I found to do it was to abstract
it into it's own custom action. It abstracts away whatever logic you need to figure out what that
new release number is.
- run: echo ${{ steps.semantic.outputs.release-version }}

This also scales well, just in case I want to add some flexibility and functionality to this action,
I can easily leverage it across any project.
- run: echo "$OUTPUTS"
env:
OUTPUTS: ${{ toJson(steps.semantic.outputs) }}

## Usage
- uses: codfish/some-other-action@master
with:
release-version: ${{ steps.semantic.outputs.release-version }}
```
Only run an action if a new version was created:
```yml
steps:
- uses: actions/checkout@master

# you'll need to add an `id` in order to access output variables
- uses: codfish/semantic-release-action@master
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

# exit gracefully if no version was published
- name: docker push version
run: |
if [ "$NEW_RELEASE_PUBLISHED" == "false" ]; then exit 0; fi;
docker tag $DOCKER_REGISTRY/your-image $DOCKER_REGISTRY/your-image:$TAG
docker push $DOCKER_REGISTRY/your-image:$TAG
env:
DOCKER_REGISTRY: ${{ secrets.DOCKER_REGISTRY }}
TAG: v$RELEASE_VERSION
```
**NOTE**: In theory we'll be able to handle this more gracefully in the future.
[We're not able to access the `steps` context within an `if` expression yet](https://github.com/actions/toolkit/issues/96).

**DOES NOT WORK YET:**

```yml
steps:
- uses: actions/checkout@master
- uses: codfish/semantic-release-action@master
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- if: steps.semantic.outputs.new-release-published == 'true'
run: echo "A new release was published!!"
```

Using environment variables set by `semantic-release-action`:

```yml
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
steps:
- uses: actions/checkout@master
- uses: codfish/semantic-release-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: codfish/actions/semantic-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: |
echo $RELEASE_VERSION
echo $RELEASE_MAJOR
echo $RELEASE_MINOR
echo $RELEASE_PATCH
```

If you're not publishing to npm and only want to use this action for GitHub releases, you'd only
need to provide a `GITHUB_TOKEN` env var. You'll also need to include a `.releaserc.js` file in your
repo, instructing `semantic-release` to not look to publish to `npm`.
If you're _not_ publishing to npm and only want to use this action for GitHub releases, you need to
include a `.releaserc.js` file in your repo, instructing `semantic-release` to not publish to the
`npm` registry.

**Example:**
Example `.releaserc.js` if you're not publishing to npm:

```js
module.exports = {
Expand All @@ -73,18 +129,71 @@ module.exports = {
};
```

### Inputs
## Why

None. Might be a good idea to accept optional configuration values via inputs that would merge, yet
override any `.releaserc.js` config file values.
It's fairly easy to run `semantic-release` as a "host action," aka something that simply runs
directly on the VM.

```yml
steps:
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
```

If you're just publishing a node package, then this could still work well for you. The problem I
found with this is when I was in projects where I had subsequent steps/actions in which I wanted to
know whether a new version was cut.

> **Use Case:** For instance, in an application where I'm using `semantic-release` to manage GitHub
> releases, but also building and pushing docker images. Dockerhub has a
> [nice GitHub integration](https://docs.docker.com/docker-hub/builds/) to handle this for us, but
> some other registries do not. If I need to cut a new release, then update a docker registry by
> adding a new tagged build, I'll want to run `semantic-release` and then build a docker image, tag
> it with a version and push it up. In my case I like to push up tags for `latest`, the semver (i.e.
> `v1.8.3`), and just the major the version (i.e. `v1`).

I want to know 1) if semantic-release cut a new version and 2) what the version is.

There's a number of ways to handle this, but the most elegant way I found to do it was to abstract
it into it's own custom action. It abstracts away whatever logic you need to figure out what that
new release number is.

This also scales well, just in case I want to add some flexibility and functionality to this action,
I can easily leverage it across any project.

## Inputs

**Docs:** https://help.github.com/en/articles/metadata-syntax-for-github-actions#inputs

None yet. Might be a good idea to accept optional configuration values via inputs that would merge,
yet override any `.releaserc.js` config file values. i.e. `branch`, etc.

### Outputs

`semantic-release-action` sets both output variables and environment variables because why not?
Allows users the ability to use whichever they want. I don't know or understand every use case there
might be so this is a way to cover more cases.

**Docs:** https://help.github.com/en/articles/metadata-syntax-for-github-actions#outputs

**Output Variables**:

| Output Variable | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| new-release-published | Either `'true'` when a new release was published or `'false'` when no release was published. Allows other actions to run or not-run based on this |
| release-version | The new releases' semantic version, i.e. `1.8.3` |
| release-major | The new releases' major version number, i.e. `1` |
| release-minor | The new releases' minor version number, i.e. `8` |
| release-patch | The new releases' patch version number, i.e. `3` |

**Environment Variables**:

- `SEMANTIC_RELEASE`: Either `'true'` or `'false'`. This allows other actions to run or not-run
based on this.
- `SEMANTIC_RELEASE_VERSION`: The new release's semantic version, i.e. `1.8.3`.
- `SEMANTIC_RELEASE_MAJOR`: The new release's major version number, i.e. `1`.
- `SEMANTIC_RELEASE_MINOR`: The new release's minor version number, i.e. `8`.
- `SEMANTIC_RELEASE_PATCH`: The new release's patch version number, i.e. `3`.
| Environment Variable | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| NEW_RELEASE_PUBLISHED | Either `'true'` when a new release was published or `'false'` when no release was published. Allows other actions to run or not-run based on this |
| RELEASE_VERSION | The new releases' semantic version, i.e. `1.8.3` |
| RELEASE_MAJOR | The new releases' major version number, i.e. `1` |
| RELEASE_MINOR | The new releases' minor version number, i.e. `8` |
| RELEASE_PATCH | The new releases' patch version number, i.e. `3` |
11 changes: 11 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ author: 'codfish'
branding:
icon: 'arrow-up-right'
color: 'orange'
outputs:
new-release-published:
description: "Either `'true'` when a new release was published or `'false'` when no release was published"
release-version:
description: "The new releases' semantic version, i.e. `1.8.3`"
release-major:
description: "The new releases' major version number, i.e. `1`"
release-minor:
description: "The new releases' minor version number, i.e. `8`"
release-patch:
description: "The new releases' patch version number, i.e. `3`"
runs:
using: 'docker'
image: 'Dockerfile'
74 changes: 39 additions & 35 deletions entrypoint.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,45 @@
const core = require('@actions/core');
const semanticRelease = require('semantic-release');

async function main() {
try {
const result = await semanticRelease();

if (result) {
const { lastRelease, nextRelease, commits } = result;

core.debug(
`Published ${nextRelease.type} release version ${nextRelease.version} containing ${commits.length} commits.`,
);

if (lastRelease.version) {
core.debug(`The last release was "${lastRelease.version}".`);
}

// outputs
const { version } = nextRelease;
const major = version.split('.')[0];
const minor = version.split('.')[1];
const patch = version.split('.')[2];

core.exportVariable('SEMANTIC_RELEASE', true);
core.exportVariable('SEMANTIC_RELEASE_VERSION', version);
core.exportVariable('SEMANTIC_RELEASE_MAJOR', major);
core.exportVariable('SEMANTIC_RELEASE_MINOR', minor);
core.exportVariable('SEMANTIC_RELEASE_PATCH', patch);

// TODO: core.setOutput as well? What are outputs, how do they differ from env vars?
} else {
core.exportVariable('SEMANTIC_RELEASE', false);
core.debug('No release published');
}
} catch (err) {
core.setFailed(`Action failed with error ${err}`);
async function run() {
const result = await semanticRelease();

if (!result) {
core.debug('No release published');

// set outputs
core.exportVariable('NEW_RELEASE_PUBLISHED', 'false');
core.setOutput('new-release-published', 'false');
return;
}

const { lastRelease, nextRelease, commits } = result;

core.debug(
`Published ${nextRelease.type} release version ${nextRelease.version} containing ${commits.length} commits.`,
);

if (lastRelease.version) {
core.debug(`The last release was "${lastRelease.version}".`);
}

// outputs
const { version } = nextRelease;
const major = version.split('.')[0];
const minor = version.split('.')[1];
const patch = version.split('.')[2];

// set outputs
core.exportVariable('NEW_RELEASE_PUBLISHED', 'true');
core.exportVariable('RELEASE_VERSION', version);
core.exportVariable('RELEASE_MAJOR', major);
core.exportVariable('RELEASE_MINOR', minor);
core.exportVariable('RELEASE_PATCH', patch);
core.setOutput('new-release-published', 'true');
core.setOutput('release-version', version);
core.setOutput('release-major', major);
core.setOutput('release-minor', minor);
core.setOutput('release-patch', patch);
}

main();
run().catch(core.setFailed);

0 comments on commit 1b6c3dc

Please sign in to comment.