Signing and publishing posts

Following on the same topic as the previous post, I had this bugging me: how can I automate this signing posts thing?

I considered a couple of ideas, but the one that seemed that fit the most was writing some elisp functions to generate the signed version of the post. Why? Because I am already living for the most part in Emacs, and also because I want to improve my elisp game.

As I mentioned, I am using ox-hugo to export from my org files to markdown and then use Hugo to generate the blog.

I am also already using elisp functions to run hugo and publish the blog.

Take a look at the publishing function:

;; It needs hugo installed and in the PATH
(defun al/publish-albxcc ()
  "[al] Run Hugo in HUGO-DIR and copy the generated files in 'public/' to TARGET-DIR."
  (interactive)
  (let* ((hugo-dir "local-dir-hugo-root")
         (target-dir "/ssh:remote-hosting-server:/home/remote-user/remote-dir/public_html/")
         (default-directory (file-name-as-directory hugo-dir))
         (public-dir (expand-file-name "public/" hugo-dir)))
    ;; Run Hugo
    (message "Running Hugo in directory: %s" hugo-dir)
    (unless (executable-find "hugo")
      (error "Hugo executable not found"))
    (let ((output (shell-command-to-string "hugo")))
      (if (string-match-p "Error" output)
          (error "Hugo encountered an error:\n%s" output)
        (message "Hugo build completed successfully")))
    ;; Copy files to target directory
    (message "Copying files from '%s' to '%s'" public-dir target-dir)
    (dired-copy-file-recursive public-dir target-dir t t t)
    (message "Files successfully copied to '%s'" target-dir)))

The cool thing about this one, is that it runs hugo in its base directory, and then copy directly the generated files to the hosting server in the right directory.

No need for password or something as it is using TRAMP with ssh and this is configured to use an id file.

Now, because I also wanted to play with the signing of these posts, I also wrote the following function:

(defun al/sign-hugo-post ()
    "[al] will gpg-sign current entry and put the output in hugo dir"
  (interactive)
  (let* ((_base-dir
          (or (org-entry-get nil "EXPORT_HUGO_SECTION" nil nil) "posts"))
         (_file-name
          (or (org-entry-get nil "EXPORT_FILE_NAME" nil nil) "unnamed"))
         (_hugo-base-dir
          (or
           (org-entry-get nil "HUGO_BASE_DIR" t nil)
           (or (cadr (nth 0 (org-collect-keywords '("HUGO_BASE_DIR")))) "unknown")))
         (_full-path (expand-file-name
                      (file-name-concat
                       (expand-file-name _hugo-base-dir)
                       "public" _base-dir (concat _file-name ".asc"))))
         (_tmp-file (make-temp-file "/tmp/sign-hugo-"))
         (_tmp-file-signed (concat _tmp-file ".asc"))
         (gpg-command "gpg")
         (args (list "--clear-sign"
                     _tmp-file)))
    (org-show-subtree)
    (org-export-to-file 'ascii _tmp-file nil t t)
    (apply 'call-process gpg-command nil "*hugo-sign*" nil args)
    (message "[al] Copying file to %s" _full-path)
    (copy-file _tmp-file-signed _full-path)
    (delete-file _tmp-file)
    (delete-file _tmp-file-signed)))

This one use org-export-to-file to export the current post as plain text (ascii), and then run gpg to sign the file.

Finally my workflow in emacs is just:

  1. C-c C-e H H (to export org to markdown)
  2. M-x al/sign-hugo-post (to sign the post I want to sign)
  3. M-x al/publish-albxcc (to publish the files)

… et voilà.

This might be the only signed post, so, if you want to check it:

curl -s https://albx.cc/posts/signing-posts.asc | gpg --verify