summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml15
-rw-r--r--app/controllers/projects/pipelines_controller.rb4
-rw-r--r--app/models/repository.rb12
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/imports/show.html.haml2
-rw-r--r--changelogs/unreleased/feature-api_owned_resource.yml4
-rw-r--r--changelogs/unreleased/fix-cache-for-commit-status.yml4
-rw-r--r--changelogs/unreleased/fix-error-when-invalid-branch-for-new-pipeline-used.yml4
-rw-r--r--changelogs/unreleased/forking-in-progress-title.yml4
-rw-r--r--doc/api/groups.md9
-rw-r--r--doc/university/README.md3
-rwxr-xr-xdoc/university/training/gitlab_flow.md53
-rw-r--r--doc/university/training/gitlab_flow/feature_branches.pngbin0 -> 20600 bytes
-rw-r--r--doc/university/training/gitlab_flow/production_branch.pngbin0 -> 21716 bytes
-rw-r--r--doc/university/training/gitlab_flow/release_branches.pngbin0 -> 44173 bytes
-rwxr-xr-xdoc/university/training/index.md6
-rw-r--r--doc/university/training/logo.pngbin0 -> 33117 bytes
-rwxr-xr-xdoc/university/training/topics/additional_resources.md8
-rwxr-xr-xdoc/university/training/topics/agile_git.md33
-rwxr-xr-xdoc/university/training/topics/bisect.md81
-rwxr-xr-xdoc/university/training/topics/cherry_picking.md39
-rwxr-xr-xdoc/university/training/topics/env_setup.md60
-rwxr-xr-xdoc/university/training/topics/explore_gitlab.md10
-rwxr-xr-xdoc/university/training/topics/feature_branching.md32
-rwxr-xr-xdoc/university/training/topics/getting_started.md95
-rwxr-xr-xdoc/university/training/topics/git_add.md33
-rwxr-xr-xdoc/university/training/topics/git_intro.md24
-rwxr-xr-xdoc/university/training/topics/git_log.md57
-rwxr-xr-xdoc/university/training/topics/gitlab_flow.md53
-rwxr-xr-xdoc/university/training/topics/merge_conflicts.md70
-rwxr-xr-xdoc/university/training/topics/merge_requests.md43
-rwxr-xr-xdoc/university/training/topics/rollback_commits.md81
-rwxr-xr-xdoc/university/training/topics/stash.md86
-rwxr-xr-xdoc/university/training/topics/subtree.md55
-rwxr-xr-xdoc/university/training/topics/tags.md38
-rwxr-xr-xdoc/university/training/topics/unstage.md31
-rwxr-xr-xdoc/university/training/user_training.md392
-rw-r--r--lib/api/groups.rb10
-rw-r--r--lib/api/milestones.rb111
-rw-r--r--lib/api/runners.rb117
-rw-r--r--lib/api/session.rb19
-rw-r--r--lib/gitlab/ee_compat_check.rb152
-rw-r--r--lib/tasks/gitlab/dev.rake26
-rw-r--r--spec/models/repository_spec.rb49
-rw-r--r--spec/requests/api/groups_spec.rb18
-rw-r--r--spec/requests/api/milestones_spec.rb9
-rw-r--r--spec/requests/api/projects_spec.rb24
-rw-r--r--spec/requests/api/runners_spec.rb4
-rw-r--r--spec/requests/api/session_spec.rb16
49 files changed, 1780 insertions, 218 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 195783454f9..34348247e91 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -213,11 +213,24 @@ rake downtime_check: *exec
rake ee_compat_check:
<<: *exec
only:
- - branches
+ - branches@gitlab-org/gitlab-ce
+ - branches@gitlab/gitlabhq
except:
- master
- tags
+ - /^[\d-]+-stable(-ee)?$/
allow_failure: yes
+ cache:
+ key: "ruby231-ee_compat_check_repo"
+ paths:
+ - ee_compat_check/repo/
+ - vendor/ruby
+ artifacts:
+ name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}_${CI_BUILD_REF}"
+ when: on_failure
+ expire_in: 10d
+ paths:
+ - ee_compat_check/patches/*.patch
rake db:migrate:reset:
stage: test
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 371cc3787fb..533af80aee0 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -18,7 +18,9 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def create
- @pipeline = Ci::CreatePipelineService.new(project, current_user, create_params).execute(ignore_skip_ci: true, save_on_errors: false)
+ @pipeline = Ci::CreatePipelineService
+ .new(project, current_user, create_params)
+ .execute(ignore_skip_ci: true, save_on_errors: false)
unless @pipeline.persisted?
render 'new'
return
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 7d06ce1e85b..fe991904601 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -84,15 +84,17 @@ class Repository
def commit(ref = 'HEAD')
return nil unless exists?
+
commit =
if ref.is_a?(Gitlab::Git::Commit)
ref
else
Gitlab::Git::Commit.find(raw_repository, ref)
end
+
commit = ::Commit.new(commit, @project) if commit
commit
- rescue Rugged::OdbError
+ rescue Rugged::OdbError, Rugged::TreeError
nil
end
@@ -232,6 +234,8 @@ class Repository
def ref_exists?(ref)
rugged.references.exist?(ref)
+ rescue Rugged::ReferenceError
+ false
end
def update_ref!(name, newrev, oldrev)
@@ -270,11 +274,7 @@ class Repository
end
def kept_around?(sha)
- begin
- ref_exists?(keep_around_ref_name(sha))
- rescue Rugged::ReferenceError
- false
- end
+ ref_exists?(keep_around_ref_name(sha))
end
def tag_names
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 9f80a974d64..34855c54176 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -6,7 +6,7 @@
- note_count = notes.user.count
- cache_key = [project.path_with_namespace, commit.id, current_application_settings, note_count]
-- cache_key.push(commit.status) if commit.status
+- cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do
%li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" }
diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml
index 4d8ee562e6a..c52b3860636 100644
--- a/app/views/projects/imports/show.html.haml
+++ b/app/views/projects/imports/show.html.haml
@@ -1,4 +1,4 @@
-- page_title "Import in progress"
+- page_title @project.forked? ? "Forking in progress" : "Import in progress"
.save-project-loader
.center
%h2
diff --git a/changelogs/unreleased/feature-api_owned_resource.yml b/changelogs/unreleased/feature-api_owned_resource.yml
new file mode 100644
index 00000000000..9c270e4ecf4
--- /dev/null
+++ b/changelogs/unreleased/feature-api_owned_resource.yml
@@ -0,0 +1,4 @@
+---
+title: Add api endpoint `/groups/owned`
+merge_request: 7103
+author: Borja Aparicio
diff --git a/changelogs/unreleased/fix-cache-for-commit-status.yml b/changelogs/unreleased/fix-cache-for-commit-status.yml
new file mode 100644
index 00000000000..eb4e96e75ae
--- /dev/null
+++ b/changelogs/unreleased/fix-cache-for-commit-status.yml
@@ -0,0 +1,4 @@
+---
+title: Fix cache for commit status in commits list to respect branches
+merge_request: 7372
+author:
diff --git a/changelogs/unreleased/fix-error-when-invalid-branch-for-new-pipeline-used.yml b/changelogs/unreleased/fix-error-when-invalid-branch-for-new-pipeline-used.yml
new file mode 100644
index 00000000000..ad6aa214f0f
--- /dev/null
+++ b/changelogs/unreleased/fix-error-when-invalid-branch-for-new-pipeline-used.yml
@@ -0,0 +1,4 @@
+---
+title: Fix error when using invalid branch name when creating a new pipeline
+merge_request: 7324
+author:
diff --git a/changelogs/unreleased/forking-in-progress-title.yml b/changelogs/unreleased/forking-in-progress-title.yml
new file mode 100644
index 00000000000..4b9684844b3
--- /dev/null
+++ b/changelogs/unreleased/forking-in-progress-title.yml
@@ -0,0 +1,4 @@
+---
+title: Use 'Forking in progress' title when appropriate
+merge_request: 7394
+author: Philip Karpiak
diff --git a/doc/api/groups.md b/doc/api/groups.md
index b56d74d25e0..45a3118f27a 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -26,6 +26,15 @@ GET /groups
You can search for groups by name or path, see below.
+=======
+## List owned groups
+
+Get a list of groups which are owned by the authenticated user.
+
+```
+GET /groups/owned
+```
+
## List a group's projects
Get a list of projects in this group.
diff --git a/doc/university/README.md b/doc/university/README.md
index 49714e4fb59..4569bc72797 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -212,5 +212,8 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Support Path](support/README.md)
1. [Sales Path (redirect to sales handbook)](https://about.gitlab.com/handbook/sales-onboarding/)
+1. [User Training](training/user_training.md)
+1. [GitLab Flow Training](training/gitlab_flow.md)
+1. [Training Topics](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/university/training/topics/)
1. [GitLab architecture for noobs](https://dev.gitlab.org/gitlab/gitlabhq/blob/master/doc/development/architecture.md)
1. [Client Assessment of GitLab versus GitHub](https://docs.google.com/a/gitlab.com/spreadsheets/d/18cRF9Y5I6I7Z_ab6qhBEW55YpEMyU4PitZYjomVHM-M/edit?usp=sharing)
diff --git a/doc/university/training/gitlab_flow.md b/doc/university/training/gitlab_flow.md
new file mode 100755
index 00000000000..a7db1f2e069
--- /dev/null
+++ b/doc/university/training/gitlab_flow.md
@@ -0,0 +1,53 @@
+# GitLab Flow
+
+- A simplified branching strategy
+- All features and fixes first go to master
+- Allows for 'production' or 'stable' branches
+- Bug fixes/hot fix patches are cherry-picked from master
+
+---
+
+# Feature branches
+
+- Create a feature/bugfix branch to do all work
+- Use merge requests to merge to master
+
+![inline](gitlab_flow/feature_branches.png)
+
+---
+
+# Production branch
+
+- One, long-running production release branch
+ as opposed to individual stable branches
+- Consider creating a tag for each version that gets deployed
+
+---
+
+# Production branch
+
+![inline](gitlab_flow/production_branch.png)
+
+---
+
+# Release branch
+
+- Useful if you release software to customers
+- When preparing a new release, create stable branch
+ from master
+- Consider creating a tag for each version
+- Cherry-pick critical bug fixes to stable branch for patch release
+- Never commit bug fixes directly to stable branch
+
+---
+
+# Release branch
+
+![inline](gitlab_flow/release_branches.png)
+
+---
+
+# More details
+
+Blog post on 'GitLab Flow' at
+[http://doc.gitlab.com/ee/workflow/gitlab_flow.html](http://doc.gitlab.com/ee/workflow/gitlab_flow.html)
diff --git a/doc/university/training/gitlab_flow/feature_branches.png b/doc/university/training/gitlab_flow/feature_branches.png
new file mode 100644
index 00000000000..88addb623ee
--- /dev/null
+++ b/doc/university/training/gitlab_flow/feature_branches.png
Binary files differ
diff --git a/doc/university/training/gitlab_flow/production_branch.png b/doc/university/training/gitlab_flow/production_branch.png
new file mode 100644
index 00000000000..33fb26dd621
--- /dev/null
+++ b/doc/university/training/gitlab_flow/production_branch.png
Binary files differ
diff --git a/doc/university/training/gitlab_flow/release_branches.png b/doc/university/training/gitlab_flow/release_branches.png
new file mode 100644
index 00000000000..da7ae53413a
--- /dev/null
+++ b/doc/university/training/gitlab_flow/release_branches.png
Binary files differ
diff --git a/doc/university/training/index.md b/doc/university/training/index.md
new file mode 100755
index 00000000000..03179ff5a77
--- /dev/null
+++ b/doc/university/training/index.md
@@ -0,0 +1,6 @@
+# GitLab Training Material
+
+All GitLab training material is stored in markdown format. Slides are
+generated using [Deskset](http://www.decksetapp.com/).
+
+All training material is open to public contribution.
diff --git a/doc/university/training/logo.png b/doc/university/training/logo.png
new file mode 100644
index 00000000000..cc831790405
--- /dev/null
+++ b/doc/university/training/logo.png
Binary files differ
diff --git a/doc/university/training/topics/additional_resources.md b/doc/university/training/topics/additional_resources.md
new file mode 100755
index 00000000000..1ee615432aa
--- /dev/null
+++ b/doc/university/training/topics/additional_resources.md
@@ -0,0 +1,8 @@
+## Additional Resources
+
+1. GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/)
+2. GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis)
+3. Pro git book [http://git-scm.com/book](http://git-scm.com/book)
+4. Platzi Course [https://courses.platzi.com/courses/git-gitlab/](https://courses.platzi.com/courses/git-gitlab/)
+5. Code School tutorial [http://try.github.io/](http://try.github.io/)
+6. Contact Us - [subscribers@gitlab.com](subscribers@gitlab.com)
diff --git a/doc/university/training/topics/agile_git.md b/doc/university/training/topics/agile_git.md
new file mode 100755
index 00000000000..e6e4fea9b51
--- /dev/null
+++ b/doc/university/training/topics/agile_git.md
@@ -0,0 +1,33 @@
+# Agile and Git
+
+----------
+
+## Agile
+
+Lean software development methods focused on collaboration and interaction
+with fast and smaller deployment cycles.
+
+----------
+
+## Where Git comes in
+
+Git is an excellent tool for an Agile team considering that it allows
+decentralized and simultaneous development.
+
+----------
+
+### Branching And Workflows
+
+Branching in an Agile environment usually happens around user stories with one
+or more developers working on it.
+
+If more than one developer then another branch for each developer is also used
+with his/her initials, and US id.
+
+After its tested merge into master and remove the branch.
+
+----------
+
+## What about GitLab
+Tools like GitLab enhance collaboration by adding dialog around code mainly
+through issues and merge requests.
diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md
new file mode 100755
index 00000000000..a60c4365e0c
--- /dev/null
+++ b/doc/university/training/topics/bisect.md
@@ -0,0 +1,81 @@
+# Bisect
+
+----------
+
+## Bisect
+
+- Find a commit that introduced a bug
+- Works through a process of elimination
+- Specify a known good and bad revision to begin
+
+----------
+
+## Bisect
+
+1. Start the bisect process
+2. Enter the bad revision (usually latest commit)
+3. Enter a known good revision (commit/branch)
+4. Run code to see if bug still exists
+5. Tell bisect the result
+6. Repeat the previous 2 items until you find the offending commit
+
+----------
+
+## Setup
+
+```
+ mkdir bisect-ex
+ cd bisect-ex
+ touch index.html
+ git add -A
+ git commit -m "starting out"
+ vi index.html
+ # Add all good
+ git add -A
+ git commit -m "second commit"
+ vi index.html
+ # Add all good 2
+ git add -A
+ git commit -m "third commit"
+ vi index.html
+```
+
+----------
+
+```
+ # Add all good 3
+ git add -A
+ git commit -m "fourth commit"
+ vi index.html
+ # This looks bad
+ git add -A
+ git commit -m "fifth commit"
+ vi index.html
+ # Really bad
+ git add -A
+ git commit -m "sixth commit"
+ vi index.html
+ # again just bad
+ git add -A
+ git commit -m "seventh commit"
+```
+
+----------
+
+## Commands
+
+```
+ git bisect start
+ # Test your code
+ git bisect bad
+ git bisect next
+ # Say yes to the warning
+ # Test
+ git bisect good
+ # Test
+ git bisect bad
+ # Test
+ git bisect good
+ # done
+ git bisect reset
+```
diff --git a/doc/university/training/topics/cherry_picking.md b/doc/university/training/topics/cherry_picking.md
new file mode 100755
index 00000000000..af7a70a2818
--- /dev/null
+++ b/doc/university/training/topics/cherry_picking.md
@@ -0,0 +1,39 @@
+# Cherry Pick
+
+----------
+
+## Cherry Pick
+
+- Given an existing commit on one branch, apply the change to another branch
+- Useful for backporting bug fixes to previous release branches
+- Make the commit on the master branch and pick in to stable
+
+----------
+
+## Cherry Pick
+
+1. Check out a new 'stable' branch from 'master'
+1. Change back to 'master'
+1. Edit '`cherry_pick.rb`' and commit the changes.
+1. Check commit log to get the commit SHA
+1. Check out the 'stable' branch
+1. Cherry pick the commit using the SHA obtained earlier
+
+----------
+
+## Commands
+
+```bash
+git checkout master
+git checkout -b stable
+git checkout master
+
+# Edit `cherry_pick.rb`
+git add cherry_pick.rb
+git commit -m 'Fix bugs in cherry_pick.rb'
+git log
+# Copy commit SHA
+git checkout stable
+
+git cherry-pick <commit SHA>
+```
diff --git a/doc/university/training/topics/env_setup.md b/doc/university/training/topics/env_setup.md
new file mode 100755
index 00000000000..8149379b36f
--- /dev/null
+++ b/doc/university/training/topics/env_setup.md
@@ -0,0 +1,60 @@
+# Configure your environment
+
+----------
+## Install
+
+- **Windows**
+ - Install 'Git for Windows' from https://git-for-windows.github.io
+
+- **Mac**
+ - Type '`git`' in the Terminal application.
+ - If it's not installed, it will prompt you to install it.
+
+- **Linux**
+ ```bash
+ sudo yum install git-all
+ ```
+ ```bash
+ sudo apt-get install git-all
+ ```
+
+----------
+
+## Configure Git
+
+One-time configuration of the Git client
+
+```bash
+git config --global user.name "Your Name"
+git config --global user.email you@example.com
+```
+
+----------
+
+## Configure SSH Key
+
+```bash
+ssh-keygen -t rsa -b 4096 -C "you@computer-name"
+```
+
+```bash
+# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
+Generating public/private rsa key pair.
+Enter file in which to save the key (/Users/you/.ssh/id_rsa):
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/you/.ssh/id_rsa.
+Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
+The key fingerprint is:
+39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
+```
+
+Copy your public key and add it to your GitLab profile
+
+```bash
+cat ~/.ssh/id_rsa.pub
+```
+
+```bash
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
+```
diff --git a/doc/university/training/topics/explore_gitlab.md b/doc/university/training/topics/explore_gitlab.md
new file mode 100755
index 00000000000..b65457728c0
--- /dev/null
+++ b/doc/university/training/topics/explore_gitlab.md
@@ -0,0 +1,10 @@
+# Explore GitLab projects
+
+----------
+
+- Dashboard
+- User Preferences
+- Issues
+- Milestones and Labels
+- Manage project members
+- Project settings
diff --git a/doc/university/training/topics/feature_branching.md b/doc/university/training/topics/feature_branching.md
new file mode 100755
index 00000000000..4b34406ea75
--- /dev/null
+++ b/doc/university/training/topics/feature_branching.md
@@ -0,0 +1,32 @@
+# Feature branching
+
+----------
+
+- Efficient parallel workflow for teams
+- Develop each feature in a branch
+- Keeps changes isolated
+- Consider a 1-to-1 link to issues
+- Push branches to the server frequently
+ - Hint: This is a cheap backup for your work-in-progress code
+
+----------
+
+## Feature branching
+
+1. Create a new feature branch called 'squash_some_bugs'
+1. Edit '`bugs.rb`' and remove all the bugs.
+1. Commit
+1. Push
+
+----------
+
+## Commands
+
+```
+git checkout -b squash_some_bugs
+# Edit `bugs.rb`
+git status
+git add bugs.rb
+git commit -m 'Fix some buggy code'
+git push origin squash_some_bugs
+```
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
new file mode 100755
index 00000000000..ec7bb2631aa
--- /dev/null
+++ b/doc/university/training/topics/getting_started.md
@@ -0,0 +1,95 @@
+# Getting Started
+
+----------
+
+## Instantiating Repositories
+
+* Create a new repository by instantiating it through
+```bash
+git init
+```
+* Copy an existing project by cloning the repository through
+```bash
+git clone <url>
+```
+
+----------
+
+## Central Repos
+
+* To instantiate a central repository a `--bare` flag is required.
+* Bare repositories don't allow file editing or committing changes.
+* Create a bare repo with
+```bash
+git init --bare project-name.git
+```
+
+----------
+
+## Instantiate workflow with clone
+
+1. Create a project in your user namespace
+ - Choose to import from 'Any Repo by URL' and use
+ https://gitlab.com/gitlab-org/training-examples.git
+2. Create a '`Workspace`' directory in your home directory.
+3. Clone the '`training-examples`' project
+
+----------
+
+## Commands
+
+```
+mkdir ~/workspace
+cd ~/workspace
+
+git clone git@gitlab.example.com:<username>/training-examples.git
+cd training-examples
+```
+----------
+
+## Git concepts
+
+**Untracked files**
+
+New files that Git has not been told to track previously.
+
+**Working area**
+
+Files that have been modified but are not committed.
+
+**Staging area**
+
+Modified files that have been marked to go in the next commit.
+
+----------
+
+## Committing Workflow
+
+1. Edit '`edit_this_file.rb`' in '`training-examples`'
+1. See it listed as a changed file (working area)
+1. View the differences
+1. Stage the file
+1. Commit
+1. Push the commit to the remote
+1. View the git log
+
+----------
+
+## Commands
+
+```
+# Edit `edit_this_file.rb`
+git status
+git diff
+git add <file>
+git commit -m 'My change'
+git push origin master
+git log
+```
+
+----------
+
+## Note
+
+* git fetch vs pull
+* Pull is git fetch + git merge
diff --git a/doc/university/training/topics/git_add.md b/doc/university/training/topics/git_add.md
new file mode 100755
index 00000000000..9ffb4b9c859
--- /dev/null
+++ b/doc/university/training/topics/git_add.md
@@ -0,0 +1,33 @@
+# Git Add
+
+----------
+
+## Git Add
+
+Adds content to the index or staging area.
+
+* Adds a list of file
+```bash
+git add <files>
+```
+* Adds all files including deleted ones
+```bash
+git add -A
+```
+
+----------
+
+## Git add continued
+
+* Add all text files in current dir
+```bash
+git add *.txt
+```
+* Add all text file in the project
+```bash
+git add "*.txt*"
+```
+* Adds all files in directory
+```bash
+git add views/layouts/
+```
diff --git a/doc/university/training/topics/git_intro.md b/doc/university/training/topics/git_intro.md
new file mode 100755
index 00000000000..ca1ff29d93b
--- /dev/null
+++ b/doc/university/training/topics/git_intro.md
@@ -0,0 +1,24 @@
+# Git introduction
+
+----------
+
+## Intro
+
+https://git-scm.com/about
+
+- Distributed version control
+ - Does not rely on connection to a central server
+ - Many copies of the complete history
+- Powerful branching and merging
+- Adapts to nearly any workflow
+- Fast, reliable and stable file format
+
+----------
+
+## Help!
+
+Use the tools at your disposal when you get stuck.
+
+- Use '`git help <command>`' command
+- Use Google
+- Read documentation at https://git-scm.com
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
new file mode 100755
index 00000000000..32ebceff491
--- /dev/null
+++ b/doc/university/training/topics/git_log.md
@@ -0,0 +1,57 @@
+# Git Log
+
+----------
+
+Git log lists commit history. It allows searching and filtering.
+
+* Initiate log
+```
+git log
+```
+
+* Retrieve set number of records:
+```
+git log -n 2
+```
+
+* Search commits by author. Allows user name or a regular expression.
+```
+git log --author="user_name"
+```
+
+----------
+
+* Search by comment message.
+```
+git log --grep="<pattern>"
+```
+
+* Search by date
+```
+git log --since=1.month.ago --until=3.weeks.ago
+```
+
+
+----------
+
+## Git Log Workflow
+
+1. Change to workspace directory
+2. Clone the multi runner projects
+3. Change to project dir
+4. Search by author
+5. Search by date
+6. Combine
+
+----------
+
+## Commands
+
+```
+cd ~/workspace
+git clone git@gitlab.com:gitlab-org/gitlab-ci-multi-runner.git
+cd gitlab-ci-multi-runner
+git log --author="Travis"
+git log --since=1.month.ago --until=3.weeks.ago
+git log --since=1.month.ago --until=1.day.ago --author="Travis"
+```
diff --git a/doc/university/training/topics/gitlab_flow.md b/doc/university/training/topics/gitlab_flow.md
new file mode 100755
index 00000000000..8e5d3baf959
--- /dev/null
+++ b/doc/university/training/topics/gitlab_flow.md
@@ -0,0 +1,53 @@
+# GitLab Flow
+
+----------
+
+- A simplified branching strategy
+- All features and fixes first go to master
+- Allows for 'production' or 'stable' branches
+- Bug fixes/hot fix patches are cherry-picked from master
+
+----------
+
+### Feature branches
+
+- Create a feature/bugfix branch to do all work
+- Use merge requests to merge to master
+
+![inline](http://gitlab.com/gitlab-org/University/raw/5baea0fe222a915d0500e40747d35eb18681cdc3/training/gitlab_flow/feature_branches.png)
+
+----------
+
+## Production branch
+
+- One, long-running production release branch
+ as opposed to individual stable branches
+- Consider creating a tag for each version that gets deployed
+
+----------
+
+## Production branch
+
+![inline](http://gitlab.com/gitlab-org/University/raw/5baea0fe222a915d0500e40747d35eb18681cdc3/training/gitlab_flow/production_branch.png)
+
+----------
+
+## Release branch
+
+- Useful if you release software to customers
+- When preparing a new release, create stable branch
+ from master
+- Consider creating a tag for each version
+- Cherry-pick critical bug fixes to stable branch for patch release
+- Never commit bug fixes directly to stable branch
+
+----------
+
+![inline](http://gitlab.com/gitlab-org/University/raw/5baea0fe222a915d0500e40747d35eb18681cdc3/training/gitlab_flow/release_branches.png)
+
+----------
+
+## More details
+
+Blog post on 'GitLab Flow' at
+[http://doc.gitlab.com/ee/workflow/gitlab_flow.html](http://doc.gitlab.com/ee/workflow/gitlab_flow.html)
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
new file mode 100755
index 00000000000..77807b3e7ef
--- /dev/null
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -0,0 +1,70 @@
+# Merge conflicts
+
+----------
+
+- Happen often
+- Learning to fix conflicts is hard
+- Practice makes perfect
+- Force push after fixing conflicts. Be careful!
+
+----------
+
+## Merge conflicts
+
+1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
+2. Commit and push
+3. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
+4. Commit and push to master
+5. Create a merge request and watch it fail
+6. Rebase our new branch with master
+7. Fix conflicts on the `conflicts.rb` file.
+8. Stage the file and continue rebasing
+9. Force push the changes
+10. Finally continue with the Merge Request
+
+----------
+
+## Commands
+
+```
+git checkout -b conflicts_branch
+
+# vi conflicts.rb
+# Add 'Line4' and 'Line5'
+
+git commit -am "add line4 and line5"
+git push origin conflicts_branch
+
+git checkout master
+
+# vi conflicts.rb
+# Add 'Line6' and 'Line7'
+git commit -am "add line6 and line7"
+git push origin master
+```
+
+Create a merge request on the GitLab web UI. You'll see a conflict warning.
+
+```
+git checkout conflicts_branch
+git fetch
+git rebase master
+
+# Fix conflicts by editing the files.
+
+git add conflicts.rb
+# No need to commit this file
+
+git rebase --continue
+
+# Remember that we have rewritten our commit history so we
+# need to force push so that our remote branch is restructured
+git push origin conflicts_branch -f
+```
+----------
+
+## Note
+* When to use 'git merge' and when to use 'git rebase'
+* Rebase when updating your branch with master
+* Merge when bringing changes from feature to master
+* Reference: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/
diff --git a/doc/university/training/topics/merge_requests.md b/doc/university/training/topics/merge_requests.md
new file mode 100755
index 00000000000..5b446f02f63
--- /dev/null
+++ b/doc/university/training/topics/merge_requests.md
@@ -0,0 +1,43 @@
+# Merge requests
+
+----------
+
+- When you want feedback create a merge request
+- Target is the default branch (usually master)
+- Assign or mention the person you would like to review
+- Add 'WIP' to the title if it's a work in progress
+- When accepting, always delete the branch
+- Anyone can comment, not just the assignee
+- Push corrections to the same branch
+
+----------
+
+## Merge requests
+
+**Create your first merge request**
+
+1. Use the blue button in the activity feed
+1. View the diff (changes) and leave a comment
+1. Push a new commit to the same branch
+1. Review the changes again and notice the update
+
+----------
+
+## Feedback and Collaboration
+
+- Merge requests are a time for feedback and collaboration
+- Giving feedback is hard
+- Be as kind as possible
+- Receiving feedback is hard
+- Be as receptive as possible
+- Feedback is about the best code, not the person. You are not your code
+
+----------
+
+## Feedback and Collaboration
+
+Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
+[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review)
+
+See GitLab merge requests for examples:
+[https://gitlab.com/gitlab-org/gitlab-ce/merge_requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests)
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
new file mode 100755
index 00000000000..cf647284604
--- /dev/null
+++ b/doc/university/training/topics/rollback_commits.md
@@ -0,0 +1,81 @@
+# Rollback Commits
+
+----------
+
+## Undo Commits
+
+* Undo last commit putting everything back into the staging area.
+```
+git reset --soft HEAD^
+```
+
+* Add files and change message with:
+```
+git commit --amend -m "New Message"
+```
+
+----------
+
+* Undo last and remove changes
+```
+git reset --hard HEAD^
+```
+
+* Same as last one but for two commits back
+```
+git reset --hard HEAD^^
+```
+
+** Don't reset after pushing **
+
+----------
+
+## Reset Workflow
+
+1. Edit file again 'edit_this_file.rb'
+2. Check status
+3. Add and commit with wrong message
+4. Check log
+5. Amend commit
+6. Check log
+7. Soft reset
+8. Check log
+9. Pull for updates
+10. Push changes
+
+
+----------
+
+## Commands
+
+```
+# Change file edit_this_file.rb
+git status
+git commit -am "kjkfjkg"
+git log
+git commit --amend -m "New comment added"
+git log
+git reset --soft HEAD^
+git log
+git pull origin master
+git push origin master
+```
+
+----------
+
+## Note
+
+* git revert vs git reset
+* Reset removes the commit while revert removes the changes but leaves the commit
+* Revert is safer considering we can revert a revert
+
+```
+# Changed file
+git commit -am "bug introduced"
+git revert HEAD
+# New commit created reverting changes
+# Now we want to re apply the reverted commit
+git log # take hash from the revert commit
+git revert <rev commit hash>
+# reverted commit is back (new commit created again)
+```
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
new file mode 100755
index 00000000000..c1bdda32645
--- /dev/null
+++ b/doc/university/training/topics/stash.md
@@ -0,0 +1,86 @@
+# Git Stash
+
+----------
+
+We use git stash to store our changes when they are not ready to be committed
+and we need to change to a different branch.
+
+* Stash
+```
+git stash save
+# or
+git stash
+# or with a message
+git stash save "this is a message to display on the list"
+```
+
+* Apply stash to keep working on it
+```
+git stash apply
+# or apply a specific one from out stack
+git stash apply stash@{3}
+```
+
+----------
+
+* Every time we save a stash it gets stacked so by using list we can see all our
+stashes.
+
+```
+git stash list
+# or for more information (log methods)
+git stash list --stat
+```
+
+* To clean our stack we need to manually remove them.
+
+```
+# drop top stash
+git stash drop
+# or
+git stash drop <name>
+# to clear all history we can use
+git stash clear
+```
+
+----------
+
+* Apply and drop on one command
+
+```
+ git stash pop
+```
+
+* If we meet conflicts we need to either reset or commit our changes.
+
+* Conflicts through `pop` will not drop a stash afterwards.
+
+----------
+
+## Git Stash
+
+1. Modify a file
+2. Stage file
+3. Stash it
+4. View our stash list
+5. Confirm no pending changes through status
+5. Apply with pop
+6. View list to confirm changes
+
+----------
+
+## Commands
+
+```
+# Modify edit_this_file.rb file
+git add .
+
+git stash save "Saving changes from edit this file"
+
+git stash list
+git status
+
+git stash pop
+git stash list
+git status
+```
diff --git a/doc/university/training/topics/subtree.md b/doc/university/training/topics/subtree.md
new file mode 100755
index 00000000000..5d869af64c1
--- /dev/null
+++ b/doc/university/training/topics/subtree.md
@@ -0,0 +1,55 @@
+## Subtree
+
+----------
+
+## Subtree
+
+* Used when there are nested repositories.
+* Not recommended when the amount of dependencies is too large
+* For these cases we need a dependency control system
+* Command are painfully long so aliases are necessary
+
+----------
+
+## Subtree Aliases
+
+* Add: git subtree add --prefix <target-folder> <url> <branch> --squash
+* Pull: git subtree add --prefix <target-folder> <url> <branch> --squash
+* Push: git subtree add --prefix <target-folder> <url> <branch>
+* Ex: git config alias.sbp 'subtree pull --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+
+----------
+
+```
+ # Add an alias
+ # Add
+ git config alias.sba 'subtree add --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+ # Pull
+ git config alias.sbpl 'subtree pull --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master --squash'
+ # Push
+ git config alias.sbph 'subtree push --prefix st /
+ git@gitlab.com:balameb/subtree-nested-example.git master'
+
+ # Adding this subtree adds a st dir with a readme
+ git sba
+ vi st/README.md
+ # Edit file
+ git status shows differences
+
+```
+
+----------
+
+```
+ # Adding, or committing won't change the sub repo at remote
+ # even if we push
+ git add -A
+ git commit -m "Adding to subtree readme"
+
+ # Push to subtree repo
+ git sbph
+ # now we can check our remote sub repo
+```
diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md
new file mode 100755
index 00000000000..e9607b5a875
--- /dev/null
+++ b/doc/university/training/topics/tags.md
@@ -0,0 +1,38 @@
+# Tags
+
+----------
+
+- Useful for marking deployments and releases
+- Annotated tags are an unchangeable part of Git history
+- Soft/lightweight tags can be set and removed at will
+- Many projects combine an anotated release tag with a stable branch
+- Consider setting deployment/release tags automatically
+
+----------
+
+# Tags
+
+- Create a lightweight tag
+- Create an annotated tag
+- Push the tags to the remote repository
+
+**Additional resources**
+
+[http://git-scm.com/book/en/Git-Basics-Tagging](http://git-scm.com/book/en/Git-Basics-Tagging)
+
+----------
+
+# Commands
+
+```
+git checkout master
+
+# Lightweight tag
+git tag my_lightweight_tag
+
+# Annotated tag
+git tag -a v1.0 -m ‘Version 1.0’
+git tag
+
+git push origin --tags
+```
diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md
new file mode 100755
index 00000000000..17dbb64b9e6
--- /dev/null
+++ b/doc/university/training/topics/unstage.md
@@ -0,0 +1,31 @@
+# Unstage
+
+----------
+
+## Unstage
+
+* To remove files from stage use reset HEAD. Where HEAD is the last commit of the current branch.
+
+```bash
+git reset HEAD <file>
+```
+
+* This will unstage the file but maintain the modifications. To revert the file back to the state it was in before the changes we can use:
+
+```bash
+git checkout -- <file>
+```
+
+----------
+
+* To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag.
+```
+git rm '*.txt'
+git rm -r <dirname>
+```
+
+
+* If we want to remove a file from the repository but keep it on disk, say we forgot to add it to our `.gitignore` file then use `--cache`.
+```
+git rm <filename> --cache
+```
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
new file mode 100755
index 00000000000..35afe73708f
--- /dev/null
+++ b/doc/university/training/user_training.md
@@ -0,0 +1,392 @@
+# GitLab Git Workshop
+
+---
+
+# Agenda
+
+1. Brief history of Git
+1. GitLab walkthrough
+1. Configure your environment
+1. Workshop
+
+---
+
+# Git introduction
+
+https://git-scm.com/about
+
+- Distributed version control
+ - Does not rely on connection to a central server
+ - Many copies of the complete history
+- Powerful branching and merging
+- Adapts to nearly any workflow
+- Fast, reliable and stable file format
+
+---
+
+# Help!
+
+Use the tools at your disposal when you get stuck.
+
+- Use '`git help <command>`' command
+- Use Google
+- Read documentation at https://git-scm.com
+
+---
+
+# GitLab Walkthrough
+
+![fit](logo.png)
+
+---
+
+# Configure your environment
+
+- Windows: Install 'Git for Windows'
+
+> https://git-for-windows.github.io
+
+- Mac: Type '`git`' in the Terminal application.
+
+> If it's not installed, it will prompt you to install it.
+
+- Debian: '`sudo apt-get install git-all`'
+or Red Hat '`sudo yum install git-all`'
+
+---
+
+# Git Workshop
+
+## Overview
+
+1. Configure Git
+1. Configure SSH Key
+1. Create a project
+1. Committing
+1. Feature branching
+1. Merge requests
+1. Feedback and Collaboration
+
+---
+
+# Configure Git
+
+One-time configuration of the Git client
+
+```bash
+git config --global user.name "Your Name"
+git config --global user.email you@example.com
+```
+
+---
+
+# Configure SSH Key
+
+```bash
+ssh-keygen -t rsa -b 4096 -C "you@computer-name"
+```
+
+```bash
+# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
+Generating public/private rsa key pair.
+Enter file in which to save the key (/Users/you/.ssh/id_rsa):
+Enter passphrase (empty for no passphrase):
+Enter same passphrase again:
+Your identification has been saved in /Users/you/.ssh/id_rsa.
+Your public key has been saved in /Users/you/.ssh/id_rsa.pub.
+The key fingerprint is:
+39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
+```
+
+Copy your public key and add it to your GitLab profile
+
+```bash
+cat ~/.ssh/id_rsa.pub
+```
+
+```bash
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
+```
+
+---
+
+# Create a project
+
+- Create a project in your user namespace
+ - Choose to import from 'Any Repo by URL' and use
+ https://gitlab.com/gitlab-org/training-examples.git
+- Create a '`development`' or '`workspace`' directory in your home directory.
+- Clone the '`training-examples`' project
+
+---
+
+# Commands
+
+```
+mkdir ~/development
+cd ~/development
+
+-or-
+
+mkdir ~/workspace
+cd ~/workspace
+
+git clone git@gitlab.example.com:<username>/training-examples.git
+cd training-examples
+```
+
+---
+
+# Git concepts
+
+**Untracked files**
+
+New files that Git has not been told to track previously.
+
+**Working area**
+
+Files that have been modified but are not committed.
+
+**Staging area**
+
+Modified files that have been marked to go in the next commit.
+
+---
+
+# Committing
+
+1. Edit '`edit_this_file.rb`' in '`training-examples`'
+1. See it listed as a changed file (working area)
+1. View the differences
+1. Stage the file
+1. Commit
+1. Push the commit to the remote
+1. View the git log
+
+---
+
+# Commands
+
+```
+# Edit `edit_this_file.rb`
+git status
+git diff
+git add <file>
+git commit -m 'My change'
+git push origin master
+git log
+```
+
+---
+
+# Feature branching
+
+- Efficient parallel workflow for teams
+- Develop each feature in a branch
+- Keeps changes isolated
+- Consider a 1-to-1 link to issues
+- Push branches to the server frequently
+ - Hint: This is a cheap backup for your work-in-progress code
+
+---
+
+# Feature branching
+
+1. Create a new feature branch called 'squash_some_bugs'
+1. Edit '`bugs.rb`' and remove all the bugs.
+1. Commit
+1. Push
+
+---
+
+# Commands
+
+```
+git checkout -b squash_some_bugs
+# Edit `bugs.rb`
+git status
+git add bugs.rb
+git commit -m 'Fix some buggy code'
+git push origin squash_some_bugs
+```
+
+---
+
+# Merge requests
+
+- When you want feedback create a merge request
+- Target is the ‘default’ branch (usually master)
+- Assign or mention the person you would like to review
+- Add 'WIP' to the title if it's a work in progress
+- When accepting, always delete the branch
+- Anyone can comment, not just the assignee
+- Push corrections to the same branch
+
+---
+
+# Merge requests
+
+**Create your first merge request**
+
+1. Use the blue button in the activity feed
+1. View the diff (changes) and leave a comment
+1. Push a new commit to the same branch
+1. Review the changes again and notice the update
+
+---
+
+# Feedback and Collaboration
+
+- Merge requests are a time for feedback and collaboration
+- Giving feedback is hard
+- Be as kind as possible
+- Receiving feedback is hard
+- Be as receptive as possible
+- Feedback is about the best code, not the person. You are not your code
+
+---
+
+# Feedback and Collaboration
+
+Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
+[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review)
+
+See GitLab merge requests for examples:
+[https://gitlab.com/gitlab-org/gitlab-ce/merge_requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests)
+
+---
+
+# Explore GitLab projects
+
+![fit](logo.png)
+
+- Dashboard
+- User Preferences
+- ReadMe, Changelog, License shortcuts
+- Issues
+- Milestones and Labels
+- Manage project members
+- Project settings
+
+---
+
+# Tags
+
+- Useful for marking deployments and releases
+- Annotated tags are an unchangeable part of Git history
+- Soft/lightweight tags can be set and removed at will
+- Many projects combine an anotated release tag with a stable branch
+- Consider setting deployment/release tags automatically
+
+---
+
+# Tags
+
+- Create a lightweight tag
+- Create an annotated tag
+- Push the tags to the remote repository
+
+**Additional resources**
+
+[http://git-scm.com/book/en/Git-Basics-Tagging](http://git-scm.com/book/en/Git-Basics-Tagging)
+
+---
+
+# Commands
+
+```
+git checkout master
+
+# Lightweight tag
+git tag my_lightweight_tag
+
+# Annotated tag
+git tag -a v1.0 -m ‘Version 1.0’
+git tag
+
+git push origin --tags
+```
+
+---
+
+# Merge conflicts
+
+- Happen often
+- Learning to fix conflicts is hard
+- Practice makes perfect
+- Force push after fixing conflicts. Be careful!
+
+---
+
+# Merge conflicts
+
+1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
+1. Commit and push
+1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
+1. Commit and push to master
+1. Create a merge request
+
+---
+
+# Merge conflicts
+
+After creating a merge request you should notice that conflicts exist. Resolve
+the conflicts locally by rebasing.
+
+```
+git rebase master
+
+# Fix conflicts by editing the files.
+
+git add conflicts.rb
+git commit -m 'Fix conflicts'
+git rebase --continue
+git push origin <branch> -f
+```
+
+---
+
+# Rebase with squash
+
+You may end up with a commit log that looks like this:
+
+```
+Fix issue #13
+Test
+Fix
+Fix again
+Test
+Test again
+Does this work?
+```
+
+Squash these in to meaningful commits using an interactive rebase.
+
+---
+
+# Rebase with squash
+
+Squash the commits on the same branch we used for the merge conflicts step.
+
+```
+git rebase -i master
+```
+
+In the editor, leave the first commit as 'pick' and set others to 'fixup'.
+
+---
+
+# Questions?
+
+![fit](logo.png)
+
+Thank you for your hard work!
+
+**Additional Resources**
+
+GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/)
+GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis)
+Pro git book [http://git-scm.com/book](http://git-scm.com/book)
+Platzi Course [https://courses.platzi.com/courses/git-gitlab/](https://courses.platzi.com/courses/git-gitlab/)
+Code School tutorial [http://try.github.io/](http://try.github.io/)
+Contact Us - [subscribers@gitlab.com](subscribers@gitlab.com)
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index a13e353b7f5..40644fc2adf 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -26,6 +26,16 @@ module API
present @groups, with: Entities::Group
end
+ # Get list of owned groups for authenticated user
+ #
+ # Example Request:
+ # GET /groups/owned
+ get '/owned' do
+ @groups = current_user.owned_groups
+ @groups = paginate @groups
+ present @groups, with: Entities::Group, user: current_user
+ end
+
# Create group. Available only for users who can create groups.
#
# Parameters:
diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb
index 9b73f6826cf..8984cf8cdcd 100644
--- a/lib/api/milestones.rb
+++ b/lib/api/milestones.rb
@@ -11,19 +11,25 @@ module API
else milestones
end
end
+
+ params :optional_params do
+ optional :description, type: String, desc: 'The description of the milestone'
+ optional :due_date, type: String, desc: 'The due date of the milestone'
+ end
end
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
resource :projects do
- # Get a list of project milestones
- #
- # Parameters:
- # id (required) - The ID of a project
- # state (optional) - Return "active" or "closed" milestones
- # Example Request:
- # GET /projects/:id/milestones
- # GET /projects/:id/milestones?iid=42
- # GET /projects/:id/milestones?state=active
- # GET /projects/:id/milestones?state=closed
+ desc 'Get a list of project milestones' do
+ success Entities::Milestone
+ end
+ params do
+ optional :state, type: String, values: %w[active closed all], default: 'all',
+ desc: 'Return "active", "closed", or "all" milestones'
+ optional :iid, type: Integer, desc: 'The IID of the milestone'
+ end
get ":id/milestones" do
authorize! :read_milestone, user_project
@@ -34,34 +40,31 @@ module API
present paginate(milestones), with: Entities::Milestone
end
- # Get a single project milestone
- #
- # Parameters:
- # id (required) - The ID of a project
- # milestone_id (required) - The ID of a project milestone
- # Example Request:
- # GET /projects/:id/milestones/:milestone_id
+ desc 'Get a single project milestone' do
+ success Entities::Milestone
+ end
+ params do
+ requires :milestone_id, type: Integer, desc: 'The ID of a project milestone'
+ end
get ":id/milestones/:milestone_id" do
authorize! :read_milestone, user_project
- @milestone = user_project.milestones.find(params[:milestone_id])
- present @milestone, with: Entities::Milestone
+ milestone = user_project.milestones.find(params[:milestone_id])
+ present milestone, with: Entities::Milestone
end
- # Create a new project milestone
- #
- # Parameters:
- # id (required) - The ID of the project
- # title (required) - The title of the milestone
- # description (optional) - The description of the milestone
- # due_date (optional) - The due date of the milestone
- # Example Request:
- # POST /projects/:id/milestones
+ desc 'Create a new project milestone' do
+ success Entities::Milestone
+ end
+ params do
+ requires :title, type: String, desc: 'The title of the milestone'
+ use :optional_params
+ end
post ":id/milestones" do
authorize! :admin_milestone, user_project
- required_attributes! [:title]
- attrs = attributes_for_keys [:title, :description, :due_date]
- milestone = ::Milestones::CreateService.new(user_project, current_user, attrs).execute
+ milestone_params = declared(params, include_parent_namespaces: false)
+
+ milestone = ::Milestones::CreateService.new(user_project, current_user, milestone_params).execute
if milestone.valid?
present milestone, with: Entities::Milestone
@@ -70,22 +73,23 @@ module API
end
end
- # Update an existing project milestone
- #
- # Parameters:
- # id (required) - The ID of a project
- # milestone_id (required) - The ID of a project milestone
- # title (optional) - The title of a milestone
- # description (optional) - The description of a milestone
- # due_date (optional) - The due date of a milestone
- # state_event (optional) - The state event of the milestone (close|activate)
- # Example Request:
- # PUT /projects/:id/milestones/:milestone_id
+ desc 'Update an existing project milestone' do
+ success Entities::Milestone
+ end
+ params do
+ requires :milestone_id, type: Integer, desc: 'The ID of a project milestone'
+ optional :title, type: String, desc: 'The title of the milestone'
+ optional :state_event, type: String, values: %w[close activate],
+ desc: 'The state event of the milestone '
+ use :optional_params
+ at_least_one_of :title, :description, :due_date, :state_event
+ end
put ":id/milestones/:milestone_id" do
authorize! :admin_milestone, user_project
- attrs = attributes_for_keys [:title, :description, :due_date, :state_event]
- milestone = user_project.milestones.find(params[:milestone_id])
- milestone = ::Milestones::UpdateService.new(user_project, current_user, attrs).execute(milestone)
+ milestone_params = declared(params, include_parent_namespaces: false, include_missing: false)
+
+ milestone = user_project.milestones.find(milestone_params.delete(:milestone_id))
+ milestone = ::Milestones::UpdateService.new(user_project, current_user, milestone_params).execute(milestone)
if milestone.valid?
present milestone, with: Entities::Milestone
@@ -94,21 +98,20 @@ module API
end
end
- # Get all issues for a single project milestone
- #
- # Parameters:
- # id (required) - The ID of a project
- # milestone_id (required) - The ID of a project milestone
- # Example Request:
- # GET /projects/:id/milestones/:milestone_id/issues
+ desc 'Get all issues for a single project milestone' do
+ success Entities::Issue
+ end
+ params do
+ requires :milestone_id, type: Integer, desc: 'The ID of a project milestone'
+ end
get ":id/milestones/:milestone_id/issues" do
authorize! :read_milestone, user_project
- @milestone = user_project.milestones.find(params[:milestone_id])
+ milestone = user_project.milestones.find(params[:milestone_id])
finder_params = {
project_id: user_project.id,
- milestone_title: @milestone.title
+ milestone_title: milestone.title
}
issues = IssuesFinder.new(current_user, finder_params).execute
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index ecc8f2fc5a2..84c19c432b0 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -1,34 +1,39 @@
module API
- # Runners API
class Runners < Grape::API
before { authenticate! }
resource :runners do
- # Get runners available for user
- #
- # Example Request:
- # GET /runners
+ desc 'Get runners available for user' do
+ success Entities::Runner
+ end
+ params do
+ optional :scope, type: String, values: %w[active paused online],
+ desc: 'The scope of specific runners to show'
+ end
get do
runners = filter_runners(current_user.ci_authorized_runners, params[:scope], without: ['specific', 'shared'])
present paginate(runners), with: Entities::Runner
end
- # Get all runners - shared and specific
- #
- # Example Request:
- # GET /runners/all
+ desc 'Get all runners - shared and specific' do
+ success Entities::Runner
+ end
+ params do
+ optional :scope, type: String, values: %w[active paused online specific shared],
+ desc: 'The scope of specific runners to show'
+ end
get 'all' do
authenticated_as_admin!
runners = filter_runners(Ci::Runner.all, params[:scope])
present paginate(runners), with: Entities::Runner
end
- # Get runner's details
- #
- # Parameters:
- # id (required) - The ID of ther runner
- # Example Request:
- # GET /runners/:id
+ desc "Get runner's details" do
+ success Entities::RunnerDetails
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the runner'
+ end
get ':id' do
runner = get_runner(params[:id])
authenticate_show_runner!(runner)
@@ -36,33 +41,37 @@ module API
present runner, with: Entities::RunnerDetails, current_user: current_user
end
- # Update runner's details
- #
- # Parameters:
- # id (required) - The ID of ther runner
- # description (optional) - Runner's description
- # active (optional) - Runner's status
- # tag_list (optional) - Array of tags for runner
- # Example Request:
- # PUT /runners/:id
+ desc "Update runner's details" do
+ success Entities::RunnerDetails
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the runner'
+ optional :description, type: String, desc: 'The description of the runner'
+ optional :active, type: Boolean, desc: 'The state of a runner'
+ optional :tag_list, type: Array[String], desc: 'The list of tags for a runner'
+ optional :run_untagged, type: Boolean, desc: 'Flag indicating the runner can execute untagged jobs'
+ optional :locked, type: Boolean, desc: 'Flag indicating the runner is locked'
+ at_least_one_of :description, :active, :tag_list, :run_untagged, :locked
+ end
put ':id' do
- runner = get_runner(params[:id])
+ runner = get_runner(params.delete(:id))
authenticate_update_runner!(runner)
- attrs = attributes_for_keys [:description, :active, :tag_list, :run_untagged, :locked]
- if runner.update(attrs)
+ runner_params = declared(params, include_missing: false)
+
+ if runner.update(runner_params)
present runner, with: Entities::RunnerDetails, current_user: current_user
else
render_validation_error!(runner)
end
end
- # Remove runner
- #
- # Parameters:
- # id (required) - The ID of ther runner
- # Example Request:
- # DELETE /runners/:id
+ desc 'Remove a runner' do
+ success Entities::Runner
+ end
+ params do
+ requires :id, type: Integer, desc: 'The ID of the runner'
+ end
delete ':id' do
runner = get_runner(params[:id])
authenticate_delete_runner!(runner)
@@ -72,28 +81,31 @@ module API
end
end
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ end
resource :projects do
before { authorize_admin_project }
- # Get runners available for project
- #
- # Example Request:
- # GET /projects/:id/runners
+ desc 'Get runners available for project' do
+ success Entities::Runner
+ end
+ params do
+ optional :scope, type: String, values: %w[active paused online specific shared],
+ desc: 'The scope of specific runners to show'
+ end
get ':id/runners' do
runners = filter_runners(Ci::Runner.owned_or_shared(user_project.id), params[:scope])
present paginate(runners), with: Entities::Runner
end
- # Enable runner for project
- #
- # Parameters:
- # id (required) - The ID of the project
- # runner_id (required) - The ID of the runner
- # Example Request:
- # POST /projects/:id/runners/:runner_id
+ desc 'Enable a runner for a project' do
+ success Entities::Runner
+ end
+ params do
+ requires :runner_id, type: Integer, desc: 'The ID of the runner'
+ end
post ':id/runners' do
- required_attributes! [:runner_id]
-
runner = get_runner(params[:runner_id])
authenticate_enable_runner!(runner)
@@ -106,13 +118,12 @@ module API
end
end
- # Disable project's runner
- #
- # Parameters:
- # id (required) - The ID of the project
- # runner_id (required) - The ID of the runner
- # Example Request:
- # DELETE /projects/:id/runners/:runner_id
+ desc "Disable project's runner" do
+ success Entities::Runner
+ end
+ params do
+ requires :runner_id, type: Integer, desc: 'The ID of the runner'
+ end
delete ':id/runners/:runner_id' do
runner_project = user_project.runner_projects.find_by(runner_id: params[:runner_id])
not_found!('Runner') unless runner_project
diff --git a/lib/api/session.rb b/lib/api/session.rb
index 55ec66a6d67..d09400b81f5 100644
--- a/lib/api/session.rb
+++ b/lib/api/session.rb
@@ -1,15 +1,14 @@
module API
- # Users API
class Session < Grape::API
- # Login to get token
- #
- # Parameters:
- # login (*required) - user login
- # email (*required) - user email
- # password (required) - user password
- #
- # Example Request:
- # POST /session
+ desc 'Login to get token' do
+ success Entities::UserLogin
+ end
+ params do
+ optional :login, type: String, desc: 'The username'
+ optional :email, type: String, desc: 'The email of the user'
+ requires :password, type: String, desc: 'The password of the user'
+ at_least_one_of :login, :email
+ end
post "/session" do
user = Gitlab::Auth.find_with_user_password(params[:email] || params[:login], params[:password])
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
index b1a6d5fe0f6..f4d1505ea91 100644
--- a/lib/gitlab/ee_compat_check.rb
+++ b/lib/gitlab/ee_compat_check.rb
@@ -2,39 +2,38 @@
module Gitlab
# Checks if a set of migrations requires downtime or not.
class EeCompatCheck
+ CE_REPO = 'https://gitlab.com/gitlab-org/gitlab-ce.git'.freeze
EE_REPO = 'https://gitlab.com/gitlab-org/gitlab-ee.git'.freeze
+ CHECK_DIR = Rails.root.join('ee_compat_check')
+ MAX_FETCH_DEPTH = 500
+ IGNORED_FILES_REGEX = /(VERSION|CHANGELOG\.md:\d+)/.freeze
- attr_reader :ce_branch, :check_dir, :ce_repo
+ attr_reader :repo_dir, :patches_dir, :ce_repo, :ce_branch
- def initialize(branch:, check_dir:, ce_repo: nil)
+ def initialize(branch:, ce_repo: CE_REPO)
+ @repo_dir = CHECK_DIR.join('repo')
+ @patches_dir = CHECK_DIR.join('patches')
@ce_branch = branch
- @check_dir = check_dir
- @ce_repo = ce_repo || 'https://gitlab.com/gitlab-org/gitlab-ce.git'
+ @ce_repo = ce_repo
end
def check
ensure_ee_repo
- delete_patches
+ ensure_patches_dir
generate_patch(ce_branch, ce_patch_full_path)
- Dir.chdir(check_dir) do
- step("In the #{check_dir} directory")
-
- step("Pulling latest master", %w[git pull --ff-only origin master])
+ Dir.chdir(repo_dir) do
+ step("In the #{repo_dir} directory")
status = catch(:halt_check) do
ce_branch_compat_check!
-
- delete_ee_branch_locally
-
+ delete_ee_branch_locally!
ee_branch_presence_check!
-
ee_branch_compat_check!
end
- delete_ee_branch_locally
- delete_patches
+ delete_ee_branch_locally!
if status.nil?
true
@@ -47,20 +46,43 @@ module Gitlab
private
def ensure_ee_repo
- if Dir.exist?(check_dir)
- step("#{check_dir} already exists")
+ if Dir.exist?(repo_dir)
+ step("#{repo_dir} already exists")
else
- cmd = %W[git clone --branch master --single-branch --depth 1 #{EE_REPO} #{check_dir}]
- step("Cloning #{EE_REPO} into #{check_dir}", cmd)
+ cmd = %W[git clone --branch master --single-branch --depth 200 #{EE_REPO} #{repo_dir}]
+ step("Cloning #{EE_REPO} into #{repo_dir}", cmd)
end
end
- def ce_branch_compat_check!
- cmd = %W[git apply --check #{ce_patch_full_path}]
- status = step("Checking if #{ce_patch_name} applies cleanly to EE/master", cmd)
+ def ensure_patches_dir
+ FileUtils.mkdir_p(patches_dir)
+ end
+
+ def generate_patch(branch, patch_path)
+ FileUtils.rm(patch_path, force: true)
+
+ depth = 0
+ loop do
+ depth += 50
+ cmd = %W[git fetch --depth #{depth} origin --prune +refs/heads/master:refs/remotes/origin/master]
+ Gitlab::Popen.popen(cmd)
+ _, status = Gitlab::Popen.popen(%w[git merge-base FETCH_HEAD HEAD])
+
+ raise "#{branch} is too far behind master, please rebase it!" if depth >= MAX_FETCH_DEPTH
+ break if status.zero?
+ end
- if status.zero?
- puts ce_applies_cleanly_msg(ce_branch)
+ step("Generating the patch against master in #{patch_path}")
+ output, status = Gitlab::Popen.popen(%w[git format-patch FETCH_HEAD --stdout])
+ throw(:halt_check, :ko) unless status.zero?
+
+ File.write(patch_path, output)
+ throw(:halt_check, :ko) unless File.exist?(patch_path)
+ end
+
+ def ce_branch_compat_check!
+ if check_patch(ce_patch_full_path).zero?
+ puts applies_cleanly_msg(ce_branch)
throw(:halt_check)
end
end
@@ -80,10 +102,8 @@ module Gitlab
step("Checking out origin/#{ee_branch}", %W[git checkout -b #{ee_branch} FETCH_HEAD])
generate_patch(ee_branch, ee_patch_full_path)
- cmd = %W[git apply --check #{ee_patch_full_path}]
- status = step("Checking if #{ee_patch_name} applies cleanly to EE/master", cmd)
- unless status.zero?
+ unless check_patch(ee_patch_full_path).zero?
puts
puts ee_branch_doesnt_apply_cleanly_msg
@@ -91,50 +111,49 @@ module Gitlab
end
puts
- puts ee_applies_cleanly_msg
+ puts applies_cleanly_msg(ee_branch)
end
- def generate_patch(branch, filepath)
- FileUtils.rm(filepath, force: true)
+ def check_patch(patch_path)
+ step("Checking out master", %w[git checkout master])
+ step("Reseting to latest master", %w[git reset --hard origin/master])
- depth = 0
- loop do
- depth += 10
- step("Fetching origin/master", %W[git fetch origin master --depth=#{depth}])
- status = step("Finding merge base with master", %W[git merge-base FETCH_HEAD #{branch}])
-
- break if status.zero? || depth > 500
- end
+ step("Checking if #{patch_path} applies cleanly to EE/master")
+ output, status = Gitlab::Popen.popen(%W[git apply --check #{patch_path}])
- raise "#{branch} is too far behind master, please rebase it!" if depth > 500
+ unless status.zero?
+ failed_files = output.lines.reduce([]) do |memo, line|
+ if line.start_with?('error: patch failed:')
+ file = line.sub(/\Aerror: patch failed: /, '')
+ memo << file unless file =~ IGNORED_FILES_REGEX
+ end
+ memo
+ end
- step("Generating the patch against master")
- output, status = Gitlab::Popen.popen(%w[git format-patch FETCH_HEAD --stdout])
- throw(:halt_check, :ko) unless status.zero?
+ if failed_files.empty?
+ status = 0
+ else
+ puts "\nConflicting files:"
+ failed_files.each do |file|
+ puts " - #{file}"
+ end
+ end
+ end
- File.write(filepath, output)
- throw(:halt_check, :ko) unless File.exist?(filepath)
+ status
end
- def delete_ee_branch_locally
+ def delete_ee_branch_locally!
command(%w[git checkout master])
step("Deleting the local #{ee_branch} branch", %W[git branch -D #{ee_branch}])
end
- def delete_patches
- step("Deleting #{ce_patch_full_path}")
- FileUtils.rm(ce_patch_full_path, force: true)
-
- step("Deleting #{ee_patch_full_path}")
- FileUtils.rm(ee_patch_full_path, force: true)
- end
-
def ce_patch_name
@ce_patch_name ||= "#{ce_branch}.patch"
end
def ce_patch_full_path
- @ce_patch_full_path ||= File.expand_path(ce_patch_name, check_dir)
+ @ce_patch_full_path ||= patches_dir.join(ce_patch_name)
end
def ee_branch
@@ -146,15 +165,18 @@ module Gitlab
end
def ee_patch_full_path
- @ee_patch_full_path ||= File.expand_path(ee_patch_name, check_dir)
+ @ee_patch_full_path ||= patches_dir.join(ee_patch_name)
end
def step(desc, cmd = nil)
puts "\n=> #{desc}\n"
if cmd
+ start = Time.now
puts "\n$ #{cmd.join(' ')}"
- command(cmd)
+ status = command(cmd)
+ puts "\nFinished in #{Time.now - start} seconds"
+ status
end
end
@@ -165,12 +187,12 @@ module Gitlab
status
end
- def ce_applies_cleanly_msg(ce_branch)
+ def applies_cleanly_msg(branch)
<<-MSG.strip_heredoc
=================================================================
🎉 Congratulations!! 🎉
- The #{ce_branch} branch applies cleanly to EE/master!
+ The #{branch} branch applies cleanly to EE/master!
Much ❤️!!
=================================================================\n
@@ -211,7 +233,7 @@ module Gitlab
# In the EE repo
$ git fetch origin
- $ git checkout -b #{ee_branch} FETCH_HEAD
+ $ git checkout -b #{ee_branch} origin/master
$ git fetch #{ce_repo} #{ce_branch}
$ git cherry-pick SHA # Repeat for all the commits you want to pick
@@ -245,17 +267,5 @@ module Gitlab
=================================================================\n
MSG
end
-
- def ee_applies_cleanly_msg
- <<-MSG.strip_heredoc
- =================================================================
- 🎉 Congratulations!! 🎉
-
- The #{ee_branch} branch applies cleanly to EE/master!
-
- Much ❤️!!
- =================================================================\n
- MSG
- end
end
end
diff --git a/lib/tasks/gitlab/dev.rake b/lib/tasks/gitlab/dev.rake
index 5ee99dfc810..3117075b08b 100644
--- a/lib/tasks/gitlab/dev.rake
+++ b/lib/tasks/gitlab/dev.rake
@@ -1,18 +1,22 @@
namespace :gitlab do
namespace :dev do
desc 'Checks if the branch would apply cleanly to EE'
- task ee_compat_check: :environment do
- return if defined?(Gitlab::License)
- return unless ENV['CI']
+ task :ee_compat_check, [:branch] => :environment do |_, args|
+ opts =
+ if ENV['CI']
+ {
+ branch: ENV['CI_BUILD_REF_NAME'],
+ ce_repo: ENV['CI_BUILD_REPO']
+ }
+ else
+ unless args[:branch]
+ puts "Must specify a branch as an argument".color(:red)
+ exit 1
+ end
+ args
+ end
- success =
- Gitlab::EeCompatCheck.new(
- branch: ENV['CI_BUILD_REF_NAME'],
- check_dir: File.expand_path('ee-compat-check', __dir__),
- ce_repo: ENV['CI_BUILD_REPO']
- ).check
-
- if success
+ if Gitlab::EeCompatCheck.new(opts || {}).check
exit 0
else
exit 1
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 12989d4db53..fe26b4ac18c 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -113,6 +113,26 @@ describe Repository, models: true do
end
end
+ describe '#ref_exists?' do
+ context 'when ref exists' do
+ it 'returns true' do
+ expect(repository.ref_exists?('refs/heads/master')).to be true
+ end
+ end
+
+ context 'when ref does not exist' do
+ it 'returns false' do
+ expect(repository.ref_exists?('refs/heads/non-existent')).to be false
+ end
+ end
+
+ context 'when ref format is incorrect' do
+ it 'returns false' do
+ expect(repository.ref_exists?('refs/heads/invalid:master')).to be false
+ end
+ end
+ end
+
describe '#last_commit_for_path' do
subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
@@ -197,6 +217,35 @@ describe Repository, models: true do
end
end
+ describe '#commit' do
+ context 'when ref exists' do
+ it 'returns commit object' do
+ expect(repository.commit('master'))
+ .to be_an_instance_of Commit
+ end
+ end
+
+ context 'when ref does not exist' do
+ it 'returns nil' do
+ expect(repository.commit('non-existent-ref')).to be_nil
+ end
+ end
+
+ context 'when ref is not valid' do
+ context 'when preceding tree element exists' do
+ it 'returns nil' do
+ expect(repository.commit('master:ref')).to be_nil
+ end
+ end
+
+ context 'when preceding tree element does not exist' do
+ it 'returns nil' do
+ expect(repository.commit('non-existent:ref')).to be_nil
+ end
+ end
+ end
+ end
+
describe "#commit_dir" do
it "commits a change that creates a new directory" do
expect do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 7b47bf5afc1..b29a13b1d8b 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -68,6 +68,24 @@ describe API::API, api: true do
end
end
+ describe 'GET /groups/owned' do
+ context 'when unauthenticated' do
+ it 'returns authentication error' do
+ get api('/groups/owned')
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'when authenticated as group owner' do
+ it 'returns an array of groups the user owns' do
+ get api('/groups/owned', user2)
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.first['name']).to eq(group2.name)
+ end
+ end
+ end
+
describe "GET /groups/:id" do
context "when authenticated as user" do
it "returns one of user1's groups" do
diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb
index dd192bea432..62327f64e50 100644
--- a/spec/requests/api/milestones_spec.rb
+++ b/spec/requests/api/milestones_spec.rb
@@ -123,6 +123,15 @@ describe API::API, api: true do
expect(json_response['title']).to eq('updated title')
end
+ it 'removes a due date if nil is passed' do
+ milestone.update!(due_date: "2016-08-05")
+
+ put api("/projects/#{project.id}/milestones/#{milestone.id}", user), due_date: nil
+
+ expect(response).to have_http_status(200)
+ expect(json_response['due_date']).to be_nil
+ end
+
it 'returns a 404 error if milestone id not found' do
put api("/projects/#{project.id}/milestones/1234", user),
title: 'updated title'
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 3c8f0ac531a..d6e9fd2c4b2 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -175,6 +175,30 @@ describe API::API, api: true do
end
end
+ describe 'GET /projects/owned' do
+ before do
+ project3
+ project4
+ end
+
+ context 'when unauthenticated' do
+ it 'returns authentication error' do
+ get api('/projects/owned')
+ expect(response).to have_http_status(401)
+ end
+ end
+
+ context 'when authenticated as project owner' do
+ it 'returns an array of projects the user owns' do
+ get api('/projects/owned', user4)
+ expect(response).to have_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.first['name']).to eq(project4.name)
+ expect(json_response.first['owner']['username']).to eq(user4.username)
+ end
+ end
+ end
+
describe 'GET /projects/visible' do
let(:public_project) { create(:project, :public) }
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index f46f016135e..99414270be6 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -226,7 +226,7 @@ describe API::Runners, api: true do
context 'authorized user' do
context 'when runner is shared' do
it 'does not update runner' do
- put api("/runners/#{shared_runner.id}", user)
+ put api("/runners/#{shared_runner.id}", user), description: 'test'
expect(response).to have_http_status(403)
end
@@ -234,7 +234,7 @@ describe API::Runners, api: true do
context 'when runner is not shared' do
it 'does not update runner without access to it' do
- put api("/runners/#{specific_runner.id}", user2)
+ put api("/runners/#{specific_runner.id}", user2), description: 'test'
expect(response).to have_http_status(403)
end
diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb
index acad1365ace..e3f22b4c578 100644
--- a/spec/requests/api/session_spec.rb
+++ b/spec/requests/api/session_spec.rb
@@ -67,22 +67,24 @@ describe API::API, api: true do
end
context "when empty password" do
- it "returns authentication error" do
+ it "returns authentication error with email" do
post api("/session"), email: user.email
- expect(response).to have_http_status(401)
- expect(json_response['email']).to be_nil
- expect(json_response['private_token']).to be_nil
+ expect(response).to have_http_status(400)
+ end
+
+ it "returns authentication error with username" do
+ post api("/session"), email: user.username
+
+ expect(response).to have_http_status(400)
end
end
context "when empty name" do
it "returns authentication error" do
post api("/session"), password: user.password
- expect(response).to have_http_status(401)
- expect(json_response['email']).to be_nil
- expect(json_response['private_token']).to be_nil
+ expect(response).to have_http_status(400)
end
end
end