Developer Cheatsheet
Useful Commands
general
- Testing CI/CD Jobs Locally:
gitlab-runner exec shell job_name
gitlab-org/gitlab
gdk start
(gdk doctor
bin/rake frontend:fixtures
- Running tests:
yarn karma
yarn jest
- Debugging Capybara
CHROME_HEADLESS=0 bundle exec rspec spec/features/projects/tree/create_directory_spec.rb
- Capybara Screenshots
screenshot_and_save_page
screenshot_and_open_image
live_debug
- Static Analysis:
scripts/static-analysis
(long)yarn eslint
(faster)
fdescribe
andfit
for focused karma specs
Running QA Specs
See https://gitlab.com/gitlab-org/gitlab/tree/master/qa#how-can-i-use-it for more details.
cd qa
bundle
brew cask <install|reinstall> chromedriver
bundle exec bin/qa Test::Instance::All http://0.0.0.0:3000 -- qa/specs/features/ee/browser_ui/1_manage/project/project_templates_spec.rb
To run the QA specs in RubyMine, use a custom rspec runner configuration (right click on the arrow next to the example in the gutter), and set the qa/bin/rubymine
script as the custom RSpec runner script, and the working directory as qa
.
See more detailed instructions for this process here: https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/end_to_end_test_configuration.md#starting-tests-using-the-rubymine-gutter
gitlab-com/www-gitlab-com
- Run site locally:
cd sites/handbook && NO_CONTRACTS=true bundle exec middleman
- (see monorepo docs for more details)
- Development Documentation
- You can use this dashboard to select a page or pages and timeframe for page views: https://datastudio.google.com/reporting/e7618539-81b4-4174-9731-3c858e3057b2/page/xXKYB
Tips and Tricks
GDK Tips
- To access EE features, you need to make sure you have an EE license added in
/admin/license
Running Web IDE Terminal in GDK
- GDK Docs: Web IDE Terminal HowTo
- YouTube: Web IDE Terminal - Setup using GDK (23:44)
GDK Debugging
Log Debugging
- If you want to print out a debugging message:
puts
orp
will ONLY show up ingdk tail rails
logger.info('...')
will ONLY show up intail -f log/development.log
RubyMine Debugging
MOVED: Ths section on debugging the GDK with the RubyMine debugger has been moved to https://handbook.gitlab.com/handbook/tools-and-tips/editors-and-ides/jetbrains-ides/individual-ides/rubymine/#debugging-rails-web
Git Tips
Rebasing
Interactive Rebasing
- Use of interactive rebasing (
git rebase -i master
) and message cleanup viareword
/fixup
are worth learning more about if you are unfamiliar with them. - Interactive rebasing tip:
- This process will let you separate “interactive rebasing” against the
merge-base
(the common ancestor of your branchHEAD
and the upstream branchmaster
) from the possibility of “conflict resolution” when rebasing against the latest upstreammaster
. - First, do a
git rebase -i $(git merge-base HEAD master)
. This lets you do your interactive rebase against themerge-base
without any chance of having to deal with conflicts at the same time. Make sure that themerge-base
commit is contained on your master branch (i.e. you didn’t just fetch and checkout the branch directly without updating master). You could justgit fetch
then rebase againstorigin/master
, but this negates the benefit of using--force-with-lease
. - Optionally
git push --force-with-lease
(Or just wait until after the next step to push if you don’t want to trigger an extra unnecessary build) - Then, do a
git rebase master
, to rebase against the latest master, and resolve any conflicts against your cleaned-up, interactively-rebased branch. git push --force-with-lease
(force-with-lease ensures nobody else has pushed to the branch since you last pulled)
- This process will let you separate “interactive rebasing” against the
Using the –onto option for rebasing stacked MRs
If you have multiple MRs which are “stacked” on each other, the --onto
option is very useful and can help avoid unnecessary rebase conflicts.
Assume this situation:
first
MR and branch is based off of themaster
(main
) branch, and has some commits.second
MR and branch is based off of thefirst
branch, and has some commits.first
branch has been rebased off ofmaster
.- This means that the
first
branch’s commit’s SHAs have changed, and thus the SHAs for those commits in thesecond
branch are outdated.
This is where --onto
comes in handy. If you simply tried to rebase second
directly on to of first
, you would get a lot of confusing rebase conflicts that didn’t make sense, because the “history” or state of the first
branch has changed compared to what the second
branch currently knows about.
But there’s a way to avoid these confusing and unnecessary conflicts: You take ONLY the commits that are part of the second
branch, and rebase them ONTO the current state of the first
branch, using the --onto
option.
Here’s how:
git checkout second
git log second
and copy the SHA of the commit that USED to be the latest commit on thefirst
branch. For example,abcdef
- NOTE: If you have ensured that there is only a single commit on the
second
branch (via regular interactive rebase andfixup
as explained above), then you can also just usehead^
instead of getting the specific SHA.
- NOTE: If you have ensured that there is only a single commit on the
- Rebase “relative” to that commit, “onto” the
first
branch:git rebase abcdef --onto first
, or ifsecond
only has one commit, usegit rebase head^ --onto first
- Continue on with the rebase as normal. You may still get some legitimate conflicts you have to resolve if
first
has changed some of the same lines assecond
, but no confusing/unnecessary conflicts due to thesecond
branch’s “outdated history” offirst
, because you’ve ignored it with--onto
.
Git References
- See this blog post and our git cheatsheet for more git tips.
Interactive Git Learning Tools
- http://onlywei.github.io/explain-git-with-d3/ is a very cool sandbox site that takes you through tutorials of various git commands, with a real-time visualization of what is going on. You can also type your own commands outside of the tutorial instructions in many cases!
- https://ndpsoftware.com/git-cheatsheet.html is a great reference and visualization of the various git commands grouped into different “areas” in git.
Squashing down a branch which has had master merged into it
When a branch has followed a merge instead of a rebase workflow, it can get very confusing to know what is going on, and you want to just squash it down to a single commit. But, you can’t just do a regular interactive rebase relative to master if the branch has had master merged into it. Here’s what you have to do instead.
Note there may be more efficient ways of doing this, suggestions are welcome. Also note that sometimes this doesn’t work, you’ll end up with almost all the changes from the branch uncommitted after step 5 - not sure why :(
Assuming branch is named branch
and upstream is named master
:
-
Do a log of all the commits on the branch:
git log master..branch --oneline
-
Find the last (latest) commit on the branch. It will be the top one, assume it is
c60ed83
. -
Find the commit on the branch which is IMMEDIATELY BEFORE the merge commit.
-
You can run
git log --graph --oneline --decorate
on your branch to find the merge commit - the merge commit will likely have a commit message like “resoove merge conflicts”. -
Follow the “line” of your branch down and find the commit on your branch immediately before the merge commit.
-
Here’s an example of what this would look like. In this example,
c36ee33
is the merge commit, andb48156a
is the commit immediately before it. In a real terminal, the lines will also be different colors, to make this easier to read.* c60ed83 (HEAD -> caw-investigate-rebase-conflicts, origin/caw-investigate-rebase-conflicts) chore: fix vue * a5269d6 chore: fix vue * b3941ad chore: fix previous commits * c36ee33 chore: resolve conflicts |\ | * a13f09e (origin/llb/conditionally-load-legacy-web-ide-scripts) Merge branch 'removeRemoteFromExample' into 'main' | |\ | | * a5144c2 chore: Remove "Remote Development" mode from the example app | |/ | * c33f00c Merge branch 'cwoolley-gitlab-main-patch-d6cd' into 'main' | |\ | | * fcfb4a1 (origin/cwoolley-gitlab-main-patch-d6cd, cwoolley-gitlab-main-patch-d6cd) chore: Update file Default.md | * | e97eeec Merge branch 'replaceLogger' into 'main' | |\ \ | | * | 8d48c3e chore: Replace console.log reference with actual logger | * | | 60be327 Merge branch 'rename-group-ide-label' into 'main' | |\ \ \ | | |_|/ | |/| | | | * | 90ac565 chore: Rename group::ide to "group::remote development" | |/ / | * | 0b89422 (origin/365-make-vscode-loglevel-configurable-2, origin/365-make-vscode-loglevel-configurable) Merge branch 'dp-remove-remote-repository' into 'main' | |\ \ | | |/ | |/| | | * fc374f0 feat: Remove "Configure a Remote Connection" command | |/ | * 522f9b9 Merge branch 'updateCommit' into 'main' | |\ | | * 9a99045 feat: update copy for committing to new branch | * | e6a542f Merge branch 'ealcantara/web-ide-development-process-issue-template' into 'main' | |\ \ | | |/ | |/| | | * a520ee4 (origin/ealcantara/web-ide-development-process-issue-template) chore: Web IDE development process issue template * | | b48156a chore: fix waitForReady * | | 3f4bae3 chore: ran prettier * | | bc990b1 chore: remove with erroneous configType * | | 75ad9f0 chore: fix errors ... ...
-
Copy the SHA of that commit which is immediately before the merge commit. For this example, we’ll assume its
b48156a
-
-
Reset hard to the commit before your merge commit:
git reset --hard b48156a
-
merge --squash
the last commit:git merge --squash c60ed83
-
Now, if you run
git log --graph --oneline --decorate
again, you will see that the merge commit and all the commits after it have been replaced with a single normal, non-merge commit. Here’s an example of what the above log looks like after doing this:* b48156a (HEAD -> caw-investigate-rebase-conflicts) chore: fix waitForReady * 3f4bae3 chore: ran prettier * bc990b1 chore: remove with erroneous configType * 75ad9f0 chore: fix errors ... ...
-
If there were other merge commits, get rid of them using the same steps.
-
NOTE: In some cases, after the squash, there may be extra changes from the master commits that you don’t want. Get rid of them with:
git restore --staged .
git checkout .
git clean -df
Now, you should be able to use rebase
and rebase --interactive
normally on your branch.
If you want to try this out yourself with the above example, you can check out this branch (just don’t push it back to the repo).
Working with Issues/MRs
New habits
Though the contributor and development docs are the single source of truth, there are some additional habits that may be worth developing when you’re new to the code contribution process.
Depending on your existing habits and git
practices the habits below may help mitigate pain during code submissions.
- Keep GDK up to date (update often, if not daily)
- Keep your commit history clean
- Take special note of the commit message guidelines
- See “Git Tips” above
- Keep merge requests small
- Merge conflicts are inevitable, but focusing on making your MRs smaller will save you pain later
- Keep localization files up to date
- When adding English copy, messages, or labels don’t forget to update localization files
Dealing with Broken Master
- https://handbook.gitlab.com/handbook/engineering/workflow/#broken-master
- https://handbook.gitlab.com/handbook/engineering/workflow/#merging-during-broken-master
Browser Testing
- Browser Testing: https://docs.gitlab.com/ee/development/fe_guide/index.html#browser-support
- Dynamic element validation in E2E tests: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/dynamic_element_validation.html
Links on Testing and Software Design
About testing:
- Vue test utils guide: https://vue-test-utils.vuejs.org/guides/
- Book: The way of the web tester: https://pragprog.com/titles/jrtest/
- An essay on mocks: https://martinfowler.com/articles/mocksArentStubs.html
- Clean architecture book: https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164
Some frontendmasters workshops related to testing that I want to take after the web security workshop:
- https://frontendmasters.com/courses/testing-practices-principles/
- https://frontendmasters.com/courses/testing-javascript/
Jetbrains IDE Usage
MOVED: There is now a dedicated handbook section on JetBrains IDEs: https://handbook.gitlab.com/handbook/tools-and-tips/editors-and-ides/jetbrains-ides/
c74771be
)