lab.el is an Emacs package that provides a simple integration with GitLab (managed or self-hosted).
lab.el
is designed to make your daily interactions with GitLab easier. Want to quickly list latest merge requests for a project? You got covered! Want to create a merge request for the project you are currently working on, totally inside Emacs? You got covered! Want every function on GitLab API exposed as an elisp function? You are on your own. See Functionality summary down below for a quick rundown of what lab.el
is capable of.
Workflow is generally completing-read
based. You list and select an item (a project/merge request/pipeline/job) and then you trigger one of the listed actions that can be acted upon selected item. There are also other special interactive functions, like lab-create-merge-request
. Also some functions work directly on current project you are working on (provided by project.el
).
lab.el also supports embark, you can use (embark-act)
on any kind of item and you’ll see all possible actions. This is generally useful for doing bulk actions (possibly using embark-act-all
) as the primary feature of embark, listing actions of a target, is already covered by lab.el.
I extracted this package from my init.el
as the feature set grew to a point that is too much to keep it in there. This may explain why some of the functionality that you expect a GitLab client would have is missing. It’s because I probably don’t use that feature.
lab is available through MELPA. If you have it set up already, just do M-x package-install lab
and you are good to go. Otherwise please see MELPA getting started page to learn how you can install packages through MELPA or see the following installation options.
Another way to install lab.el
would be using either straight or quelpa package managers:
;; Using straight:
(use-package lab
:straight (:host github :repo "isamert/lab.el"))
;; Using quelpa:
(use-package lab
:quelpa (lab
:fetcher github
:repo "isamert/lab.el"))
Yet another option is just downloading lab.el
file and putting into your load-path
, afterwards you can simply do the following in your init.el
:
(require 'lab)
Set the following variables and you are good to go:
;; Required.
(setq lab-host "https://gitlab.mycompany.com")
;; Required.
;; See the following link to learn how you can gather one for yourself:
;; https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token
(setq lab-token "YOUR-PRIVATE-GITLAB-API-TOKEN")
;; Optional, but useful. See the variable documentation.
(setq lab-group "YOUR-GROUP-ID")
Alternative you could retrieve your token using auth-source. Some auth-source backends support encryption. ej.
(setq auth-sources '("~/.authinfo.gpg"))
;; And then store and entry with the following format in ~/.authinfo.gpg
machine $lab-host password $lab-token
See M-x customize-group lab
for all customization options.
Here is a quick rundown of features lab.el
provides. I’ve included entry functions inside parenthesis but some of the functionality is accessed through other listing functions.
- Projects
-
- List projects belonging to you or a group (
lab-list-all-{owned,group}-projects
), and act on these projects.- Open them in browser.
- Clone single project or do a bulk cloning.
- List merge requests of given project.
- Show detailed information about given project.
- Bulk pull projects to keep your local copies up-to-date (
lab-pull-bulk
).
- List projects belonging to you or a group (
- Merge Requests
-
- List merge requests belonging to a group, a branch, a project or all merge requests that you created or assigned to (
lab-list-{my,group,branch,project}-merge-requests
), and act on these merge requests:- Open them in browser.
- Mark them as ready or as draft.
- Rebase remote branch against the target.
- List pipelines and act on them.
- Show detailed information about given merge request.
- Create merge requests with an easy to use merge request wizard. It also let’s you edit details of your merge requests in markdown buffer with yaml header and shows you the diff generated by your merge request (
lab-create-merge-request
).
- List merge requests belonging to a group, a branch, a project or all merge requests that you created or assigned to (
- Pipelines
-
- List pipelines belonging to a project or a merge request (
lab-list-project-pipelines
), and act on these pipelines:- Open them in browser.
- Trigger retries, cancellation or deletion.
- Start watching given pipeline in background and get notified if pipeline finishes or requires a manual action.
- List individual jobs of a pipeline and act on them.
- Show detailed information about given pipeline.
- Automatically start watching pipelines after a push and get notified about their status. (See Extras/tips section below)
- List pipelines belonging to a project or a merge request (
- Jobs
-
- List jobs belonging to a pipeline.
- Show logs of a (latest) failing job in a nicely formatted Emacs buffer (
lab-act-on-last-failed-pipeline-job
). - Act on jobs:
- Open them in browser.
- Trigger retries, cancellation or deletion.
- Show logs of a job on a nicely formatted buffer.
- Show detailed information about given job.
- TODOs
-
- List all TODOs for current user
- Mark all TODOs as done
- Act on TODOs:
- Open them in browser.
- Mark as done.
Here are few screenshots to get a feel of what you would see while using lab.el
:
By default, actions can be selected using read-multiple-choice
. You can change this to a completing-read
based action handler by modifying the lab-action-handler
variable.
Other functions work in similar fashion, where you list something (projects/pipelines/jobs etc.) and act upon them. Here is how you create a merge request:
No default keybindings are provided but there is lab-map
keymap which contains some interactive lab functions. You can bind this keymap to a key, like following:
(bind-key "C-x l" lab-map)
…and now you can do C-x mm
to list your open merge requests, for example. Do M-x describe-keymap
lab-map to list all actions in this keymap.
Some packages enhances lab.el
with extra features:
- alert
- Desktop notifications for
lab-watch-*
commands. - markdown-mode
- For better
lab-create-merge-request
. - vc
- Shows you the diff generated by your merge request while creating a merge request with
lab-create-merge-request
. - git-link
- Open current repository in browser easily.
lab.el
does not use this package but it’s nice to have if your workflow requires some manual interventions to GitLab UI.
- After creating an MR:
(add-hook lab-after-merge-requests-create-functions #'lab-watch-merge-request-last-pipeline)
- After pushing a commit:
(add-hook YOUR-PUSH-HOOK #'lab-watch-pipeline-for-last-commit)
- If you are using magit, following advice may be used for triggering pipeline watcher after each push:
(define-advice magit-push-current-to-pushremote (:after (&rest _) start-watching-pipeline) (lab-watch-pipeline-for-last-commit))
- If you are using vc, it would be the following:
(define-advice vc-push (:after (&rest _) start-watching-pipeline) (lab-watch-pipeline-for-last-commit))
You can integrate the lab.el
functions you frequently use into project.el
, like following:
(define-key project-prefix-map "M" #'lab-list-project-merge-requests)
(add-to-list 'project-switch-commands `(lab-list-project-merge-requests "List merge requests"))
(define-key project-prefix-map "P" #'lab-list-project-pipelines)
(add-to-list 'project-switch-commands `(lab-list-project-pipelines "List pipelines"))
Now List pipelines
and List merge requests
actions will be added to project.el
actions list and you’ll be able to access them using C-x p M
and C-x p P
respectively.
lab.el
provides a dynamic block named lab-merge-requests
which let’s you list merge requests that matches your query. See the following example.
#+begin: lab-merge-requests :type group :group "my" :limit 4 :state opened :headers ("state" "title" "author.username")
#+end
Hitting C-c C-c
on this line will fetch the requests and display something like the following:
#+begin: lab-merge-requests :type group :group "my" :limit 4 :state opened :headers ("state" "title" "author.username")
| State | Title | Author Username |
|--------+----------------------------+-----------------|
| opened | Update DB configuration | john |
| opened | Add tsIn and tsOut headers | isamert |
| opened | Update media display type | prot |
| opened | Lists offers by sellers | rms |
#+end
This dynamic block has various options that let you change how the merge requests are displayed and filtered. Refer to the documentation of the function org-dblock-write:lab-merge-requests
to learn more.
You can use the provided lab--request
function write your on GitLab API wrappers:
;; Get *all* pipelines currently running on master.
(lab--request
"projects/#{project}/pipelines"
:scope "running"
:ref "master"
:%collect-all t)
Differences & similarities with forge
Although lab.el and forge have some overlapping features, they can be used together to complement each other. Here is a comment I made earlier when the difference is asked:
I don’t use forge (tried in the past but not got so far with it), so I cant really give a throughout answer but here is a quick summary as far as I know:
forge does not provide any functionality regarding to
- pipelines
- jobs
- projects (like listing owned/group projects and doing actions on them like cloning, printing detailed info etc.)
Please see README for rundown of operations that you can do with aforementioned features.
forge copies remote information into your local, so you need to sync stuff time to time. lab.el retrieves information on demand. This can be a good or bad thing depending on how your workflow is structured.
lab.el have specialized functions, like
lab-list-my-merge-requests
which lists all the merge requests you’ve opened or assigned to recently. So it is not tied to a single project, you can jump around more easily. There are a few functions like this.lab.el is structured around
completing-read
. So there is really so little that you need to learn, just call the function, select something and act on them. No complex buffers.Most of the time, lab.el provides you an easy way to jump to related GitLab page instead of trying to do things in Emacs. For example, I don’t see the point of having merge-request comments inside Emacs without the diff like forge does. So lab.el redirects you to GitLab page where-I think-its better to do. If the thing is easier and beneficial to handle in Emacs, lab.el does that. An example for that would be the
lab-act-on-last-failed-pipeline-job
function which shows you the jobs for the latest failed pipeline so that you can act on them (like triggering a retry or dumping the logs into a buffer) right inside Emacs.forge has a way of dealing with GitLab issues too, lab.el does not provide anything on this end (but merge requests are welcome). forge also handles merge-request comments whereas with lab.el you can only create merge-requests inside Emacs, no comment management. (But as I indicated above, I don’t find this feature in forge super useful.)
I believe the overall usage and focus is completely different, you need to check it out to see yourself. I may have misinformation about forge on some topics I listed above, please correct me where I’m wrong.