lab.el
lab.el copied to clipboard
Emacs-GitLab integration
#+TITLE: lab.el
[[https://stable.melpa.org/#/lab][file:https://stable.melpa.org/packages/lab-badge.svg]] [[https://melpa.org/#/lab][file:https://melpa.org/packages/lab-badge.svg]]
/lab.el/ is an Emacs package that provides a simple integration with GitLab (managed or self-hosted).
- Basics
~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 [[https://github.com/oantolin/embark][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.
- Installation lab is available through [[https://melpa.org/#/lab][MELPA]]. If you have it set up already, just do ~M-x package-install lab~ and you are good to go. Otherwise please see [[https://melpa.org/#/getting-started][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 [[https://github.com/radian-software/straight.el][straight]] or [[https://github.com/quelpa/quelpa-use-package][quelpa]] package managers:
#+begin_src elisp ;; 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")) #+end_src
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=:
#+begin_src elisp (require 'lab) #+end_src
- Usage
Set the following variables and you are good to go:
#+begin_src elisp ;; 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") #+end_src
Alternative you could retrieve your token using auth-source. Some auth-source backends support encryption. ej.
#+begin_src elisp (setq auth-sources '("~/.authinfo.gpg"))
;; And then store and entry with the following format in ~/.authinfo.gpg machine $lab-host password $lab-token #+end_src
See ~M-x customize-group lab~ for all customization options.
- Functionality summary
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. Search projects using ~lab-search-project~ (optionally with [[https://github.com/minad/consult][consult]] live search support).
- 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 (~lab-list-all-{owned,group}-projects~), and act on these projects. Search projects using ~lab-search-project~ (optionally with [[https://github.com/minad/consult][consult]] live search support).
- 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 (~lab-list-{my,group,branch,project}-merge-requests~), and act on these merge requests:
- 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 (~lab-list-project-pipelines~), and act on these pipelines:
- 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~:
[[file:https://user-images.githubusercontent.com/8031017/204106589-7558cac5-e41c-4fe5-8834-1df610b736f4.png]]
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.
[[file:https://user-images.githubusercontent.com/8031017/204106597-f51d3e9c-084e-45e2-bbeb-c2dee6a7a2d9.png]]
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:
[[file:https://user-images.githubusercontent.com/8031017/204106593-3acdaffc-a1a4-4115-9fd8-339d2ac3930f.png]]
- Extras/tips
** Embark and Consult integration
If you have [[https://github.com/minad/consult][consult]] and [[https://github.com/oantolin/embark][embark]] installed on your Emacs, ~lab.el~ will automatically integrate itself with them. If you have ~consult~ installed, you get live search feature on some of the commands, like ~lab-search-project~. With 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/.
Installing these packages are highly recommended.
** Keybindings
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:
#+begin_src emacs-lisp (bind-key "C-x l" lab-map) #+end_src
...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.
** Supplemental packages
Some packages enhances ~lab.el~ with extra features:
- [[https://github.com/jwiegley/alert][alert]] :: Desktop notifications for ~lab-watch-*~ commands.
- [[https://github.com/jrblevin/markdown-mode][markdown-mode]] :: For better ~lab-create-merge-request~.
- [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Version-Control.html][vc]] :: Shows you the diff generated by your merge request while creating a merge request with ~lab-create-merge-request~.
- [[https://github.com/sshaw/git-link][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.
** Start watching your pipeline automatically
-
After creating an MR:
#+begin_src emacs-lisp (add-hook lab-after-merge-requests-create-functions #'lab-watch-merge-request-last-pipeline) #+end_src
-
After pushing a commit:
#+begin_src emacs-lisp (add-hook YOUR-PUSH-HOOK #'lab-watch-pipeline-for-last-commit) #+end_src
-
If you are using [[https://github.com/magit/magit][magit]], following advice may be used for triggering pipeline watcher after each push:
#+begin_src emacs-lisp (define-advice magit-push-current-to-pushremote (:after (&rest _) start-watching-pipeline) (lab-watch-pipeline-for-last-commit)) #+end_src
-
If you are using vc, it would be the following:
#+begin_src emacs-lisp (define-advice vc-push (:after (&rest _) start-watching-pipeline) (lab-watch-pipeline-for-last-commit)) #+end_src
** ~project.el~ integration
You can integrate the ~lab.el~ functions you frequently use into ~project.el~, like following:
#+begin_src emacs-lisp (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")) #+end_src
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.
** org-mode integration
~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_src org ,#+begin: lab-merge-requests :type group :group "my" :limit 4 :state opened :headers ("state" "title" "author.username") ,#+end #+end_src
Hitting ~C-c C-c~ on this line will fetch the requests and display something like the following:
#+begin_src org ,#+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 #+end_src
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.
- Using as a GitLab API client
You can use the provided ~lab--request~ function write your on [[https://docs.gitlab.com/ee/api/api_resources.html][GitLab API]] wrappers:
#+begin_src elisp ;; Get all pipelines currently running on master. (lab--request "projects/#{project}/pipelines" :scope "running" :ref "master" :%collect-all t) #+end_src
- Differences & similarities with [[https://github.com/magit/forge][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:
#+begin_quote 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. #+end_quote