{"id":24335635,"url":"https://github.com/gs-101/emacs-master","last_synced_at":"2025-04-14T16:42:02.621Z","repository":{"id":272813442,"uuid":"917822994","full_name":"gs-101/emacs-master","owner":"gs-101","description":"Guix channel for the latest Emacs from the master branch.","archived":false,"fork":false,"pushed_at":"2025-04-12T02:54:14.000Z","size":752,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-12T03:34:22.563Z","etag":null,"topics":["emacs","guix-channel"],"latest_commit_sha":null,"homepage":"","language":"Scheme","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gs-101.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-01-16T17:58:13.000Z","updated_at":"2025-04-12T02:54:17.000Z","dependencies_parsed_at":"2025-02-14T07:22:13.805Z","dependency_job_id":"461f47a9-781e-4719-81e8-a697e0a4b112","html_url":"https://github.com/gs-101/emacs-master","commit_stats":null,"previous_names":["gs-101/emacs-master"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gs-101%2Femacs-master","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gs-101%2Femacs-master/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gs-101%2Femacs-master/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gs-101%2Femacs-master/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gs-101","download_url":"https://codeload.github.com/gs-101/emacs-master/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248918321,"owners_count":21183164,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","guix-channel"],"created_at":"2025-01-18T05:19:33.084Z","updated_at":"2025-04-14T16:42:02.608Z","avatar_url":"https://github.com/gs-101.png","language":"Scheme","funding_links":[],"categories":["Channels"],"sub_categories":[],"readme":"#+title: Emacs Master\n#+OPTIONS: f:t\n\n#+html: \u003ca href=\"https://github.com/gs-101/emacs-master/actions/workflows/update-emacs.yml\"\u003e\u003cimg src=\"https://github.com/gs-101/emacs-master/actions/workflows/update-emacs.yml/badge.svg\"\u003e\u003c/a\u003e\n#+html: \u003ca href=\"https://github.com/gs-101/emacs-master/actions/workflows/build-emacs.yml\"\u003e\u003cimg src=\"https://github.com/gs-101/emacs-master/actions/workflows/build-emacs.yml/badge.svg\"\u003e\u003c/a\u003e\n\n#+begin_quote\n[!NOTE]\n\nThis channel features automation through GitHub Actions. That means bugs are to be expected.\n\nIf you want a safer experience but still close to source, check out the built-in [[https://packages.guix.gnu.org/packages/emacs-next/][emacs-next]] packages, or the ones available at the [[https://codeberg.org/divyaranjan/divya-lambda][divya-lambda]] channel.\n#+end_quote\n\nGuix channel featuring automated builds that run every two hours, updating the packages to the latest [[https://git.savannah.gnu.org/cgit/emacs.git][Savannah]] commit.\n\nThis channel is sort of a fork of divya-lambda[fn:1], which features a non-automated build of =emacs-master=, taken from guix-channel-emacs-master[fn:2].\n\nCommit updates are made with a [[./.github/workflows/emacs-master.yml][GitHub Actions workflow]], and are automatically signed[fn:3].\n\n* Channel Definition\n\nUse this for adding this channel to your configuration:\n\n#+begin_src scheme\n  (cons* (channel\n          (name 'emacs-master)\n          (url \"https://github.com/gs-101/emacs-master.git\")\n          (branch \"main\")\n          (introduction\n           (make-channel-introduction\n            \"568579841d0ca41a9d222a2cfcad9a7367f9073b\"\n            (openpgp-fingerprint\n             \"3049 BF6C 0829 94E4 38ED  4A15 3033 E0E9 F7E2 5FE4\"))))\n         %default-channels)\n#+end_src\n\n* Packages\n\nSince this takes packages from divya-lambda, the following packages are available:\n\n- =emacs-master= ::\n\n  Regular package.\n\n- =emacs-master-pgtk= ::\n\n  Package featuring a GTK build. Best suited for Wayland users.\n\n- =emacs-master-lucid= ::\n\n  Package using the [[https://gitlab.freedesktop.org/xorg/lib/libxaw][Lucid (Athena)]] X toolkit. Best suited for those on X11.\n\n  Some recommend it over PGTK, so try both of them out and use what best suits you.\n\n- =emacs-master-igc= ::\n\n  New garbage collection method in development.\n\n* Workflow\n\nIn case I stop maintaining this and someone else becomes interested, this section details how the workflow works.\n\n** Scheduling\n\nScheduling is done through the use of a cron job, taken from copr-lutris-git[fn:4].\n\nAt first, it ran every hour:\n\n#+begin_src yaml\n  on:\n    workflow_dispatch:\n    schedule:\n      - cron: \"0 * * * *\"\n#+end_src\n\nBut then I changed it to every two hours because I thought I was overloading savannah:\n\n#+begin_src yaml\n  on:\n    workflow_dispatch:\n    schedule:\n      - cron: \"0 */2 * * *\"\n#+end_src\n\n** The Job\n\nTo allow GitHub Actions to commit to repository, you need to give the job write permissions:\n\n#+begin_src yaml\n  jobs:\n    update-emacs:\n      runs-on: ubuntu-latest\n      permissions:\n        contents: write\n#+end_src\n\n*** Steps\n\n**** Checkout\n\nThis should've been clear to me from the start, but, to have Actions actually work with your repository, you have to use the checkout action:\n\n#+begin_src yaml\n      - name: Checkout Repository\n        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683\n#+end_src\n\nThis makesthe runner clone your repository.\n\n**** Dependencies\n\nThese dependencies are primarily used by the scripts. Guix is used to get the hash of the Emacs commit, in the [[./bin/get_hash.sh][get_hash]] script. Since we're not installing anything, no extra setup for Guix is required.\n\n#+begin_src yaml\n      - name: Install Dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y curl grep guix git gpg guile-3.0 guile-library\n#+end_src\n\n**** Get Curent Commit\n\nThis is going to be needed later. It cuts the exact space where the commit hash is found, storing it in a enviroment variable, so it can be used by the other steps.\n\n#+begin_src yaml\n      - name: Get Current Commit\n        run: |\n          echo \"current-commit=$(grep \"(define emacs-master-commit\" emacs-master.scm | awk '{print $3}' | cut -c 2-41)\" \u003e\u003e $GITHUB_ENV\n#+end_src\n\n**** Update Emacs\n\nThis runs the scripts from guix-channel-emacs-master for getting the latest commit. [[./bin/update-emacs][update-emacs]] gets the commit and time, and we rely on [[./bin/get_hash.sh][get_hash]] for, well, getting the hash.\n\n#+begin_src yaml\n  - name: Update Emacs\n    run: |\n      chmod +x bin/get_hash.sh\n      chmod +x bin/update-emacs\n      bin/update-emacs\n      echo \"new-commit=$(grep \"(define emacs-master-commit\" emacs-master.scm | awk '{print $3}' | cut -c 2-41)\" \u003e\u003e $GITHUB_ENV\n#+end_src\n\nWe also create another variable, ~new-commit~, to be usd in the next step: Compare Commits.\n\n**** Compare Commits\n\nDespite what the echoed messages say, this doesn't make the workflow exit directly. It's a simple comparison for defining a boolean variable to be used by the other steps.\n\n#+begin_src yaml\n      - name: Compare Commits\n        id: compare-commits\n        run: |\n          if [ \"${{ env.new-commit }}\" != \"${{ env.current-commit }}\" ]; then\n            echo \"The commits are different. Continue the workflow.\"\n            echo \"different-commit='true'\" \u003e\u003e $GITHUB_OUTPUT\n          else\n            echo \"The commits are the same. Exiting the workflow...\"\n            echo \"different-commit='false'\" \u003e\u003e $GITHUB_OUTPUT\n          fi\n#+end_src\n\n**** GPG Key\n\nThis is where we use those instructions from “Sign git commits with GPG in GitHub Actions”. This is the workflow's key, not yours.\n\nWe'll setup some *repository* secrets. See how /repository/ is in bold? That indicates another mistake I made during this. I thought that GitHub Actions used /enviroment/ secrets, so I wasted some time on this.\n\n[[./images/gpg_secrets.png]]\n\nIn case you didn't know how, you can generate a GPG key with:\n\n#+begin_src sh\n  gpg --full-generate-key\n#+end_src\n\n1. When choosing a key type, you can pick a signing only one if you want. We have no need for encryption here. I always choose RSA.\n2. For the keysize, same thing, you choose. I always go for 4096 because there's no issue in doing this.\n3. Make it not expire if you want, though, that can be insecure.\n4. Use either your real name or your GitHub username.\n5. This should be the e-mail address you use for GitHub.\n6. Add a descriptive comment here, you'll start to make a lot of these once you get used to them. Mine is \"GitHub Actions Key\".\n7. Make a password.\n8. There is no other step, that was it!\n\nNow we'll get to the secrets. Save them to Settings \\rightarrow Secrets and variables \\rightarrow Actions \\rightarrow Repository secrets with these exact names.\n\n- ~GPG_KEY_PASSPHRASE~ ::\n\n  This is the password you set up for the key.\n\n- ~GPG_KEY_ID~ ::\n\n  This is the identification of the key, you can get this with:\n\n  #+begin_src sh\n    gpg --list-secret-keys --keyid-format=long\n  #+end_src\n\n  #+begin_src text\n    sec   something/YOU-WANT-THIS-HERE 1111-11-11 [SC] [expires: 9999-99-99]\n          don't-bother-with-this\n    uid                 [ultimate] your-name (GitHub Actions Key) \u003cthe-email-you-used@address.com\u003e\n  #+end_src\n\n  You'll want the numbers and letters that are in the same position as =YOU-WANT-THIS-HERE= in the example above.\n\n  =your-name= and =the-email-you-used@address.com= are also important, but will be explained later.\n\n- ~GPG_KEY~ ::\n\n  THis is your key itself, exported in base64. Based on the previous variable, you'd run:\n\n  #+begin_src sh\n    gpg --export-secret-keys YOU-WANT-THIS-HERE | base64\n  #+end_src\n\n  This will give you even more numbers and letters.\n\n  #+begin_quote\n  [!NOTE]\n\n  If your terminal added newlines for the display, before adding this output to your secrets, remove the newlines and make everything a single line. I'm not sure if this is necessary, but seems like a good practice.\n  #+end_quote\n\n***** Import GPG Key\n\nThis just makes the runner import your base64 encoded key:\n\n#+begin_src yaml\n      - name: Import GPG Key\n        if: ${{ contains(steps.compare-commits.Outputs.different-commit, 'true') }}\n        run: echo \"$GPG_KEY\" | base64 --decode | gpg --batch --import\n        env:\n          GPG_KEY: ${{ secrets.GPG_KEY }}\n#+end_src\n\nThe ~if~ statement comes from our previous comparison step. This and the next steps only run if ~different-commit~ is ~true~.\n\n***** Custom GPG Signing Program\n\nUsed in the next step for Git. Makes it so that the runner always inputs the passphrase, to keep the process automatic. It's not like we can access it to input the password, and even if we could, that would be a manual step.\n\n#+begin_src yaml\n      - name: Custom GPG Signing Program\n        if: ${{ contains(steps.compare-commits.Outputs.different-commit, 'true') }}\n        run: |\n          echo \"#!/bin/bash\" \u003e\u003e /tmp/gpg.sh\n          echo \"gpg --batch --pinentry-mode=loopback --passphrase \\$GPG_KEY_PASSPHRASE \\\"\\$@\\\"\" \u003e\u003e /tmp/gpg.sh\n          chmod +x /tmp/gpg.sh\n        env:\n          GPG_KEY_PASSPHRASE: ${{ secrets.GPG_KEY_PASSPHRASE }}\n#+end_src\n\n***** Setup Git\n\nNothing out of the ordinary. This just makes Git use our key.\n\n#+begin_src yaml\n      - name: Setup Git\n        if: ${{ contains(steps.compare-commits.Outputs.different-commit, 'true') }}\n        run: |\n          git config commit.gpgsign true\n          git config user.signingkey $GPG_KEY_ID\n          git config gpg.program /tmp/gpg.sh\n        env:\n          GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}\n#+end_src\n\n***** Commit\n\n#+begin_src yaml\n      - name: Commit\n        if: ${{ contains(steps.compare-commits.Outputs.different-commit, 'true') }}\n        run: |\n          git add emacs-master.scm\n          short_commit=$(grep \"(define emacs-master-commit\" emacs-master.scm | awk '{print $3}' | cut -c 2-8)\n          git commit -m \"feat (emacs-master.scm): Update Emacs to $short_commit\" --gpg-sign=$GPG_KEY_ID\n          git push --set-upstream origin main\n        env:\n         GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}\n         GPG_KEY_PASSPHRASE: ${{ secrets.GPG_KEY_PASSPHRASE }}\n         GIT_COMMITTER_NAME: ${{ secrets.GIT_COMMITTER_NAME }}\n         GIT_COMMITTER_EMAIL: ${{ secrets.GIT_COMMITTER_EMAIL }}\n         GIT_AUTHOR_NAME: github-actions\n         GIT_AUTHOR_EMAIL: github-actions@example.com\n#+end_src\n\nNot sure if =--gpg-sign=$GPG_KEY_ID= is necessary, but I don't want to change as everything is working now. Try doing a run without it to see the outcome.\n\nNow, remember when I said that =your-name= and =the-email-you-used@address.com= were important? This is where they are used. Add them as ~GIT_COMMITTER_NAME~ and ~GIT_COMMITTER_EMAIL~, respectively.\n\n~GIT_AUTHOR_NAME~ should preferably be the name of your workflow bot (we use GitHub Actions, so I named it ~github-actions~ here). ~GIT_AUTHOR_EMAIL~ can be anything.\n\nAnd that was it for the workflow! Hope you could understand everything.\n\n* References\n\n[fn:1] Ranjan, D. (2024) “Divya-lambda.” Available at: https://codeberg.org/divyaranjan/divya-lambda (Accessed: January 16, 2025).\n\n[fn:2] Azmain Turja, A. (2023) “guix-channel-emacs-master.” Available at: https://codeberg.org/akib/guix-channel-emacs-master (Accessed: January 16, 2025).\n\n[fn:3] Bakulin, S. “Sign git commits with GPG in GitHub Actions” Available at: https://gist.github.com/vansergen/88eb7e71fea2e3bdaf6aa3e752371eb7 (Accessed: January 16, 2025).\n\n[fn:4] Greiner, J. (2025) “Projectsynchro/copr-lutris-git.” Available at: https://github.com/ProjectSynchro/copr-lutris-git (Accessed: January 18, 2025).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgs-101%2Femacs-master","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgs-101%2Femacs-master","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgs-101%2Femacs-master/lists"}