Radish alpha
r
rad:z371PVmDHdjJucejRoRYJcDEvD5pp
Radicle website including documentation and guides
Radicle
Git
blog: Add post about gh actions
Rūdolfs Ošiņš committed 11 months ago
commit 26179eef4e039ae89774f0cc5abd2a89ef51c398
parent eb73d5d
5 files changed +628 -0
added _layouts/blog.html
@@ -0,0 +1,31 @@
+
<!DOCTYPE html>
+
<html lang="{{ site.lang | default: "en-US" }}">
+
  <head>
+
    {% include meta.html %}
+
    <link rel="stylesheet" type="text/css" href="{{ "/assets/css/blog.css" | relative_url }}"/>
+
  </head>
+
  <body>
+
    <header>
+
      <div class="title">
+
        <a href="/">
+
          <img src="{{ "/assets/images/radicle.svg" | relative_url }}" alt="" />
+
          <span>Blog</span>
+
        </a>
+
      </div>
+
      <nav>
+
      </nav>
+
      <button class="toggle" id="toggle-theme"><!-- Set by script --></button>
+
    </header>
+
    <main>
+
      <h1>{{ page.title }}</h1>
+
      <p class="subtitle">{{ page.subtitle }}</p>
+
      <span class="author">Published by <a href="{{page.authorUrl}}">{{page.author}}</a> on {{ page.date | date: "%d.%m.%Y" }}</span>
+
      {% include toc.html html=content class="toc" item_class="toc-h%level%" %}
+
      {{ content }}
+
    </main>
+
    <footer>
+
      <p>&copy; The Radicle Team</p>
+
    </footer>
+
    <script src="{{ "/assets/js/toggle-theme.js" | relative_url }}"></script>
+
  </body>
+
</html>
added _posts/2025-05-30-radicle-with-github-actions.md
@@ -0,0 +1,60 @@
+
---
+
title: "How we used Radicle with GitHub Actions"
+
subtitle: "Quick guide to trying Radicle without dropping GitHub or whatever CI you’re using."
+
author: "rudolfs"
+
authorUrl: "https://app.radicle.xyz/nodes/seed.radicle.garden/users/did:key:z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx"
+
layout: "blog"
+
---
+

+
A chat with [burrito](https://app.radicle.xyz/nodes/seed.radicle.garden/users/did:key:z6MkrubmdTJKR42YZd7yDYysyx4JRez1wmvxjpmhzhTMKxsr) aka [Dietrich Ayala](https://metafluff.com) today sparked the idea to write down how we started dogfooding Radicle before we had our native Radicle CI going. He also encouraged me to just set a deadline for writing blog posts in general, so this had to be written and published by the end of today.
+

+
We wanted to dogfood Radicle as soon as possible, but there was one caveat: we didn't have a solution for CI at the time. So what we did was just reuse our existing GitHub actions and push both to Radicle and GitHub. The code review would happen in Radicle, and GitHub would run our tests. For easy visual indication, we used workflow status badges generated for each branch pushed to GitHub.
+

+
The screenshot below shows how this looks in the Desktop app.
+
<img src="/assets/images/blog/radicle-with-github-actions-screenshot.png" class="screenshot"/>
+

+
The workflow was as simple as:
+

+
1. Create a branch and commit your changes
+
2. Push the changes to GitHub with `git push github rudolfs/breadcrumb-tweak:rudolfs/breadcrumb-tweak`
+
3. Copy the build badge links to your clipboard, see script below
+
4. Open a patch on Radicle via `git push rad HEAD:refs/patches`, paste the build badges into the patch body and submit it
+

+
When we addressed changes from code review and submitted a new revision, we pushed it to both Radicle and GitHub to trigger another build, the badges updated automatically.
+

+
```sh
+
$ git push github rudolfs/breadcrumb-tweak:rudolfs/breadcrumb-tweak
+
$ git push rad
+
```
+

+
The `rad` remote is set up for you automatically when you initialize a project with `rad init`. The GitHub remote can be set up manually via `git remote add github git@github.com:radicle-dev/radicle-interface.git` pointing to a copy of the project which lives on your GitHub account.
+

+
```sh
+
$ git remote -v
+

+
github	git@github.com:radicle-dev/radicle-interface.git (fetch)
+
github	git@github.com:radicle-dev/radicle-interface.git (push)
+
rad	rad://z4V1sjrXqjvFdnCUbxPFqd5p4DtH5 (fetch)
+
rad	rad://z4V1sjrXqjvFdnCUbxPFqd5p4DtH5/z6MkwPUeUS2fJMfc2HZN1RQTQcTTuhw4HhPySB8JeUg2mVvx (push)
+
```
+

+
Bash script that automatically copies the build badge links to the clipboard.
+

+
```bash
+
#!/bin/bash
+
set -euo pipefail
+
branchName=$(git branch --show-current)
+
previewBranchName="${branchName//\//-}"
+
workflowBranchName="${branchName//\//%2F}"
+
# Use a here document to include the text and pipe it to sed
+
sed -e "s|<branchName>|$branchName|g" \
+
  -e "s|<workflowBranchName>|$workflowBranchName|g" \
+
  -e "s|<previewBranchName>|$previewBranchName|g" <<'EOF' | pbcopy
+
![check](https://github.com/radicle-dev/radicle-interface/actions/workflows/check.yml/badge.svg?branch=<branchName>) ![check-visual](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-visual.yml/badge.svg?branch=<branchName>) ![check-unit-test](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-unit-test.yml/badge.svg?branch=<branchName>) ![check-http-client-unit-test](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-http-client-unit-test.yml/badge.svg?branch=<branchName>) ![check-radicle-httpd](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-radicle-httpd.yml/badge.svg?branch=<branchName>) ![check-e2e](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-e2e.yml/badge.svg?branch=<branchName>) ![check-build](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-build.yml/badge.svg?branch=<branchName>) ![check-http](https://github.com/radicle-dev/radicle-interface/actions/workflows/check-radicle-httpd.yml/badge.svg?branch=<branchName>)
+
👉 [Preview](https://radicle-interface-git-<previewBranchName>-radicle.vercel.app)
+
👉 [Workflow runs](https://github.com/radicle-dev/radicle-interface/actions?query=branch%3A<workflowBranchName>)
+
👉 [Branch on GitHub](https://github.com/radicle-dev/radicle-interface/tree/<branchName>)
+
EOF
+
```
+

+
This is how we used to run tests and builds. Now, we're dogfooding [our own CI solution](https://app.radicle.xyz/nodes/ash.radicle.garden/rad:zwTxygwuz5LDGBq255RA2CbNGrz8) together with [Woodpecker](https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z39Cf1XzrvCLRZZJRUZnx9D1fj5ws). If you want to learn more about CI in Radicle, check out the conversations on [Zulip](https://radicle.zulipchat.com/#narrow/channel/452370-radicle-ci).
added assets/css/blog.css
@@ -0,0 +1,533 @@
+
@charset "utf-8";
+
@import "/assets/css/common.css";
+
@import "/assets/css/fonts.css";
+
@import "/assets/css/monokai.css";
+

+
main,
+
footer {
+
  display: grid;
+
  grid-column-gap: 2rem;
+
  grid-auto-flow: row;
+
  grid-template-columns:
+
    [screen-start] 1fr
+
    [page-start kicker-start left-start] 6rem [wide-start] 6rem
+
    [text-start kicker-end] 2rem 3rem 6rem 3rem
+
    [left-end right-start] 3rem [text-middle] 3rem 6rem 2rem
+
    [text-end gutter-start] 6rem [wide-end] 6rem
+
    [page-end gutter-end right-end] 1fr [screen-end];
+
  grid-template-rows: auto [last-row];
+
}
+

+
main {
+
  align-items: first baseline;
+
  padding-bottom: 8rem;
+
}
+

+
header,
+
footer {
+
  font-weight: 300;
+
}
+

+
header {
+
  display: flex;
+
  background-color: var(--color-bg-default);
+
  padding: 1rem 1.5rem;
+
  align-items: center;
+
  justify-content: space-between;
+
}
+

+
footer {
+
  padding-bottom: 3rem;
+
  color: var(--color-fg-dim);
+
}
+

+
footer p {
+
  font-size: var(--font-size-tiny);
+
  display: block;
+
  text-align: left;
+
  grid-column: text;
+
}
+

+
nav {
+
  display: grid;
+
  grid-column: right;
+
  grid-auto-flow: column;
+
  grid-gap: 1.5rem;
+
  align-items: stretch;
+
  justify-self: end;
+
  text-transform: uppercase;
+
}
+

+
header a {
+
  display: flex;
+
  align-items: center;
+
}
+

+
main > *,
+
footer > * {
+
  grid-column: text;
+
}
+

+
footer > *:last-child {
+
  margin-bottom: 0;
+
}
+

+
strong {
+
  font-weight: 600;
+
}
+

+
h1 {
+
  font-size: var(--font-size-xx-large);
+
  font-weight: var(--font-weight-semibold);
+
  margin: 4rem 0 0.5rem;
+
  line-height: 1.25;
+
}
+

+
h2 {
+
  font-size: var(--font-size-x-large);
+
  font-weight: var(--font-weight-semibold);
+
  margin: 3.75rem 0 1.5rem;
+
  padding-bottom: 1rem;
+
  border-bottom: 1px solid var(--color-fill-separator);
+
}
+

+
h3 {
+
  font-size: var(--font-size-large);
+
  font-weight: var(--font-weight-semibold);
+
  margin: 2rem 0 1.5rem;
+
}
+

+
h4 {
+
  font-size: var(--font-size-medium);
+
  font-weight: var(--font-weight-semibold);
+
  margin: 1.5rem 0 1rem;
+
}
+

+
h5 {
+
  font-size: var(--font-size-small);
+
  font-weight: var(--font-weight-semibold);
+
  margin: 1rem 0 0.25rem;
+
}
+

+
pre,
+
code {
+
  line-height: 1.5;
+
  color: var(--color-fg-low-contrast);
+
  font-family: var(--font-family-code);
+
}
+

+
pre {
+
  background-color: var(--color-bg-highlight);
+
  overflow-x: scroll;
+
  font-size: 0.875rem;
+
  border-radius: 4px;
+
  padding: 1rem;
+
  margin: 0;
+
}
+

+
pre code {
+
  background: none !important;
+
  padding: 0;
+
}
+

+
pre.center {
+
  text-align: center;
+
}
+
pre.wide {
+
  margin: 1.5rem auto 2.5rem auto;
+
  padding: 1.5rem;
+
  grid-column-start: wide-start;
+
  grid-column-end: wide-end;
+
}
+

+
p code,
+
ul code,
+
ol code,
+
aside code {
+
  padding: 1px 4px;
+
  border-radius: 2px;
+
  word-spacing: -2px;
+
  background-color: var(--color-fill-separator);
+
}
+

+
strong code {
+
  font-weight: 600 !important;
+
}
+

+
p code {
+
  font-weight: 400;
+
}
+

+
aside code {
+
  font-weight: normal;
+
  color: var(--color-fg-dim);
+
}
+

+
table {
+
  font-size: 0.875rem;
+
  border-collapse: collapse;
+
  background-color: var(--color-bg-highlight);
+
}
+

+
table td:first-child {
+
  white-space: nowrap;
+
  padding-right: 1rem;
+
}
+

+
table td {
+
  vertical-align: top;
+
  padding: 0.5rem;
+
}
+

+
table th {
+
  font-size: var(--font-size-small);
+
  font-weight: var(--font-weight-regular);
+
  background-color: var(--color-fill-separator);
+
  padding: 0.5rem;
+
  text-align: left;
+
}
+

+
table tr {
+
  border-bottom: 1px solid var(--color-fill-separator);
+
}
+

+
table tr:last-child {
+
  border-bottom: none;
+
}
+

+
table code {
+
  font-weight: normal;
+
}
+

+
p:last-child {
+
  margin-bottom: 0;
+
}
+

+
p + blockquote {
+
  margin-top: 1rem;
+
}
+
blockquote + p {
+
  margin-top: 1rem;
+
}
+

+
blockquote {
+
  color: var(--color-fg-low-contrast);
+
  background: var(--color-bg-highlight);
+
  padding: 1rem;
+
  margin: 1rem 0;
+
  border-left: 2px solid var(--color-border-focus);
+
}
+

+
blockquote pre {
+
  background-color: var(--color-fill-separator);
+
}
+

+
.title {
+
  align-items: stretch;
+
  justify-self: start;
+
}
+

+
.title img {
+
  width: 1.75rem;
+
  height: 1.75rem;
+
}
+

+
.title span {
+
  color: var(--color-fg-low-contrast);
+
  margin-left: 0.5rem;
+
}
+

+
.title:hover span {
+
  text-decoration: underline;
+
}
+

+
.toc + hr {
+
  margin-bottom: 3rem;
+
}
+

+
.first {
+
  margin-top: 60px;
+
}
+

+
.author {
+
  font-style: italic;
+
  text-align: right;
+
  margin: 0 0 3rem;
+
  color: var(--color-fg-dim);
+
  font-size: var(--font-size-small);
+
}
+
.author a {
+
  text-decoration: underline;
+
}
+

+
.subtitle {
+
  font-size: 1.125rem;
+
  color: var(--color-fg-dim);
+
  margin: 0;
+
}
+

+
main figure,
+
main img {
+
  margin: 1rem 0 2rem 0;
+
}
+

+
main img,
+
main object {
+
  margin: 0;
+
  padding: 0;
+
  border: 0;
+
  outline: none;
+
}
+

+
main img.placeholder {
+
  width: 100%;
+
  height: 8rem;
+
  border: none !important;
+
  outline: none !important;
+
  background: var(--color-bg-highlight) !important;
+
}
+

+
figure {
+
  width: 100%;
+
}
+

+
figure pre {
+
  margin: 0;
+
}
+

+
li pre {
+
  margin-top: 1rem;
+
  margin-right: 1rem;
+
  padding: 0.75rem;
+
}
+

+
figure img,
+
figure object {
+
  display: block;
+
  margin: 0 auto;
+
}
+

+
figure object + figcaption {
+
  margin-top: 1rem;
+
}
+

+
figure.diagram {
+
  grid-column-start: kicker-start;
+
  grid-column-end: gutter-end;
+
}
+

+
figure.diagram.tall {
+
  grid-column-start: text-start;
+
  grid-column-end: text-end;
+
}
+

+
figcaption {
+
  margin-top: 0.5rem;
+
  width: 100%;
+
  white-space: nowrap;
+
  overflow-x: hidden;
+
  text-align: center;
+
  text-overflow: ellipsis;
+
}
+

+
aside {
+
  grid-column: gutter;
+
}
+

+
aside.span-2 {
+
  grid-row: span 2;
+
}
+
aside.span-3 {
+
  grid-row: span 3;
+
}
+
aside.span-4 {
+
  grid-row: span 4;
+
}
+
aside.span-5 {
+
  grid-row: span 5;
+
}
+

+
aside p {
+
  margin-bottom: 1em;
+
}
+

+
aside a {
+
  text-decoration: none !important;
+
  border-bottom: 1px dotted var(--color-fg-dim);
+
}
+

+
aside.kicker {
+
  grid-column: kicker;
+
}
+

+
aside.diagram {
+
  margin-top: 1.5rem;
+
}
+

+
figcaption,
+
aside {
+
  font-size: 0.75rem;
+
  line-height: 1.5;
+
  color: var(--color-fg-dim);
+
}
+

+
a {
+
  color: unset;
+
  text-decoration: unset;
+
}
+

+
li a,
+
p a {
+
  border-bottom: 1px solid var(--color-fg-dim);
+
}
+
p a:hover {
+
  border-bottom-color: var(--color-fg-contrast);
+
}
+

+
p,
+
ol,
+
ul,
+
table,
+
pre {
+
  margin: 0 0 1rem;
+
}
+

+
ol,
+
ul {
+
  padding-left: 2rem;
+
}
+

+
li {
+
  padding-left: 0.5rem;
+
}
+

+
hr {
+
  grid-column: screen;
+
  width: 100%;
+
  border: none;
+
  border-top: 1px solid var(--color-fill-separator);
+
  margin: 0;
+
}
+

+
span.highlight {
+
  color: var(--color-fg-emphasized);
+
}
+

+
span.highlight-secondary {
+
  color: var(--color-fg-highlight-secondary);
+
}
+

+
.banner {
+
  border-radius: 4px;
+
  width: 100%;
+
}
+

+
.button {
+
  color: var(--color-fill-secondary);
+
  font-weight: normal;
+
  padding: 1rem 2rem;
+
  border: 1px solid var(--color-fill-secondary);
+
  border-radius: 4px;
+
}
+
.button:hover {
+
  color: white;
+
  background-color: var(--color-fill-secondary);
+
}
+

+
.toc {
+
  display: flex;
+
  flex-direction: column;
+
  flex-wrap: wrap;
+
  gap: 1rem;
+
  font-size: 0.75rem !important;
+
  margin: 2rem 0 3rem 0;
+
  padding: 0;
+
  max-height: 18rem;
+
}
+

+
.toc a {
+
  border-bottom-width: 1px;
+
  border-bottom-style: none;
+
}
+
.toc a:hover {
+
  border-bottom-style: solid;
+
}
+

+
.toc code {
+
  font-size: 0.75rem;
+
}
+

+
.toc li,
+
.toc ul {
+
  padding: 0;
+
  margin: 0;
+
  list-style-type: none;
+
}
+

+
.toc-h2 > a {
+
  font-weight: bold !important;
+
}
+
.toc-h2 > ul {
+
  margin-left: 0.5rem;
+
}
+
.toc-h3 > ul {
+
  margin-left: 1rem;
+
}
+
.toc-h3 > a,
+
.toc-h4 > a,
+
.tok-h5 > a {
+
  color: var(--color-fg-dim);
+
}
+

+
.poem {
+
  font-style: italic;
+
  font-size: 0.75rem;
+
  grid-column-start: text-start;
+
  grid-column-end: text-middle;
+
  margin-bottom: 1rem;
+
  padding-left: 2rem;
+
}
+

+
.screenshot {
+
  width: 100%;
+
  margin: 0;
+
}
+

+
@media (max-width: 1280px) {
+
  main,
+
  footer {
+
    grid-column-gap: 1.25rem;
+
  }
+
}
+

+
@media (max-width: 1024px) {
+
  aside,
+
  .poem {
+
    display: none;
+
  }
+

+
  main,
+
  header,
+
  footer {
+
    padding-left: 1rem;
+
    padding-right: 1rem;
+
  }
+
  main,
+
  footer {
+
    max-width: 720px;
+
    margin: 0 auto;
+
    grid-template-columns: [screen-start page-start text-start] 100% [page-end text-end screen-end];
+
  }
+

+
  pre.wide {
+
    grid-column: text !important;
+
    margin-right: 0;
+
    margin-left: 0;
+
  }
+
  figure.diagram {
+
    grid-column: screen !important;
+
  }
+
  figure.diagram object {
+
    width: 100%;
+
  }
+
}
added assets/images/blog/radicle-with-github-actions-screenshot.png
modified index.md
@@ -127,6 +127,10 @@ updated, join our community on 💬 [Zulip][zulip], or <a href="{{ site.feed.pat
[hn]: https://news.ycombinator.com/item?id=39600810
[1.0]: https://twitter.com/radicle/status/1772659708978991605

+
## Blog
+

+
- 30.05.2025 [How we used Radicle with GitHub Actions](/2025/05/30/radicle-with-github-actions.html)
+

# Feedback

If you have feedback, join our [Zulip][zulip] or send us an email at