diff options
23 files changed, 775 insertions, 682 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index f279a57105c..e075de055e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 8.17.2 (2017-03-01) + +- Expire all webpack assets after 8.17.1 included a badly compiled asset. !9602 + ## 8.17.1 (2017-02-28) - Replace setInterval with setTimeout to prevent highly frequent requests. !9271 (Takuya Noguchi) diff --git a/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 b/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 index 1ca01d3bdb9..958a0cc6d50 100644 --- a/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 +++ b/app/assets/javascripts/issuable/time_tracking/time_tracking_bundle.js.es6 @@ -39,8 +39,9 @@ require('../../subbable_resource'); listenForSlashCommands() { $(document).on('ajax:success', '.gfm-form', (e, data) => { const subscribedCommands = ['spend_time', 'time_estimate']; - const changedCommands = data.commands_changes; - + const changedCommands = data.commands_changes + ? Object.keys(data.commands_changes) + : []; if (changedCommands && _.intersection(subscribedCommands, changedCommands).length) { this.fetchIssuable(); } diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 03504255bda..47fa0f2eb96 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -246,12 +246,21 @@ require('./task_list'); }; Notes.prototype.handleCreateChanges = function(note) { + var votesBlock; if (typeof note === 'undefined') { return; } - if (note.commands_changes && note.commands_changes.indexOf('merge') !== -1) { - $.get(mrRefreshWidgetUrl); + if (note.commands_changes) { + if ('merge' in note.commands_changes) { + $.get(mrRefreshWidgetUrl); + } + + if ('emoji_award' in note.commands_changes) { + votesBlock = $('.js-awards-block').eq(0); + gl.awardsHandler.addAwardToEmojiBar(votesBlock, note.commands_changes.emoji_award); + return gl.awardsHandler.scrollToAwards(); + } } }; @@ -262,26 +271,16 @@ require('./task_list'); */ Notes.prototype.renderNote = function(note) { - var $notesList, votesBlock; + var $notesList; if (!note.valid) { - if (note.award) { - new Flash('You have already awarded this emoji!', 'alert', this.parentTimeline); - } - else { - if (note.errors.commands_only) { - new Flash(note.errors.commands_only, 'notice', this.parentTimeline); - this.refresh(); - } + if (note.errors.commands_only) { + new Flash(note.errors.commands_only, 'notice', this.parentTimeline); + this.refresh(); } return; } - if (note.award) { - votesBlock = $('.js-awards-block').eq(0); - gl.awardsHandler.addAwardToEmojiBar(votesBlock, note.name); - return gl.awardsHandler.scrollToAwards(); - // render note if it not present in loaded list - // or skip if rendered - } else if (this.isNewNote(note)) { + + if (this.isNewNote(note)) { this.note_ids.push(note.id); $notesList = $('ul.main-notes-list'); $notesList.append(note.html).syntaxHighlight(); diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index b033f7b5ea9..5cf3a7f593b 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -148,17 +148,10 @@ class Projects::NotesController < Projects::ApplicationController def note_json(note) attrs = { - award: false, id: note.id } - if note.is_a?(AwardEmoji) - attrs.merge!( - valid: note.valid?, - award: true, - name: note.name - ) - elsif note.persisted? + if note.persisted? Banzai::NoteRenderer.render([note], @project, current_user) attrs.merge!( @@ -198,7 +191,7 @@ class Projects::NotesController < Projects::ApplicationController ) end - attrs[:commands_changes] = note.commands_changes unless attrs[:award] + attrs[:commands_changes] = note.commands_changes attrs end diff --git a/app/models/note.rb b/app/models/note.rb index d6d5396afa5..4c97e4a986c 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -231,10 +231,6 @@ class Note < ActiveRecord::Base note =~ /\A#{Banzai::Filter::EmojiFilter.emoji_pattern}\s?\Z/ end - def award_emoji_name - note.match(Banzai::Filter::EmojiFilter.emoji_pattern)[1] - end - def to_ability_name for_personal_snippet? ? 'personal_snippet' : noteable_type.underscore end diff --git a/app/models/user.rb b/app/models/user.rb index 6fb5ac4a4ef..8443594c055 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -346,7 +346,11 @@ class User < ActiveRecord::Base # Return (create if necessary) the ghost user. The ghost user # owns records previously belonging to deleted users. def ghost - User.find_by_ghost(true) || create_ghost_user + unique_internal(where(ghost: true), 'ghost', 'ghost%s@example.com') do |u| + u.bio = 'This is a "Ghost User", created to hold all issues authored by users that have since been deleted. This user cannot be removed.' + u.state = :blocked + u.name = 'Ghost User' + end end end @@ -1017,10 +1021,14 @@ class User < ActiveRecord::Base end end - def self.create_ghost_user - # Since we only want a single ghost user in an instance, we use an + def self.unique_internal(scope, username, email_pattern, &b) + scope.first || create_unique_internal(scope, username, email_pattern, &b) + end + + def self.create_unique_internal(scope, username, email_pattern, &creation_block) + # Since we only want a single one of these in an instance, we use an # exclusive lease to ensure than this block is never run concurrently. - lease_key = "ghost_user_creation" + lease_key = "user:unique_internal:#{username}" lease = Gitlab::ExclusiveLease.new(lease_key, timeout: 1.minute.to_i) until uuid = lease.try_obtain @@ -1029,25 +1037,25 @@ class User < ActiveRecord::Base sleep(1) end - # Recheck if a ghost user is already present. One might have been + # Recheck if the user is already present. One might have been # added between the time we last checked (first line of this method) # and the time we acquired the lock. - ghost_user = User.find_by_ghost(true) - return ghost_user if ghost_user.present? + existing_user = uncached { scope.first } + return existing_user if existing_user.present? uniquify = Uniquify.new - username = uniquify.string("ghost") { |s| User.find_by_username(s) } + username = uniquify.string(username) { |s| User.find_by_username(s) } - email = uniquify.string(-> (n) { "ghost#{n}@example.com" }) do |s| + email = uniquify.string(-> (n) { Kernel.sprintf(email_pattern, n) }) do |s| User.find_by_email(s) end - bio = 'This is a "Ghost User", created to hold all issues authored by users that have since been deleted. This user cannot be removed.' - - User.create( - username: username, password: Devise.friendly_token, bio: bio, - email: email, name: "Ghost User", state: :blocked, ghost: true + scope.create( + username: username, + password: Devise.friendly_token, + email: email, + &creation_block ) ensure Gitlab::ExclusiveLease.cancel(lease_key, uuid) diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 9500faf2862..b618c3e038e 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -203,6 +203,7 @@ class IssuableBaseService < BaseService change_state(issuable) change_subscription(issuable) change_todo(issuable) + toggle_award(issuable) filter_params(issuable) old_labels = issuable.labels.to_a old_mentioned_users = issuable.mentioned_users.to_a @@ -263,6 +264,14 @@ class IssuableBaseService < BaseService end end + def toggle_award(issuable) + award = params.delete(:emoji_award) + if award + todo_service.new_award_emoji(issuable, current_user) + issuable.toggle_award_emoji(award, current_user) + end + end + def has_changes?(issuable, old_labels: []) valid_attrs = [:title, :description, :assignee_id, :milestone_id, :target_branch] diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index b4f8b33d564..61d66a26932 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -8,14 +8,6 @@ module Notes note.author = current_user note.system = false - if note.award_emoji? - noteable = note.noteable - if noteable.user_can_award?(current_user, note.award_emoji_name) - todo_service.new_award_emoji(noteable, current_user) - return noteable.create_award_emoji(note.award_emoji_name, current_user) - end - end - # We execute commands (extracted from `params[:note]`) on the noteable # **before** we save the note because if the note consists of commands # only, there is no need be create a note! @@ -48,7 +40,7 @@ module Notes note.errors.add(:commands_only, 'Commands applied') end - note.commands_changes = command_params.keys + note.commands_changes = command_params end note diff --git a/app/services/slash_commands/interpret_service.rb b/app/services/slash_commands/interpret_service.rb index 3e0a85cf059..c39a2c4cf1e 100644 --- a/app/services/slash_commands/interpret_service.rb +++ b/app/services/slash_commands/interpret_service.rb @@ -255,6 +255,18 @@ module SlashCommands @updates[:wip_event] = issuable.work_in_progress? ? 'unwip' : 'wip' end + desc 'Toggle emoji reward' + params ':emoji:' + condition do + issuable.persisted? + end + command :award do |emoji| + name = award_emoji_name(emoji) + if name && issuable.user_can_award?(current_user, name) + @updates[:emoji_award] = name + end + end + desc 'Set time estimate' params '<1w 3d 2h 14m>' condition do @@ -329,5 +341,10 @@ module SlashCommands ext.references(type) end + + def award_emoji_name(emoji) + match = emoji.match(Banzai::Filter::EmojiFilter.emoji_pattern) + match[1] if match + end end end diff --git a/changelogs/unreleased/25437-just-emoji.yml b/changelogs/unreleased/25437-just-emoji.yml new file mode 100644 index 00000000000..ceb81a47f2d --- /dev/null +++ b/changelogs/unreleased/25437-just-emoji.yml @@ -0,0 +1,4 @@ +--- +title: Introduce /award slash command; Allow posting of just an emoji in comment +merge_request: 9382 +author: mhasbini diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md new file mode 100644 index 00000000000..6edf99239ea --- /dev/null +++ b/doc/user/project/pages/getting_started_part_four.md @@ -0,0 +1,382 @@ +# GitLab Pages from A to Z: Part 4 + +- [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md) +- [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md) +- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md) +- **Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages** + +## Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages + +[GitLab CI](https://about.gitlab.com/gitlab-ci/) serves +numerous purposes, to build, test, and deploy your app +from GitLab through +[Continuous Integration, Continuous Delivery, and Continuous Deployment](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) +methods. You will need it to build your website with GitLab Pages, +and deploy it to the Pages server. + +What this file actually does is telling the +[GitLab Runner](https://docs.gitlab.com/runner/) to run scripts +as you would do from the command line. The Runner acts as your +terminal. GitLab CI tells the Runner which commands to run. +Both are built-in in GitLab, and you don't need to set up +anything for them to work. + +Explaining [every detail of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html) +and GitLab Runner is out of the scope of this guide, but we'll +need to understand just a few things to be able to write our own +`.gitlab-ci.yml` or tweak an existing one. It's an +[Yaml](http://docs.ansible.com/ansible/YAMLSyntax.html) file, +with its own syntax. You can always check your CI syntax with +the [GitLab CI Lint Tool](https://gitlab.com/ci/lint). + +**Practical Example:** + +Let's consider you have a [Jekyll](https://jekyllrb.com/) site. +To build it locally, you would open your terminal, and run `jekyll build`. +Of course, before building it, you had to install Jekyll in your computer. +For that, you had to open your terminal and run `gem install jekyll`. +Right? GitLab CI + GitLab Runner do the same thing. But you need to +write in the `.gitlab-ci.yml` the script you want to run so +GitLab Runner will do it for you. It looks more complicated then it +is. What you need to tell the Runner: + +``` +$ gem install jekyll +$ jekyll build +``` + +### Script + +To transpose this script to Yaml, it would be like this: + +```yaml +script: + - gem install jekyll + - jekyll build +``` + +### Job + +So far so good. Now, each `script`, in GitLab is organized by +a `job`, which is a bunch of scripts and settings you want to +apply to that specific task. + +```yaml +job: + script: + - gem install jekyll + - jekyll build +``` + +For GitLab Pages, this `job` has a specific name, called `pages`, +which tells the Runner you want that task to deploy your website +with GitLab Pages: + +```yaml +pages: + script: + - gem install jekyll + - jekyll build +``` + +### The `public` directory + +We also need to tell Jekyll where do you want the website to build, +and GitLab Pages will only consider files in a directory called `public`. +To do that with Jekyll, we need to add a flag specifying the +[destination (`-d`)](https://jekyllrb.com/docs/usage/) of the +built website: `jekyll build -d public`. Of course, we need +to tell this to our Runner: + +```yaml +pages: + script: + - gem install jekyll + - jekyll build -d public +``` + +### Artifacts + +We also need to tell the Runner that this _job_ generates +_artifacts_, which is the site built by Jekyll. +Where are these artifacts stored? In the `public` directory: + +```yaml +pages: + script: + - gem install jekyll + - jekyll build -d public + artifacts: + paths: + - public +``` + +The script above would be enough to build your Jekyll +site with GitLab Pages. But, from Jekyll 3.4.0 on, its default +template originated by `jekyll new project` requires +[Bundler](http://bundler.io/) to install Jekyll dependencies +and the default theme. To adjust our script to meet these new +requirements, we only need to install and build Jekyll with Bundler: + +```yaml +pages: + script: + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +That's it! A `.gitlab-ci.yml` with the content above would deploy +your Jekyll 3.4.0 site with GitLab Pages. This is the minimum +configuration for our example. On the steps below, we'll refine +the script by adding extra options to our GitLab CI. + +### Image + +At this point, you probably ask yourself: "okay, but to install Jekyll +I need Ruby. Where is Ruby on that script?". The answer is simple: the +first thing GitLab Runner will look for in your `.gitlab-ci.yml` is a +[Docker](https://www.docker.com/) image specifying what do you need in +your container to run that script: + +```yaml +image: ruby:2.3 + +pages: + script: + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public +``` + +In this case, you're telling the Runner to pull this image, which +contains Ruby 2.3 as part of its file system. When you don't specify +this image in your configuration, the Runner will use a default +image, which is Ruby 2.1. + +If your SSG needs [NodeJS](https://nodejs.org/) to build, you'll +need to specify which image you want to use, and this image should +contain NodeJS as part of its file system. E.g., for a +[Hexo](https://gitlab.com/pages/hexo) site, you can use `image: node:4.2.2`. + +>**Note:** +We're not trying to explain what a Docker image is, +we just need to introduce the concept with a minimum viable +explanation. To know more about Docker images, please visit +their website or take a look at a +[summarized explanation](http://paislee.io/how-to-automate-docker-deployments/) here. + +Let's go a little further. + +### Branching + +If you use GitLab as a version control platform, you will have your +branching strategy to work on your project. Meaning, you will have +other branches in your project, but you'll want only pushes to the +default branch (usually `master`) to be deployed to your website. +To do that, we need to add another line to our CI, telling the Runner +to only perform that _job_ called `pages` on the `master` branch `only`: + +```yaml +image: ruby:2.3 + +pages: + script: + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + only: + - master +``` + +### Stages + +Another interesting concept to keep in mind are build stages. +Your web app can pass through a lot of tests and other tasks +until it's deployed to staging or production environments. +There are three default stages on GitLab CI: build, test, +and deploy. To specify which stage your _job_ is running, +simply add another line to your CI: + +```yaml +image: ruby:2.3 + +pages: + stage: deploy + script: + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + only: + - master +``` + +You might ask yourself: "why should I bother with stages +at all?" Well, let's say you want to be able to test your +script and check the built site before deploying your site +to production. You want to run the test exactly as your +script will do when you push to `master`. It's simple, +let's add another task (_job_) to our CI, telling it to +test every push to other branches, `except` the `master` branch: + +```yaml +image: ruby:2.3 + +pages: + stage: deploy + script: + - bundle install + - bundle exec jekyll build -d public + artifacts: + paths: + - public + only: + - master + +test: + stage: test + script: + - bundle install + - bundle exec jekyll build -d test + artifacts: + paths: + - test + except: + - master +``` + +The `test` job is running on the stage `test`, Jekyll +will build the site in a directory called `test`, and +this job will affect all the branches except `master`. + +The best benefit of applying _stages_ to different +_jobs_ is that every job in the same stage builds in +parallel. So, if your web app needs more than one test +before being deployed, you can run all your test at the +same time, it's not necessary to wait one test to finish +to run the other. Of course, this is just a brief +introduction of GitLab CI and GitLab Runner, which are +tools much more powerful than that. This is what you +need to be able to create and tweak your builds for +your GitLab Pages site. + +### Before Script + +To avoid running the same script multiple times across +your _jobs_, you can add the parameter `before_script`, +in which you specify which commands you want to run for +every single _job_. In our example, notice that we run +`bundle install` for both jobs, `pages` and `test`. +We don't need to repeat it: + +```yaml +image: ruby:2.3 + +before_script: + - bundle install + +pages: + stage: deploy + script: + - bundle exec jekyll build -d public + artifacts: + paths: + - public + only: + - master + +test: + stage: test + script: + - bundle exec jekyll build -d test + artifacts: + paths: + - test + except: + - master +``` + +### Caching Dependencies + +If you want to cache the installation files for your +projects dependencies, for building faster, you can +use the parameter `cache`. For this example, we'll +cache Jekyll dependencies in a `vendor` directory +when we run `bundle install`: + +```yaml +image: ruby:2.3 + +cache: + paths: + - vendor/ + +before_script: + - bundle install --path vendor + +pages: + stage: deploy + script: + - bundle exec jekyll build -d public + artifacts: + paths: + - public + only: + - master + +test: + stage: test + script: + - bundle exec jekyll build -d test + artifacts: + paths: + - test + except: + - master +``` + +For this specific case, we need to exclude `/vendor` +from Jekyll `_config.yml` file, otherwise Jekyll will +understand it as a regular directory to build +together with the site: + +```yml +exclude: + - vendor +``` + +There we go! Now our GitLab CI not only builds our website, +but also **continuously test** pushes to feature-branches, +**caches** dependencies installed with Bundler, and +**continuously deploy** every push to the `master` branch. + +## Advanced GitLab CI for GitLab Pages + +What you can do with GitLab CI is pretty much up to your +creativity. Once you get used to it, you start creating +awesome scripts that automate most of tasks you'd do +manually in the past. Read through the +[documentation of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html) +to understand how to go even further on your scripts. + +- On this blog post, understand the concept of +[using GitLab CI `environments` to deploy your +web app to staging and production](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/). +- On this post, learn [how to run jobs sequentially, +in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/) +- On this blog post, we go through the process of +[pulling specific directories from different projects](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) +to deploy this website you're looking at, docs.gitlab.com. +- On this blog post, we teach you [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). + +||| +|:--|--:| +|[**← Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates**](getting_started_part_three.md)|| diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md index c5b1aa4b654..582a4afbab4 100644 --- a/doc/user/project/pages/getting_started_part_one.md +++ b/doc/user/project/pages/getting_started_part_one.md @@ -1,15 +1,28 @@ # GitLab Pages from A to Z: Part 1 -- **Part 1: Static Sites, Domains, DNS Records, and SSL/TLS Certificates** -- _[Part 2: Quick Start Guide - Setting Up GitLab Pages](getting_started_part_two.md)_ -- _[Part 3: Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_three.md)_ +- **Part 1: Static sites and GitLab Pages domains** +- [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md) +- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md) +- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md) ----- +## GitLab Pages form A to Z This is a comprehensive guide, made for those who want to publish a website with GitLab Pages but aren't familiar with the entire process involved. +This [first part](#what-you-need-to-know-before-getting-started) of this series will present you to the concepts of +static sites, and go over how the default Pages domains work. + +The [second part](getting_started_part_two.md) covers how to get started with GitLab Pages: deploy +a website from a forked project or create a new one from scratch. + +The [third part](getting_started_part_three.md) will show you how to set up a custom domain or subdomain +to your site already deployed. + +The [fourth part](getting_started_part_four.md) will show you how to create and tweak GitLab CI for +GitLab Pages. + To **enable** GitLab Pages for GitLab CE (Community Edition) and GitLab EE (Enterprise Edition), please read the [admin documentation](https://docs.gitlab.com/ce/administration/pages/index.html), @@ -33,7 +46,7 @@ CSS, and JS, or use a [Static Site Generator (SSG)](https://www.staticgen.com/) to simplify your code and build the static site for you, which is highly recommendable and much faster than hardcoding. ---- +#### Further Reading - Read through this technical overview on [Static versus Dynamic Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) - Understand [how modern Static Site Generators work](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) and what you can add to your static site @@ -88,179 +101,6 @@ your website will be published under `https://websites.gitlab.io`. - On your GitLab instance, replace `gitlab.io` above with your Pages server domain. Ask your sysadmin for this information. -### DNS Records - -A Domain Name System (DNS) web service routes visitors to websites -by translating domain names (such as `www.example.com`) into the -numeric IP addresses (such as `192.0.2.1`) that computers use to -connect to each other. - -A DNS record is created to point a (sub)domain to a certain location, -which can be an IP address or another domain. In case you want to use -GitLab Pages with your own (sub)domain, you need to access your domain's -registrar control panel to add a DNS record pointing it back to your -GitLab Pages site. - -Note that **how to** add DNS records depends on which server your domain -is hosted on. Every control panel has its own place to do it. If you are -not an admin of your domain, and don't have access to your registrar, -you'll need to ask for the technical support of your hosting service -to do it for you. - -To help you out, we've gathered some instructions on how to do that -for the most popular hosting services: - -- [Amazon](http://docs.aws.amazon.com/gettingstarted/latest/swh/getting-started-configure-route53.html) -- [Bluehost](https://my.bluehost.com/cgi/help/559) -- [CloudFlare](https://support.cloudflare.com/hc/en-us/articles/200169096-How-do-I-add-A-records-) -- [cPanel](https://documentation.cpanel.net/display/ALD/Edit+DNS+Zone) -- [DreamHost](https://help.dreamhost.com/hc/en-us/articles/215414867-How-do-I-add-custom-DNS-records-) -- [Go Daddy](https://www.godaddy.com/help/add-an-a-record-19238) -- [Hostgator](http://support.hostgator.com/articles/changing-dns-records) -- [Inmotion hosting](https://my.bluehost.com/cgi/help/559) -- [Media Temple](https://mediatemple.net/community/products/dv/204403794/how-can-i-change-the-dns-records-for-my-domain) -- [Microsoft](https://msdn.microsoft.com/en-us/library/bb727018.aspx) - -If your hosting service is not listed above, you can just try to -search the web for "how to add dns record on <my hosting service>". - -#### DNS A record - -In case you want to point a root domain (`example.com`) to your -GitLab Pages site, deployed to `namespace.gitlab.io`, you need to -log into your domain's admin control panel and add a DNS `A` record -pointing your domain to Pages' server IP address. For projects on -GitLab.com, this IP is `104.208.235.32`. For projects leaving in -other GitLab instances (CE or EE), please contact your sysadmin -asking for this information (which IP address is Pages server -running on your instance). - -**Practical Example:** - -![DNS A record pointing to GitLab.com Pages server](img/dns_a_record_example.png) - -#### DNS CNAME record - -In case you want to point a subdomain (`hello-world.example.com`) -to your GitLab Pages site initially deployed to `namespace.gitlab.io`, -you need to log into your domain's admin control panel and add a DNS -`CNAME` record pointing your subdomain to your website URL -(`namespace.gitlab.io`) address. - -Notice that, despite it's a user or project website, the `CNAME` -should point to your Pages domain (`namespace.gitlab.io`), -without any `/project-name`. - -**Practical Example:** - -![DNS CNAME record pointing to GitLab.com project](img/dns_cname_record_example.png) - -#### TL;DR - -| From | DNS Record | To | -| ---- | ---------- | -- | -| domain.com | A | 104.208.235.32 | -| subdomain.domain.com | CNAME | namespace.gitlab.io | - -> **Notes**: -> -> - **Do not** use a CNAME record if you want to point your -`domain.com` to your GitLab Pages site. Use an `A` record instead. -> - **Do not** add any special chars after the default Pages -domain. E.g., **do not** point your `subdomain.domain.com` to -`namespace.gitlab.io.` or `namespace.gitlab.io/`. - -### SSL/TLS Certificates - -Every GitLab Pages project on GitLab.com will be available under -HTTPS for the default Pages domain (`*.gitlab.io`). Once you set -up your Pages project with your custom (sub)domain, if you want -it secured by HTTPS, you will have to issue a certificate for that -(sub)domain and install it on your project. - ->**Note:** -Certificates are NOT required to add to your custom -(sub)domain on your GitLab Pages project, though they are -highly recommendable. - -The importance of having any website securely served under HTTPS -is explained on the introductory section of the blog post -[Secure GitLab Pages with StartSSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/#https-a-quick-overview). - -The reason why certificates are so important is that they encrypt -the connection between the **client** (you, me, your visitors) -and the **server** (where you site lives), through a keychain of -authentications and validations. - -### Issuing Certificates - -GitLab Pages accepts [PEM](https://support.quovadisglobal.com/kb/a37/what-is-pem-format.aspx) certificates issued by -[Certificate Authorities (CA)](https://en.wikipedia.org/wiki/Certificate_authority) -and self-signed certificates. Of course, -[you'd rather issue a certificate than generate a self-signed](https://en.wikipedia.org/wiki/Self-signed_certificate), -for security reasons and for having browsers trusting your -site's certificate. - -There are several different kinds of certificates, each one -with certain security level. A static personal website will -not require the same security level as an online banking web app, -for instance. There are a couple Certificate Authorities that -offer free certificates, aiming to make the internet more secure -to everyone. The most popular is [Let's Encrypt](https://letsencrypt.org/), -which issues certificates trusted by most of browsers, it's open -source, and free to use. Please read through this tutorial to -understand [how to secure your GitLab Pages website with Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/). - -With the same popularity, there are [certificates issued by CloudFlare](https://www.cloudflare.com/ssl/), -which also offers a [free CDN service](https://blog.cloudflare.com/cloudflares-free-cdn-and-you/). -Their certs are valid up to 15 years. Read through the tutorial on -[how to add a CloudFlare Certificate to your GitLab Pages website](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/). - -### Adding certificates to your project - -Regardless the CA you choose, the steps to add your certificate to -your Pages project are the same. - -#### What do you need - -1. A PEM certificate -1. An intermediate certificate -1. A public key - -![Pages project - adding certificates](img/add_certificate_to_pages.png) - -These fields are found under your **Project**'s **Settings** > **Pages** > **New Domain**. - -#### What's what? - -- A PEM certificate is the certificate generated by the CA, -which needs to be added to the field **Certificate (PEM)**. -- An [intermediate certificate](https://en.wikipedia.org/wiki/Intermediate_certificate_authority) (aka "root certificate") is -the part of the encryption keychain that identifies the CA. -Usually it's combined with the PEM certificate, but there are -some cases in which you need to add them manually. -[CloudFlare certs](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) -are one of these cases. -- A public key is an encrypted key which validates -your PEM against your domain. - -#### Now what? - -Now that you hopefully understand why you need all -of this, it's simple: - -- Your PEM certificate needs to be added to the first field -- If your certificate is missing its intermediate, copy -and paste the root certificate (usually available from your CA website) -and paste it in the [same field as your PEM certificate](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/), -just jumping a line between them. -- Copy your public key and paste it in the last field - ->**Note:** -**Do not** open certificates or encryption keys in -regular text editors. Always use code editors (such as -Sublime Text, Atom, Dreamweaver, Brackets, etc). - ||| |:--|--:| ||[**Part 2: Quick start guide - Setting up GitLab Pages →**](getting_started_part_two.md)| diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md index ef47abef3a0..dba5fb6c17a 100644 --- a/doc/user/project/pages/getting_started_part_three.md +++ b/doc/user/project/pages/getting_started_part_three.md @@ -1,383 +1,189 @@ # GitLab Pages from A to Z: Part 3 -- _[Part 1: Static Sites, Domains, DNS Records, and SSL/TLS Certificates](getting_started_part_one.md)_ -- _[Part 2: Quick Start Guide - Setting Up GitLab Pages](getting_started_part_two.md)_ -- **Part 3: Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages** - ---- - -## Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages - -[GitLab CI](https://about.gitlab.com/gitlab-ci/) serves -numerous purposes, to build, test, and deploy your app -from GitLab through -[Continuous Integration, Continuous Delivery, and Continuous Deployment](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) -methods. You will need it to build your website with GitLab Pages, -and deploy it to the Pages server. - -What this file actually does is telling the -[GitLab Runner](https://docs.gitlab.com/runner/) to run scripts -as you would do from the command line. The Runner acts as your -terminal. GitLab CI tells the Runner which commands to run. -Both are built-in in GitLab, and you don't need to set up -anything for them to work. - -Explaining [every detail of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html) -and GitLab Runner is out of the scope of this guide, but we'll -need to understand just a few things to be able to write our own -`.gitlab-ci.yml` or tweak an existing one. It's an -[Yaml](http://docs.ansible.com/ansible/YAMLSyntax.html) file, -with its own syntax. You can always check your CI syntax with -the [GitLab CI Lint Tool](https://gitlab.com/ci/lint). +- [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md) +- [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md) +- **Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates** +- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md) + +## Setting Up Custom Domains - DNS Records and SSL/TLS Certificates + +As described in the previous part of this series, setting up GitLab Pages with custom domains, and adding SSL/TLS certificates to them, are optional features of GitLab Pages. + +These steps assume you've already [set your site up](getting_started_part_two.md) and and it's served under the default Pages domain `namespace.gitlab.io`, or `namespace.gitlab.io/project-name`. + +### DNS Records + +A Domain Name System (DNS) web service routes visitors to websites +by translating domain names (such as `www.example.com`) into the +numeric IP addresses (such as `192.0.2.1`) that computers use to +connect to each other. + +A DNS record is created to point a (sub)domain to a certain location, +which can be an IP address or another domain. In case you want to use +GitLab Pages with your own (sub)domain, you need to access your domain's +registrar control panel to add a DNS record pointing it back to your +GitLab Pages site. + +Note that **how to** add DNS records depends on which server your domain +is hosted on. Every control panel has its own place to do it. If you are +not an admin of your domain, and don't have access to your registrar, +you'll need to ask for the technical support of your hosting service +to do it for you. + +To help you out, we've gathered some instructions on how to do that +for the most popular hosting services: + +- [Amazon](http://docs.aws.amazon.com/gettingstarted/latest/swh/getting-started-configure-route53.html) +- [Bluehost](https://my.bluehost.com/cgi/help/559) +- [CloudFlare](https://support.cloudflare.com/hc/en-us/articles/200169096-How-do-I-add-A-records-) +- [cPanel](https://documentation.cpanel.net/display/ALD/Edit+DNS+Zone) +- [DreamHost](https://help.dreamhost.com/hc/en-us/articles/215414867-How-do-I-add-custom-DNS-records-) +- [Go Daddy](https://www.godaddy.com/help/add-an-a-record-19238) +- [Hostgator](http://support.hostgator.com/articles/changing-dns-records) +- [Inmotion hosting](https://my.bluehost.com/cgi/help/559) +- [Media Temple](https://mediatemple.net/community/products/dv/204403794/how-can-i-change-the-dns-records-for-my-domain) +- [Microsoft](https://msdn.microsoft.com/en-us/library/bb727018.aspx) + +If your hosting service is not listed above, you can just try to +search the web for "how to add dns record on <my hosting service>". + +#### DNS A record + +In case you want to point a root domain (`example.com`) to your +GitLab Pages site, deployed to `namespace.gitlab.io`, you need to +log into your domain's admin control panel and add a DNS `A` record +pointing your domain to Pages' server IP address. For projects on +GitLab.com, this IP is `104.208.235.32`. For projects leaving in +other GitLab instances (CE or EE), please contact your sysadmin +asking for this information (which IP address is Pages server +running on your instance). **Practical Example:** -Let's consider you have a [Jekyll](https://jekyllrb.com/) site. -To build it locally, you would open your terminal, and run `jekyll build`. -Of course, before building it, you had to install Jekyll in your computer. -For that, you had to open your terminal and run `gem install jekyll`. -Right? GitLab CI + GitLab Runner do the same thing. But you need to -write in the `.gitlab-ci.yml` the script you want to run so -GitLab Runner will do it for you. It looks more complicated then it -is. What you need to tell the Runner: - -``` -$ gem install jekyll -$ jekyll build -``` - -### Script - -To transpose this script to Yaml, it would be like this: - -```yaml -script: - - gem install jekyll - - jekyll build -``` - -### Job - -So far so good. Now, each `script`, in GitLab is organized by -a `job`, which is a bunch of scripts and settings you want to -apply to that specific task. - -```yaml -job: - script: - - gem install jekyll - - jekyll build -``` - -For GitLab Pages, this `job` has a specific name, called `pages`, -which tells the Runner you want that task to deploy your website -with GitLab Pages: - -```yaml -pages: - script: - - gem install jekyll - - jekyll build -``` - -### The `public` directory - -We also need to tell Jekyll where do you want the website to build, -and GitLab Pages will only consider files in a directory called `public`. -To do that with Jekyll, we need to add a flag specifying the -[destination (`-d`)](https://jekyllrb.com/docs/usage/) of the -built website: `jekyll build -d public`. Of course, we need -to tell this to our Runner: - -```yaml -pages: - script: - - gem install jekyll - - jekyll build -d public -``` - -### Artifacts - -We also need to tell the Runner that this _job_ generates -_artifacts_, which is the site built by Jekyll. -Where are these artifacts stored? In the `public` directory: - -```yaml -pages: - script: - - gem install jekyll - - jekyll build -d public - artifacts: - paths: - - public -``` - -The script above would be enough to build your Jekyll -site with GitLab Pages. But, from Jekyll 3.4.0 on, its default -template originated by `jekyll new project` requires -[Bundler](http://bundler.io/) to install Jekyll dependencies -and the default theme. To adjust our script to meet these new -requirements, we only need to install and build Jekyll with Bundler: - -```yaml -pages: - script: - - bundle install - - bundle exec jekyll build -d public - artifacts: - paths: - - public -``` - -That's it! A `.gitlab-ci.yml` with the content above would deploy -your Jekyll 3.4.0 site with GitLab Pages. This is the minimum -configuration for our example. On the steps below, we'll refine -the script by adding extra options to our GitLab CI. - -### Image - -At this point, you probably ask yourself: "okay, but to install Jekyll -I need Ruby. Where is Ruby on that script?". The answer is simple: the -first thing GitLab Runner will look for in your `.gitlab-ci.yml` is a -[Docker](https://www.docker.com/) image specifying what do you need in -your container to run that script: - -```yaml -image: ruby:2.3 - -pages: - script: - - bundle install - - bundle exec jekyll build -d public - artifacts: - paths: - - public -``` - -In this case, you're telling the Runner to pull this image, which -contains Ruby 2.3 as part of its file system. When you don't specify -this image in your configuration, the Runner will use a default -image, which is Ruby 2.1. - -If your SSG needs [NodeJS](https://nodejs.org/) to build, you'll -need to specify which image you want to use, and this image should -contain NodeJS as part of its file system. E.g., for a -[Hexo](https://gitlab.com/pages/hexo) site, you can use `image: node:4.2.2`. +![DNS A record pointing to GitLab.com Pages server](img/dns_a_record_example.png) + +#### DNS CNAME record + +In case you want to point a subdomain (`hello-world.example.com`) +to your GitLab Pages site initially deployed to `namespace.gitlab.io`, +you need to log into your domain's admin control panel and add a DNS +`CNAME` record pointing your subdomain to your website URL +(`namespace.gitlab.io`) address. + +Notice that, despite it's a user or project website, the `CNAME` +should point to your Pages domain (`namespace.gitlab.io`), +without any `/project-name`. + +**Practical Example:** + +![DNS CNAME record pointing to GitLab.com project](img/dns_cname_record_example.png) + +#### TL;DR + +| From | DNS Record | To | +| ---- | ---------- | -- | +| domain.com | A | 104.208.235.32 | +| subdomain.domain.com | CNAME | namespace.gitlab.io | + +> **Notes**: +> +> - **Do not** use a CNAME record if you want to point your +`domain.com` to your GitLab Pages site. Use an `A` record instead. +> - **Do not** add any special chars after the default Pages +domain. E.g., **do not** point your `subdomain.domain.com` to +`namespace.gitlab.io.` or `namespace.gitlab.io/`. + +### SSL/TLS Certificates + +Every GitLab Pages project on GitLab.com will be available under +HTTPS for the default Pages domain (`*.gitlab.io`). Once you set +up your Pages project with your custom (sub)domain, if you want +it secured by HTTPS, you will have to issue a certificate for that +(sub)domain and install it on your project. + +>**Note:** +Certificates are NOT required to add to your custom +(sub)domain on your GitLab Pages project, though they are +highly recommendable. + +The importance of having any website securely served under HTTPS +is explained on the introductory section of the blog post +[Secure GitLab Pages with StartSSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/#https-a-quick-overview). + +The reason why certificates are so important is that they encrypt +the connection between the **client** (you, me, your visitors) +and the **server** (where you site lives), through a keychain of +authentications and validations. + +### Issuing Certificates + +GitLab Pages accepts [PEM](https://support.quovadisglobal.com/kb/a37/what-is-pem-format.aspx) certificates issued by +[Certificate Authorities (CA)](https://en.wikipedia.org/wiki/Certificate_authority) +and self-signed certificates. Of course, +[you'd rather issue a certificate than generate a self-signed](https://en.wikipedia.org/wiki/Self-signed_certificate), +for security reasons and for having browsers trusting your +site's certificate. + +There are several different kinds of certificates, each one +with certain security level. A static personal website will +not require the same security level as an online banking web app, +for instance. There are a couple Certificate Authorities that +offer free certificates, aiming to make the internet more secure +to everyone. The most popular is [Let's Encrypt](https://letsencrypt.org/), +which issues certificates trusted by most of browsers, it's open +source, and free to use. Please read through this tutorial to +understand [how to secure your GitLab Pages website with Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/). + +With the same popularity, there are [certificates issued by CloudFlare](https://www.cloudflare.com/ssl/), +which also offers a [free CDN service](https://blog.cloudflare.com/cloudflares-free-cdn-and-you/). +Their certs are valid up to 15 years. Read through the tutorial on +[how to add a CloudFlare Certificate to your GitLab Pages website](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/). + +### Adding certificates to your project + +Regardless the CA you choose, the steps to add your certificate to +your Pages project are the same. + +#### What do you need + +1. A PEM certificate +1. An intermediate certificate +1. A public key + +![Pages project - adding certificates](img/add_certificate_to_pages.png) + +These fields are found under your **Project**'s **Settings** > **Pages** > **New Domain**. + +#### What's what? + +- A PEM certificate is the certificate generated by the CA, +which needs to be added to the field **Certificate (PEM)**. +- An [intermediate certificate](https://en.wikipedia.org/wiki/Intermediate_certificate_authority) (aka "root certificate") is +the part of the encryption keychain that identifies the CA. +Usually it's combined with the PEM certificate, but there are +some cases in which you need to add them manually. +[CloudFlare certs](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) +are one of these cases. +- A public key is an encrypted key which validates +your PEM against your domain. + +#### Now what? + +Now that you hopefully understand why you need all +of this, it's simple: + +- Your PEM certificate needs to be added to the first field +- If your certificate is missing its intermediate, copy +and paste the root certificate (usually available from your CA website) +and paste it in the [same field as your PEM certificate](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/), +just jumping a line between them. +- Copy your public key and paste it in the last field >**Note:** -We're not trying to explain what a Docker image is, -we just need to introduce the concept with a minimum viable -explanation. To know more about Docker images, please visit -their website or take a look at a -[summarized explanation](http://paislee.io/how-to-automate-docker-deployments/) here. - -Let's go a little further. - -### Branching - -If you use GitLab as a version control platform, you will have your -branching strategy to work on your project. Meaning, you will have -other branches in your project, but you'll want only pushes to the -default branch (usually `master`) to be deployed to your website. -To do that, we need to add another line to our CI, telling the Runner -to only perform that _job_ called `pages` on the `master` branch `only`: - -```yaml -image: ruby:2.3 - -pages: - script: - - bundle install - - bundle exec jekyll build -d public - artifacts: - paths: - - public - only: - - master -``` - -### Stages - -Another interesting concept to keep in mind are build stages. -Your web app can pass through a lot of tests and other tasks -until it's deployed to staging or production environments. -There are three default stages on GitLab CI: build, test, -and deploy. To specify which stage your _job_ is running, -simply add another line to your CI: - -```yaml -image: ruby:2.3 - -pages: - stage: deploy - script: - - bundle install - - bundle exec jekyll build -d public - artifacts: - paths: - - public - only: - - master -``` - -You might ask yourself: "why should I bother with stages -at all?" Well, let's say you want to be able to test your -script and check the built site before deploying your site -to production. You want to run the test exactly as your -script will do when you push to `master`. It's simple, -let's add another task (_job_) to our CI, telling it to -test every push to other branches, `except` the `master` branch: - -```yaml -image: ruby:2.3 - -pages: - stage: deploy - script: - - bundle install - - bundle exec jekyll build -d public - artifacts: - paths: - - public - only: - - master - -test: - stage: test - script: - - bundle install - - bundle exec jekyll build -d test - artifacts: - paths: - - test - except: - - master -``` - -The `test` job is running on the stage `test`, Jekyll -will build the site in a directory called `test`, and -this job will affect all the branches except `master`. - -The best benefit of applying _stages_ to different -_jobs_ is that every job in the same stage builds in -parallel. So, if your web app needs more than one test -before being deployed, you can run all your test at the -same time, it's not necessary to wait one test to finish -to run the other. Of course, this is just a brief -introduction of GitLab CI and GitLab Runner, which are -tools much more powerful than that. This is what you -need to be able to create and tweak your builds for -your GitLab Pages site. - -### Before Script - -To avoid running the same script multiple times across -your _jobs_, you can add the parameter `before_script`, -in which you specify which commands you want to run for -every single _job_. In our example, notice that we run -`bundle install` for both jobs, `pages` and `test`. -We don't need to repeat it: - -```yaml -image: ruby:2.3 - -before_script: - - bundle install - -pages: - stage: deploy - script: - - bundle exec jekyll build -d public - artifacts: - paths: - - public - only: - - master - -test: - stage: test - script: - - bundle exec jekyll build -d test - artifacts: - paths: - - test - except: - - master -``` - -### Caching Dependencies - -If you want to cache the installation files for your -projects dependencies, for building faster, you can -use the parameter `cache`. For this example, we'll -cache Jekyll dependencies in a `vendor` directory -when we run `bundle install`: - -```yaml -image: ruby:2.3 - -cache: - paths: - - vendor/ - -before_script: - - bundle install --path vendor - -pages: - stage: deploy - script: - - bundle exec jekyll build -d public - artifacts: - paths: - - public - only: - - master - -test: - stage: test - script: - - bundle exec jekyll build -d test - artifacts: - paths: - - test - except: - - master -``` - -For this specific case, we need to exclude `/vendor` -from Jekyll `_config.yml` file, otherwise Jekyll will -understand it as a regular directory to build -together with the site: - -```yml -exclude: - - vendor -``` - -There we go! Now our GitLab CI not only builds our website, -but also **continuously test** pushes to feature-branches, -**caches** dependencies installed with Bundler, and -**continuously deploy** every push to the `master` branch. - -## Advanced GitLab CI for GitLab Pages - -What you can do with GitLab CI is pretty much up to your -creativity. Once you get used to it, you start creating -awesome scripts that automate most of tasks you'd do -manually in the past. Read through the -[documentation of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html) -to understand how to go even further on your scripts. - -- On this blog post, understand the concept of -[using GitLab CI `environments` to deploy your -web app to staging and production](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/). -- On this post, learn [how to run jobs sequentially, -in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/) -- On this blog post, we go through the process of -[pulling specific directories from different projects](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) -to deploy this website you're looking at, docs.gitlab.com. -- On this blog post, we teach you [how to use GitLab Pages to produce a code coverage report](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/). +**Do not** open certificates or encryption keys in +regular text editors. Always use code editors (such as +Sublime Text, Atom, Dreamweaver, Brackets, etc). ||| |:--|--:| -|[**← Part 2: Quick start guide - Setting up GitLab Pages**](getting_started_part_two.md)|| +|[**← Part 2: Quick start guide - Setting up GitLab Pages**](getting_started_part_two.md)|[**Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages →**](getting_started_part_four.md)| diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md index 07dd24122c4..d0e2c467fee 100644 --- a/doc/user/project/pages/getting_started_part_two.md +++ b/doc/user/project/pages/getting_started_part_two.md @@ -1,14 +1,9 @@ # GitLab Pages from A to Z: Part 2 -> Type: user guide -> -> Level: beginner - -- _[Part 1: Static Sites, Domains, DNS Records, and SSL/TLS Certificates](getting_started_part_one.md)_ -- **Part 2: Quick Start Guide - Setting Up GitLab Pages** -- _[Part 3: Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_three.md)_ - ----- +- [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md) +- **Part 2: Quick start guide - Setting up GitLab Pages** +- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md) +- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md) ## Setting up GitLab Pages @@ -30,6 +25,8 @@ Optional Features: 1. **Optional**: an SSL/TLS certificate so your custom domain is accessible under HTTPS. +The optional settings, custom domain, DNS records, and SSL/TLS certificates, are described in [Part 3](getting_started_part_three.md)). + ## Project Your GitLab Pages project is a regular project created the @@ -106,7 +103,7 @@ where you'll find its default URL. > - GitLab Pages [supports any SSG](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/), but, if you don't find yours among the templates, you'll need to configure your own `.gitlab-ci.yml`. Do do that, please -read through the article [Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_three.md). New SSGs are very welcome among +read through the article [Creating and Tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md). New SSGs are very welcome among the [example projects](https://gitlab.com/pages). If you set up a new one, please [contribute](https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md) @@ -147,6 +144,11 @@ example we've just mentioned, you'd have to change Jekyll's `_config.yml` to: baseurl: "" ``` +### Custom Domains + +GitLab Pages supports custom domains and subdomains, served under HTTPS or HTTPS. +Please check the [next part](getting_started_part_three.md) of this series for an overview. + ||| |:--|--:| -|[**← Part 1: Static sites, domains, DNS records, and SSL/TLS certificates**](getting_started_part_one.md)|[**Part 3: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages →**](getting_started_part_three.md)| +|[**← Part 1: Static sites, domains, DNS records, and SSL/TLS certificates**](getting_started_part_one.md)|[**Setting Up Custom Domains - DNS Records and SSL/TLS Certificates →**](getting_started_part_three.md)| diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md index dbb9d9ad9c4..1366756d593 100644 --- a/doc/user/project/pages/index.md +++ b/doc/user/project/pages/index.md @@ -1,49 +1,48 @@ -# All you need to know about GitLab Pages +# GitLab Pages documentation With GitLab Pages you can create static websites for your GitLab projects, groups, or user accounts. You can use any static website generator: Jekyll, Middleman, Hexo, Hugo, Pelican, you name it! Connect as many customs domains as you like and bring your own TLS certificate to secure them. -Here's some info we have gathered to get you started. +Here's some info we've gathered to get you started. ## General info - [Product webpage](https://pages.gitlab.io) -- [We're bringing GitLab Pages to CE](https://about.gitlab.com/2016/12/24/were-bringing-gitlab-pages-to-community-edition/) +- ["We're bringing GitLab Pages to CE" blog post](https://about.gitlab.com/2016/12/24/were-bringing-gitlab-pages-to-community-edition/) - [Pages group - templates](https://gitlab.com/pages) +- [General user documentation](introduction.md) +- [Admin documentation - Set GitLab Pages on your own GitLab instance](../../../administration/pages/index.md) ## Getting started -- GitLab Pages from A to Z - - [Part 1: Static sites, domains, DNS records, and SSL/TLS certificates](getting_started_part_one.md) +- **GitLab Pages from A to Z** + - [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md) - [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md) - - [Part 3: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_three.md) -- [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) a comprehensive step-by-step guide -- Secure GitLab Pages custom domain with SSL/TLS certificates - - [Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) - - [CloudFlare](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) - - [StartSSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/) -- Static Site Generators - Blog posts series + - [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md) + - [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md) +- **Static Site Generators - Blog posts series** - [SSGs part 1: Static vs dynamic websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) - [SSGs part 2: Modern static site generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) - [SSGs part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) -- [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/) +- **Secure GitLab Pages custom domain with SSL/TLS certificates** + - [Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) + - [CloudFlare](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) + - [StartSSL](https://about.gitlab.com/2016/06/24/secure-gitlab-pages-with-startssl/) +- **General** + - [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) a comprehensive step-by-step guide + - [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/) ## Video tutorials - [How to publish a website with GitLab Pages on GitLab.com: from a forked project](https://youtu.be/TWqh9MtT4Bg) -- [How to Enable GitLab Pages for GitLab CE and EE](https://youtu.be/dD8c7WNcc6s) +- [How to Enable GitLab Pages for GitLab CE and EE (for Admins only)](https://youtu.be/dD8c7WNcc6s) ## Advanced use -- Blog Posts: +- **Blog Posts** - [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/) - [GitLab CI: Deployment & environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) - [Building a new GitLab docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) - [Publish code coverage reports with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/) - -## Specific documentation - -- [User docs](introduction.md) -- [Admin docs](../../../administration/pages/index.md) diff --git a/doc/user/project/slash_commands.md b/doc/user/project/slash_commands.md index ad5d51d34f2..45176fde9db 100644 --- a/doc/user/project/slash_commands.md +++ b/doc/user/project/slash_commands.md @@ -35,3 +35,4 @@ do. | <code>/spend <1h 30m | -1h 5m></code> | Add or subtract spent time | | `/remove_time_spent` | Remove time spent | | `/target_branch <Branch Name>` | Set target branch for current merge request | +| `/award :emoji:` | Toggle award for :emoji: | diff --git a/features/project/issues/award_emoji.feature b/features/project/issues/award_emoji.feature index f0fd414a9f9..1d7adfdd2c2 100644 --- a/features/project/issues/award_emoji.feature +++ b/features/project/issues/award_emoji.feature @@ -42,4 +42,4 @@ Feature: Award Emoji @javascript Scenario: I add award emoji using regular comment Given I leave comment with a single emoji - Then I have award added + Then I have new comment with emoji added diff --git a/features/steps/project/issues/award_emoji.rb b/features/steps/project/issues/award_emoji.rb index cbe5738e7e4..dd7a58b454a 100644 --- a/features/steps/project/issues/award_emoji.rb +++ b/features/steps/project/issues/award_emoji.rb @@ -44,6 +44,10 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps end end + step 'I have new comment with emoji added' do + expect(page).to have_selector ".emoji[title=':smile:']" + end + step 'I have award added' do page.within '.awards' do expect(page).to have_selector '.js-emoji-btn' diff --git a/spec/features/issues/award_emoji_spec.rb b/spec/features/issues/award_emoji_spec.rb index 73e43316dc7..3ab3d2d4229 100644 --- a/spec/features/issues/award_emoji_spec.rb +++ b/spec/features/issues/award_emoji_spec.rb @@ -67,6 +67,18 @@ describe 'Awards Emoji', feature: true do expect(page).not_to have_selector(emoji_counter) end end + + context 'execute /award slash command' do + it 'toggles the emoji award on noteable', js: true do + execute_slash_command('/award :100:') + + expect(find(noteable_award_counter)).to have_text("1") + + execute_slash_command('/award :100:') + + expect(page).not_to have_selector(noteable_award_counter) + end + end end end @@ -80,6 +92,15 @@ describe 'Awards Emoji', feature: true do end end + def execute_slash_command(cmd) + within('.js-main-target-form') do + fill_in 'note[note]', with: cmd + click_button 'Comment' + end + + wait_for_ajax + end + def thumbsup_emoji page.all(emoji_counter).first end @@ -92,6 +113,10 @@ describe 'Awards Emoji', feature: true do 'span.js-counter' end + def noteable_award_counter + ".awards .active" + end + def toggle_smiley_emoji(status) within('.note') do find('.note-emoji-button').click diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 9d3c821b692..347f8f6fa3b 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -225,11 +225,11 @@ describe API::Notes, api: true do context 'when the user is posting an award emoji on an issue created by someone else' do let(:issue2) { create(:issue, project: project) } - it 'returns an award emoji' do + it 'creates a new issue note' do post api("/projects/#{project.id}/issues/#{issue2.id}/notes", user), body: ':+1:' expect(response).to have_http_status(201) - expect(json_response['awardable_id']).to eq issue2.id + expect(json_response['body']).to eq(':+1:') end end diff --git a/spec/requests/api/v3/notes_spec.rb b/spec/requests/api/v3/notes_spec.rb index b8f0260c6a2..ddef2d5eb04 100644 --- a/spec/requests/api/v3/notes_spec.rb +++ b/spec/requests/api/v3/notes_spec.rb @@ -228,11 +228,11 @@ describe API::V3::Notes, api: true do context 'when the user is posting an award emoji on an issue created by someone else' do let(:issue2) { create(:issue, project: project) } - it 'returns an award emoji' do + it 'creates a new issue note' do post v3_api("/projects/#{project.id}/issues/#{issue2.id}/notes", user), body: ':+1:' expect(response).to have_http_status(201) - expect(json_response['awardable_id']).to eq issue2.id + expect(json_response['body']).to eq(':+1:') end end diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index 9c92a5080c6..152c6d20daa 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -102,47 +102,19 @@ describe Notes::CreateService, services: true do expect(subject.note).to eq(params[:note]) end end - end - - describe "award emoji" do - before do - project.team << [user, :master] - end - - it "creates an award emoji" do - opts = { - note: ':smile: ', - noteable_type: 'Issue', - noteable_id: issue.id - } - note = described_class.new(project, user, opts).execute - - expect(note).to be_valid - expect(note.name).to eq('smile') - end - it "creates regular note if emoji name is invalid" do - opts = { - note: ':smile: moretext:', - noteable_type: 'Issue', - noteable_id: issue.id - } - note = described_class.new(project, user, opts).execute - - expect(note).to be_valid - expect(note.note).to eq(opts[:note]) - end - - it "normalizes the emoji name" do - opts = { - note: ':+1:', - noteable_type: 'Issue', - noteable_id: issue.id - } - - expect_any_instance_of(TodoService).to receive(:new_award_emoji).with(issue, user) + describe 'note with emoji only' do + it 'creates regular note' do + opts = { + note: ':smile: ', + noteable_type: 'Issue', + noteable_id: issue.id + } + note = described_class.new(project, user, opts).execute - described_class.new(project, user, opts).execute + expect(note).to be_valid + expect(note.note).to eq(':smile:') + end end end end diff --git a/spec/services/slash_commands/interpret_service_spec.rb b/spec/services/slash_commands/interpret_service_spec.rb index 0b0925983eb..52e8678cb9d 100644 --- a/spec/services/slash_commands/interpret_service_spec.rb +++ b/spec/services/slash_commands/interpret_service_spec.rb @@ -267,6 +267,14 @@ describe SlashCommands::InterpretService, services: true do end end + shared_examples 'award command' do + it 'toggle award 100 emoji if content containts /award :100:' do + _, updates = service.execute(content, issuable) + + expect(updates).to eq(emoji_award: "100") + end + end + it_behaves_like 'reopen command' do let(:content) { '/reopen' } let(:issuable) { issue } @@ -654,6 +662,37 @@ describe SlashCommands::InterpretService, services: true do end end + context '/award command' do + it_behaves_like 'award command' do + let(:content) { '/award :100:' } + let(:issuable) { issue } + end + + it_behaves_like 'award command' do + let(:content) { '/award :100:' } + let(:issuable) { merge_request } + end + + context 'ignores command with no argument' do + it_behaves_like 'empty command' do + let(:content) { '/award' } + let(:issuable) { issue } + end + end + + context 'ignores non-existing / invalid emojis' do + it_behaves_like 'empty command' do + let(:content) { '/award noop' } + let(:issuable) { issue } + end + + it_behaves_like 'empty command' do + let(:content) { '/award :lorem_ipsum:' } + let(:issuable) { issue } + end + end + end + context '/target_branch command' do let(:non_empty_project) { create(:project) } let(:another_merge_request) { create(:merge_request, author: developer, source_project: non_empty_project) } |