summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Thomas <nick@gitlab.com>2016-12-13 19:21:30 +0000
committerNick Thomas <nick@gitlab.com>2016-12-13 19:31:23 +0000
commit1fdd5d682368b6807b89e8a399d7751c519737bd (patch)
tree91d90f856134edb4429268d0a2927a654376b3d3
parent7b63587d5d8f9865408a474efef5ca6064c29155 (diff)
downloadgitlab-ce-1fdd5d682368b6807b89e8a399d7751c519737bd.tar.gz
Introduce $CI_BUILD_REF_SLUG
-rw-r--r--app/models/ci/build.rb12
-rw-r--r--changelogs/unreleased/22849-ci-build-ref-slug.yml4
-rw-r--r--doc/ci/environments.md38
-rw-r--r--doc/ci/variables/README.md1
-rw-r--r--doc/ci/yaml/README.md15
-rw-r--r--spec/models/build_spec.rb19
6 files changed, 62 insertions, 27 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 88c46076df6..8a7c9e70dcf 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -184,6 +184,17 @@ module Ci
project.build_timeout
end
+ # A slugified version of the build ref, suitable for inclusion in URLs and
+ # domain names. Rules:
+ #
+ # * Lowercased
+ # * Anything not matching [a-z0-9-] is replaced with a -
+ # * Maximum length is 63 bytes
+ def ref_slug
+ slugified = ref.to_s.downcase
+ slugified.gsub(/[^a-z0-9]/, '-')[0..62]
+ end
+
def variables
variables = predefined_variables
variables += project.predefined_variables
@@ -518,6 +529,7 @@ module Ci
{ key: 'CI_BUILD_REF', value: sha, public: true },
{ key: 'CI_BUILD_BEFORE_SHA', value: before_sha, public: true },
{ key: 'CI_BUILD_REF_NAME', value: ref, public: true },
+ { key: 'CI_BUILD_REF_SLUG', value: ref_slug, public: true },
{ key: 'CI_BUILD_NAME', value: name, public: true },
{ key: 'CI_BUILD_STAGE', value: stage, public: true },
{ key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
diff --git a/changelogs/unreleased/22849-ci-build-ref-slug.yml b/changelogs/unreleased/22849-ci-build-ref-slug.yml
new file mode 100644
index 00000000000..b159ecca6d8
--- /dev/null
+++ b/changelogs/unreleased/22849-ci-build-ref-slug.yml
@@ -0,0 +1,4 @@
+---
+title: Introduce $CI_BUILD_REF_SLUG
+merge_request: 8072
+author:
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index 9dd84a5ff81..705bca6cc1f 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -248,7 +248,7 @@ deploy_review:
- echo "Deploy a review app"
environment:
name: review/$CI_BUILD_REF_NAME
- url: https://$CI_BUILD_REF_NAME.example.com
+ url: https://$CI_BUILD_REF_SLUG.example.com
only:
- branches
except:
@@ -259,13 +259,14 @@ Let's break it down in pieces. The job's name is `deploy_review` and it runs
on the `deploy` stage. The `script` at this point is fictional, you'd have to
use your own based on your deployment. Then, we set the `environment` with the
`environment:name` being `review/$CI_BUILD_REF_NAME`. Now that's an interesting
-one. Since the [environment name][env-name] can contain also slashes (`/`), we
-can use this pattern to distinguish between dynamic environments and the regular
+one. Since the [environment name][env-name] can contain slashes (`/`), we can
+use this pattern to distinguish between dynamic environments and the regular
ones.
So, the first part is `review`, followed by a `/` and then `$CI_BUILD_REF_NAME`
-which takes the value of the branch name. We also use the same
-`$CI_BUILD_REF_NAME` value in the `environment:url` so that the environment
+which takes the value of the branch name. Since `$CI_BUILD_REF_NAME` itself may
+also contain `/`, or other characters that would be invalid in a domain name or
+URL, we use `$CI_BUILD_REF_SLUG` in the `environment:url` so that the environment
can get a specific and distinct URL for each branch. Again, the way you set up
the webserver to serve these requests is based on your setup.
@@ -299,7 +300,7 @@ deploy_review:
- echo "Deploy a review app"
environment:
name: review/$CI_BUILD_REF_NAME
- url: https://$CI_BUILD_REF_NAME.example.com
+ url: https://$CI_BUILD_REF_SLUG.example.com
only:
- branches
except:
@@ -329,16 +330,16 @@ deploy_prod:
A more realistic example would include copying files to a location where a
webserver (NGINX) could then read and serve. The example below will copy the
-`public` directory to `/srv/nginx/$CI_BUILD_REF_NAME/public`:
+`public` directory to `/srv/nginx/$CI_BUILD_REF_SLUG/public`:
```yaml
review_app:
stage: deploy
script:
- - rsync -av --delete public /srv/nginx/$CI_BUILD_REF_NAME
+ - rsync -av --delete public /srv/nginx/$CI_BUILD_REF_SLUG
environment:
name: review/$CI_BUILD_REF_NAME
- url: https://$CI_BUILD_REF_NAME.example.com
+ url: https://$CI_BUILD_REF_SLUG.example.com
```
It is assumed that the user has already setup NGINX and GitLab Runner in the
@@ -346,7 +347,7 @@ server this job will run on.
>**Note:**
Be sure to check out the [limitations](#limitations) section for some edge
-cases regarding naming of you branches and Review Apps.
+cases regarding naming of your branches and Review Apps.
---
@@ -418,7 +419,7 @@ deploy_review:
- echo "Deploy a review app"
environment:
name: review/$CI_BUILD_REF_NAME
- url: https://$CI_BUILD_REF_NAME.example.com
+ url: https://$CI_BUILD_REF_SLUG.example.com
on_stop: stop_review
only:
- branches
@@ -480,9 +481,8 @@ exist, you should see something like:
## Checkout deployments locally
-Since 8.13, a reference in the git repository is saved for each deployment. So
-knowing what the state is of your current environments is only a `git fetch`
-away.
+Since 8.13, a reference in the git repository is saved for each deployment, so
+knowing the state of your current environments is only a `git fetch` away.
In your git config, append the `[remote "<your-remote>"]` block with an extra
fetch line:
@@ -493,10 +493,10 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
## Limitations
-1. If the branch name contains special characters (`/`), and you use the
- `$CI_BUILD_REF_NAME` variable to dynamically create environments, there might
- be complications during your Review Apps deployment. Follow the
- [issue 22849][ce-22849] for more information.
+1. `$CI_BUILD_REF_SLUG` is not *guaranteed* to be unique, so there is a small
+ chance of collisions between similarly-named branches (`fix-foo` would
+ conflict with `fix/foo`, for instance). Following a well-defined workflow
+ such as [GitLab Flow][gitlab-flow] can keep this from being a problem.
1. You are limited to use only the [CI predefined variables][variables] in the
`environment: name`. If you try to re-use variables defined inside `script`
as part of the environment name, it will not work.
@@ -520,6 +520,6 @@ Below are some links you may find interesting:
[only]: yaml/README.md#only-and-except
[onstop]: yaml/README.md#environment-on_stop
[ce-7015]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7015
-[ce-22849]: https://gitlab.com/gitlab-org/gitlab-ce/issues/22849
+[gitlab-flow]: ../workflow/gitlab_flow.md
[gitlab runner]: https://docs.gitlab.com/runner/
[git-strategy]: yaml/README.md#git-strategy
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index d142fe266a2..e0ff9756868 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -40,6 +40,7 @@ version of Runner required.
| **CI_BUILD_NAME** | all | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
| **CI_BUILD_STAGE** | all | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_BUILD_REF_NAME** | all | all | The branch or tag name for which project is built |
+| **CI_BUILD_REF_SLUG** | 8.15 | all | `$CI_BUILD_REF_NAME` lowercased, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. |
| **CI_BUILD_REPO** | all | all | The URL to clone the Git repository |
| **CI_BUILD_TRIGGERED** | all | 0.5 | The flag to indicate that build was [triggered] |
| **CI_BUILD_MANUAL** | 8.12 | all | The flag to indicate that build was manually started |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 5f88974d360..5e8d888e555 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -690,18 +690,12 @@ The `stop_review_app` job is **required** to have the following keywords defined
#### dynamic environments
> [Introduced][ce-6323] in GitLab 8.12 and GitLab Runner 1.6.
+ `$CI_BUILD_REF_SLUG` was [introduced][ce-8072] in GitLab 8.15.
`environment` can also represent a configuration hash with `name` and `url`.
These parameters can use any of the defined [CI variables](#variables)
(including predefined, secure variables and `.gitlab-ci.yml` variables).
->**Note:**
-Be aware than if the branch name contains special characters and you use the
-`$CI_BUILD_REF_NAME` variable to dynamically create environments, there might
-be complications during deployment. Follow the
-[issue 22849](https://gitlab.com/gitlab-org/gitlab-ce/issues/22849) for more
-information.
-
For example:
```
@@ -710,7 +704,7 @@ deploy as review app:
script: make deploy
environment:
name: review-apps/$CI_BUILD_REF_NAME
- url: https://$CI_BUILD_REF_NAME.review.example.com/
+ url: https://$CI_BUILD_REF_SLUG.review.example.com/
```
The `deploy as review app` job will be marked as deployment to dynamically
@@ -726,6 +720,10 @@ The common use case is to create dynamic environments for branches and use them
as Review Apps. You can see a simple example using Review Apps at
https://gitlab.com/gitlab-examples/review-apps-nginx/.
+`$CI_BUILD_REF_SLUG` is another environment variable set by the runner, based on
+`$CI_BUILD_REF_NAME` but lower-cased, and with some characters replaced with
+`-`, making it suitable for use in URLs and domain names.
+
### artifacts
>**Notes:**
@@ -1245,4 +1243,5 @@ CI with various languages.
[ce-6323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6323
[environment]: ../environments.md
[ce-6669]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6669
+[ce-8072]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/xxxx
[variables]: ../variables/README.md
diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb
index d4970e38f7c..4d6790ddbd4 100644
--- a/spec/models/build_spec.rb
+++ b/spec/models/build_spec.rb
@@ -254,6 +254,24 @@ describe Ci::Build, models: true do
end
end
+ describe '#ref_slug' do
+ {
+ 'master' => 'master',
+ '1-foo' => '1-foo',
+ 'fix/1-foo' => 'fix-1-foo',
+ 'fix-1-foo' => 'fix-1-foo',
+ 'a' * 63 => 'a' * 63,
+ 'a' * 64 => 'a' * 63,
+ 'FOO' => 'foo',
+ }.each do |ref, slug|
+ it "transforms #{ref} to #{slug}" do
+ build.ref = ref
+
+ expect(build.ref_slug).to eq(slug)
+ end
+ end
+ end
+
describe '#variables' do
let(:container_registry_enabled) { false }
let(:predefined_variables) do
@@ -265,6 +283,7 @@ describe Ci::Build, models: true do
{ key: 'CI_BUILD_REF', value: build.sha, public: true },
{ key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
{ key: 'CI_BUILD_REF_NAME', value: 'master', public: true },
+ { key: 'CI_BUILD_REF_SLUG', value: 'master', public: true },
{ key: 'CI_BUILD_NAME', value: 'test', public: true },
{ key: 'CI_BUILD_STAGE', value: 'test', public: true },
{ key: 'CI_SERVER_NAME', value: 'GitLab', public: true },