Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

is_default_branch global expression #192

Merged
merged 4 commits into from Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -165,6 +165,27 @@ jobs:
org.opencontainers.image.description=this is a "good" example
org.opencontainers.image.vendor=MyCompany

global-exps:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Docker meta
uses: ./
with:
images: |
${{ env.DOCKER_IMAGE }}
ghcr.io/name/app
tags: |
type=sha
type=raw,value=gexp-branch-{{branch}}
type=raw,value=gexp-date-{{date 'YYYYMMDD'}}
type=raw,value=gexp-tag-{{tag}}
type=raw,value=gexp-baseref-{{base_ref}}
type=raw,value=gexp-defbranch,enable={{is_default_branch}}

json:
runs-on: ubuntu-latest
steps:
Expand Down
93 changes: 79 additions & 14 deletions README.md
Expand Up @@ -32,6 +32,12 @@ ___
* [Notes](#notes)
* [Latest tag](#latest-tag)
* [Global expressions](#global-expressions)
* [`{{branch}}`](#branch)
* [`{{tag}}`](#tag)
* [`{{sha}}`](#sha)
* [`{{base_ref}}`](#base_ref)
* [`{{is_default_branch}}`](#is_default_branch)
* [`{{date '<format>'}}`](#date-format)
* [Major version zero](#major-version-zero)
* [JSON output object](#json-output-object)
* [Overwrite labels](#overwrite-labels)
Expand Down Expand Up @@ -232,7 +238,7 @@ Content of `${{ steps.meta.outputs.bake-file }}` file will look like this with `
"org.opencontainers.image.source": "https://github.com/octocat/Hello-World",
"org.opencontainers.image.version": "1.2.3",
"org.opencontainers.image.created": "2020-01-10T00:30:00.000Z",
"org.opencontainers.image.revision": "90dd6032fac8bda1b6c4436a2e65de27961ed071",
"org.opencontainers.image.revision": "860c1904a1ce19322e91ac35af1ab07466440c37",
"org.opencontainers.image.licenses": "MIT"
},
"args": {
Expand Down Expand Up @@ -605,26 +611,28 @@ tags: |
* [`type=semver,pattern=...`](#typesemver)
* [`type=match,pattern=...`](#typematch)

For conditionally tagging with latest for a specific branch name, e.g. if your default branch name
is not `master`, use `type=raw` with a boolean expression:
For conditionally tagging with latest for a specific branch name, e.g. if your
default branch name is not `master`, use `type=raw` with a boolean expression:

```yaml
tags: |
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
# set latest tag for master branch
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
```
Comment on lines 617 to 621
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO you should remove this entirely. A solution which may not work under some circumstances should not be suggested, especially without warnings.

Copy link
Member Author

Choose a reason for hiding this comment

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

I actually updated this example with a hardcoded branch name to show how to handle this case for a specific branch as it seems still valid for me.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, right. I didn't notice.


### Global expressions
You can also use the [`{{is_default_branch}}` global expression](#is_default_branch)
to conditionally tag with latest for the default branch:

The following [Handlebars' template](https://handlebarsjs.com/guide/) expressions for `prefix`, `suffix` and `value`
attributes are available:
```yaml
tags: |
# set latest tag for default branch
type=raw,value=latest,enable={{is_default_branch}}
```

| Expression | Output |
|--------------------------|----------------------|
| `{{branch}}` | `master` |
| `{{tag}}` | `v1.2.3` |
| `{{sha}}` | `90dd603` |
| `{{base_ref}}` | `master` |
| `{{date 'YYYYMMDD'}}` | `20210326` |
### Global expressions

The following [Handlebars' template](https://handlebarsjs.com/guide/) expressions
for `prefix`, `suffix`, `value` and `enable` attributes are available:

```yaml
tags: |
Expand All @@ -634,6 +642,63 @@ tags: |
type=raw,value=mytag-{{branch}}-{{sha}}
```

#### `{{branch}}`

Returns the branch name that triggered the workflow run. Will be empty if not
a branch reference:

| Event | Ref | Output |
|-----------------|-------------------------------|---------------------|
| `pull_request` | `refs/pull/2/merge` | |
| `push` | `refs/heads/master` | `master` |
| `push` | `refs/heads/my/branch` | `my-branch` |
| `push tag` | `refs/tags/v1.2.3` | |

#### `{{tag}}`

Returns the tag name that triggered the workflow run. Will be empty if not a
tag reference:

| Event | Ref | Output |
|-----------------|-------------------------------|--------------------|
| `pull_request` | `refs/pull/2/merge` | |
| `push` | `refs/heads/master` | |
| `push` | `refs/heads/my/branch` | |
| `push tag` | `refs/tags/v1.2.3` | `v1.2.3` |

#### `{{sha}}`

Returns the short commit SHA that triggered the workflow run (e.g., `90dd603`).

#### `{{base_ref}}`

Returns the base ref or target branch of the pull request that triggered the
workflow run. Will be empty for a branch reference:

| Event | Ref | Output |
|-----------------|-------------------------------|--------------------|
| `pull_request` | `refs/pull/2/merge` | `master` |
| `push` | `refs/heads/master` | |
| `push` | `refs/heads/my/branch` | |
| `push tag` | `refs/tags/v1.2.3` | `master` |
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe you should not populate this variable in tag events, because it will always be the default branch.

Tags aren't anyhow tied to a branch in Git.

Example:

$ git checkout -b feature
$ git commit -m "Test commit" --allow-empty
$ git tag v1.2.3
$ git push --follow-tags

And the result is:

https://github.com/felipecrs/ghaction-dump-context/runs/6104549396?check_suite_focus=true#step:3:356

$ git checkout master
$ git tag v1.2.3-master
$ git push origin v1.2.3-master

Results in:
https://github.com/felipecrs/ghaction-dump-context/runs/6104557753?check_suite_focus=true#step:3:356

Copy link
Member Author

@crazy-max crazy-max Apr 22, 2022

Choose a reason for hiding this comment

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

Agree that a tag points to a commit, and commits exist independently of branches. But GitHub context seems to record the branch where this event occurs:

"base_ref": "refs/heads/master",

You can see it in your logs: https://github.com/felipecrs/ghaction-dump-context/runs/6104549396?check_suite_focus=true#step:3:360

Copy link
Contributor

Choose a reason for hiding this comment

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

Very interesting. Thank you.

Copy link
Contributor

@felipecrs felipecrs Apr 25, 2022

Choose a reason for hiding this comment

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

BTW, I made both master and feature point to the same revision, and it does not matter how I tag (or push) them, GitHub seems to just select one randomly to be the base_ref in case both matches the same revision.

https://github.com/felipecrs/ghaction-dump-context/runs/6164266775?check_suite_focus=true#step:3:360

This was created with:

$ git checkout master

$ git tag v1.2.3-sentfrommaster

$ git push origin v1.2.3-sentfrommaster

And it shows base_ref as feature.

This is just to say that this information isn't something to be relied on. I don't know if is worth mention this in the documentation or not.

Copy link
Member Author

Choose a reason for hiding this comment

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

I would say it's GitHub' side bug:

I suppose GitHub manages a DB that records the base ref of a tag. In this case you have created both tag against the same commit so I presume GitHub logic returns all tags for the same commit and matches the first one he found in the DB and therefore here the wrong ref is returned. Just speculations ofc but that seems to be it.

Maybe they SELECT 1 and ORDER by name or smth like that. Can you try to tag from master for a tag named smth like v1.2.3-aaaaa against the same commit and see what it returns?
Can you also tag against another commit from master?

Copy link
Contributor

Choose a reason for hiding this comment

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

Wow, that would make sense. Let me try again.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, check my new tags. I believe the base_ref gets populated with the first reference in alphabetical order.

  • refs/heads/<branch> will only be there if tags matches the latest revision of the branch
  • refs/heads/<branch> will always get precedence over refs/tags/<oldtag> since it's alphabetically ordered
  • That also explains why refs/heads/feature is always chosen instead of master, no matter what.

Copy link
Contributor

@felipecrs felipecrs Apr 25, 2022

Choose a reason for hiding this comment

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

BTW, in case you publish a tag against a revision which does not point to the latest version of a tag neither another tag, here is what you get (null):

https://github.com/felipecrs/ghaction-dump-context/runs/6164973057?check_suite_focus=true#step:3:360

Copy link
Member Author

@crazy-max crazy-max Apr 25, 2022

Choose a reason for hiding this comment

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

BTW, in case you publish a tag against a revision which does not point to the latest version of a tag neither another tag, here is what you get (null):

Yes just saw that too and I don't like that. I will remove support of base_ref (for push tag events) as it seems to be not what we want.


#### `{{is_default_branch}}`

Returns `true` if the branch that triggered the workflow run is the default
one, otherwise `false`.

Will compare against the branch name that triggered the workflow run or the
base ref or target branch for a pull request or a tag.

#### `{{date '<format>'}}`

Returns the current date rendered by its [moment format](https://momentjs.com/docs/#/displaying/format/).

| Expression | Output example |
|--------------------------------------------|-----------------------------------------|
| `{{date 'YYYYMMDD'}}` | `20200110` |
| `{{date 'dddd, MMMM Do YYYY, h:mm:ss a'}}` | `Friday, January 10th 2020, 3:25:50 pm` |

### Major version zero

Major version zero (`0.y.z`) is for initial development and **may** change at any time. This means the public API
Expand Down
86 changes: 71 additions & 15 deletions __tests__/meta.test.ts
Expand Up @@ -598,23 +598,26 @@ describe('push', () => {
`type=raw,value=mytag-{{branch}}`,
`type=raw,value=mytag-{{date 'YYYYMMDD'}}`,
`type=raw,value=mytag-tag-{{tag}}`,
`type=raw,value=mytag-baseref-{{base_ref}}`
`type=raw,value=mytag-baseref-{{base_ref}}`,
`type=raw,value=mytag-defbranch,enable={{is_default_branch}}`
],
} as Inputs,
{
main: 'mytag-master',
partial: [
'mytag-20200110',
'mytag-tag-',
'mytag-baseref-'
'mytag-baseref-',
'mytag-defbranch'
],
latest: false
} as Version,
[
'user/app:mytag-master',
'user/app:mytag-20200110',
'user/app:mytag-tag-',
'user/app:mytag-baseref-'
'user/app:mytag-baseref-',
'user/app:mytag-defbranch'
],
[
"org.opencontainers.image.title=Hello-World",
Expand Down Expand Up @@ -667,7 +670,8 @@ describe('push', () => {
tags: [
`type=edge,branch=master`,
`type=ref,event=branch,enable=false`,
`type=sha,format=long`
`type=sha,format=long`,
`type=raw,value=defbranch,enable={{is_default_branch}}`
],
} as Inputs,
{
Expand Down Expand Up @@ -1321,21 +1325,25 @@ describe('tag', () => {
images: ['org/app', 'ghcr.io/user/app'],
tags: [
`type=raw,{{tag}}-{{sha}}-foo`,
`type=raw,{{base_ref}}-foo`
`type=raw,{{base_ref}}-foo`,
`type=raw,defbranch-foo,enable={{is_default_branch}}`
]
} as Inputs,
{
main: 'v1.1.1-860c190-foo',
partial: [
'master-foo'
'master-foo',
'defbranch-foo'
],
latest: false
} as Version,
[
'org/app:v1.1.1-860c190-foo',
'org/app:master-foo',
'org/app:defbranch-foo',
'ghcr.io/user/app:v1.1.1-860c190-foo',
'ghcr.io/user/app:master-foo'
'ghcr.io/user/app:master-foo',
'ghcr.io/user/app:defbranch-foo'
],
[
"org.opencontainers.image.title=Hello-World",
Expand Down Expand Up @@ -2317,15 +2325,19 @@ describe('pr', () => {
images: ['org/app'],
tags: [
`type=raw,value=mytag-{{base_ref}}`,
`type=raw,mytag-defbranch,enable={{is_default_branch}}`
]
} as Inputs,
{
main: 'mytag-master',
partial: [],
partial: [
'mytag-defbranch'
],
latest: false
} as Version,
[
'org/app:mytag-master'
'org/app:mytag-master',
'org/app:mytag-defbranch'
],
[
"org.opencontainers.image.title=Hello-World",
Expand All @@ -2339,21 +2351,25 @@ describe('pr', () => {
]
],
[
'pr06',
'pr11',
'event_pull_request.env',
{
images: ['org/app'],
tags: [
`type=raw,value=mytag-{{base_ref}}`,
`type=raw,mytag-defbranch,enable={{is_default_branch}}`
]
} as Inputs,
{
main: 'mytag-master',
partial: [],
partial: [
'mytag-defbranch'
],
latest: false
} as Version,
[
'org/app:mytag-master'
'org/app:mytag-master',
'org/app:mytag-defbranch'
],
[
"org.opencontainers.image.title=Hello-World",
Expand Down Expand Up @@ -2521,19 +2537,25 @@ describe('schedule', () => {
images: ['org/app', 'ghcr.io/user/app'],
tags: [
`type=schedule`,
`type=sha,priority=2000`
`type=sha,priority=2000`,
`type=raw,value=defbranch,enable={{is_default_branch}}`
]
} as Inputs,
{
main: 'sha-860c190',
partial: ['nightly'],
partial: [
'nightly',
'defbranch'
],
latest: false
} as Version,
[
'org/app:sha-860c190',
'org/app:nightly',
'org/app:defbranch',
'ghcr.io/user/app:sha-860c190',
'ghcr.io/user/app:nightly'
'ghcr.io/user/app:nightly',
'ghcr.io/user/app:defbranch'
],
[
"org.opencontainers.image.title=Hello-World",
Expand Down Expand Up @@ -2611,6 +2633,40 @@ describe('release', () => {
"org.opencontainers.image.licenses=MIT"
]
],
[
'release02',
'event_release_created.env',
{
images: ['user/app'],
tags: [
`type=ref,event=tag`,
`type=raw,value=baseref-{{base_ref}}`,
`type=raw,value=defbranch,enable={{is_default_branch}}`
]
} as Inputs,
{
main: 'v1.1.1',
partial: [
'baseref-'
],
latest: true
} as Version,
[
'user/app:v1.1.1',
'user/app:baseref-',
'user/app:latest'
],
[
"org.opencontainers.image.title=Hello-World",
"org.opencontainers.image.description=This your first repo!",
"org.opencontainers.image.url=https://github.com/octocat/Hello-World",
"org.opencontainers.image.source=https://github.com/octocat/Hello-World",
"org.opencontainers.image.version=v1.1.1",
"org.opencontainers.image.created=2020-01-10T00:30:00.000Z",
"org.opencontainers.image.revision=860c1904a1ce19322e91ac35af1ab07466440c37",
"org.opencontainers.image.licenses=MIT"
]
]
])('given %s with %p event', tagsLabelsTest);
});

Expand Down
5 changes: 0 additions & 5 deletions __tests__/tag.test.ts
Expand Up @@ -417,11 +417,6 @@ describe('parse', () => {
{} as Tag,
true
],
[
`type=sha,enable=foo`,
{} as Tag,
true
],
[
`type=sha,format=foo`,
{} as Tag,
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/main.ts
Expand Up @@ -25,6 +25,12 @@ async function run() {
core.info(`runId: ${context.runId}`);
core.endGroup();

if (core.isDebug()) {
core.startGroup(`Webhook payload`);
core.info(JSON.stringify(context.payload, null, 2));
core.endGroup();
}

const meta: Meta = new Meta(inputs, context, repo);

const version: Version = meta.version;
Expand Down