Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • experimental
  • v2023.2.5-ffs
  • nrb/ex400-remove-wps
  • nrb/airmax-test
  • v2023.2.4-ffs
  • nrb/ar9344-reset-sequence
  • autinerd/experimental-openwrt-24.10
  • v2023.2.3-ffs
  • v2023.2.2-ffs
  • v2023.2-ffs
  • v2023.1-ffs
  • v2022.1.4-ffs
  • feature/addMikrotikwAP
  • v2022.1.3-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • master
  • v2021.1.1-ffs
  • nrb/gluon-master-cpe510
  • v2021.1-ffs
  • v2020.2.3-ffs
  • nrbffs/fastd-remove-delay
  • v2020.2.2-ffs
  • v2020.2.1-ffs
  • v2020.2-ffs
  • v2020.1.3-ffs
  • v2020.1.1-ffs
  • v2020.1-ffs
  • v2019.1.2-ffs
  • v2019.1.1-ffs
  • nrb/test-radv-filter
  • v2019.1-ffs
  • nrbffs/netgear-ex6120
  • v2018.2.3-ffs
  • 0x4A6F-rpi4
  • 0x4A6F-master
  • v2018.2.2-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
137 results

Target

Select target project
  • firmware / FFS Gluon
  • 0x4A6F / FFS Gluon
  • Patrick / FFS Gluon
3 results
Select Git revision
  • 0x4A6F-rpi4
  • 0x4A6F-master
  • master
  • v2018.2.2-ffs
  • v2018.2.x
  • v2016.2.4-batmanbug
  • radv-filterd
  • v2016.2.x
  • hoodselector
  • v2016.1.x
  • babel
  • v2015.1.x
  • 2014.4.x
  • 2014.3.x
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
56 results
Show changes
954 files
+ 39600
16817
Compare changes
  • Side-by-side
  • Inline

Files

.ecrc

0 → 100644
+3 −0
Original line number Diff line number Diff line
{
  "Exclude": ["docs/_build"]
}

.editorconfig

0 → 100644
+67 −0
Original line number Diff line number Diff line
# Top-most EditorConfig file
root = true

[*]
end_of_line = lf
insert_final_newline = true
indent_style = tab
charset = utf-8

[Dockerfile]
indent_style = space
indent_size = 4

[/patches/**]
indent_style = unset
indent_size = unset

[*.c]

[*.css]

[*.dia]
indent_style = space
indent_size = 2

[*.h]

[*.html]

[*.js]

[*{.json,.ecrc}]
indent_style = space
indent_size = 2

[*.lua]

[{Makefile,*.mk}]
indent_style = unset

[*.md]
indent_style = space
indent_size = 4

[*.pl]

[*.py]
indent_style = space
indent_size = 4

[*.rst]
indent_style = space
indent_size = 2

[*.sh]

[*.yml]
indent_style = space
indent_size = 2

[CMakeLists.txt]
indent_style = space
indent_size = 2

[{docs,contrib/ci}/*site*/**/*.conf]
indent_style = space
indent_size = 2
+71 −0
Original line number Diff line number Diff line
---
name: Bug report
about: Report a bug in a recent version of Gluon
label: bug
---

<!--

Please carefully fill out the questionnaire below to help improve the
timely triaging of issues. Walk through the questions below and use
them as an inspiration for what information you can provide.

Make use of codeblocks (three backticks before and after) where
appropriate (configuration excerpts, log output, etc.). Example:

```
your code goes here
```

You can use the "Preview" tab to check how your issue is going to look
before you actually send it in.

Thank you for taking the time to report a bug with the Gluon project.

-->

### Bug report

**What is the problem?**
<!--
- What is not working as expected?
- How is it misbehaving?
- When did the problem first start showing up?
- What were you doing when you first noticed the problem?
- On which devices (vendor, model and revision) is it misbehaving?
- Does the issue appear on multiple devices or targets?
-->

**What is the expected behaviour?**
<!--
- How do you think it should work instead?
- Did it work like that before?
-->

**Gluon Version:**
<!--
Please provide a usable Git reference before applying custom patches:

By using a Git reference:
    $ git describe --always
    v2018.2-17-g3abadc28

Or the URL to the relevant Gluon commit
    https://github.com/freifunk-gluon/gluon/commit/<commit hash here>
-->

**Site Configuration:**
<!--
Please provide the URL to your site configuration repository and the
explicit commit used to build the firmware experiencing the problem.

Additionally excerpts of problem-related configuration parts are 
often helpful.
-->

**Custom patches:**
<!--
Be upfront about any custom patches you have applied to your Gluon build, as they might
be part of your problem.
-->

.github/dependabot.yml

0 → 100644
+12 −0
Original line number Diff line number Diff line
# Docs: <https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/customizing-dependency-updates>

version: 2

updates:
  - package-ecosystem: github-actions
    directory: /
    schedule: {interval: monthly}

  - package-ecosystem: pip
    directory: /docs/
    schedule: {interval: monthly}

.github/filters.yml

0 → 100644
+345 −0
Original line number Diff line number Diff line
{
  "armsr-armv7": [
    "targets/armsr-armv7",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/armsr.inc"
  ],
  "armsr-armv8": [
    "targets/armsr-armv8",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/armsr.inc"
  ],
  "ath79-generic": [
    "targets/ath79-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ath79-nand": [
    "targets/ath79-nand",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ath79-mikrotik": [
    "targets/ath79-mikrotik",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/mikrotik.inc"
  ],
  "bcm27xx-bcm2708": [
    "targets/bcm27xx-bcm2708",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "bcm27xx-bcm2709": [
    "targets/bcm27xx-bcm2709",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "ipq40xx-generic": [
    "targets/ipq40xx-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ipq40xx-mikrotik": [
    "targets/ipq40xx-mikrotik",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/mikrotik.inc"
  ],
  "ipq806x-generic": [
    "targets/ipq806x-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "lantiq-xrx200": [
    "targets/lantiq-xrx200",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "lantiq-xrx200_legacy": [
    "targets/lantiq-xrx200_legacy",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "lantiq-xway": [
    "targets/lantiq-xway",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mediatek-filogic": [
    "targets/mediatek-filogic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mediatek-mt7622": [
    "targets/mediatek-mt7622",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mvebu-cortexa53": [
    "targets/mvebu-cortexa53",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mpc85xx-p1010": [
    "targets/mpc85xx-p1010",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mpc85xx-p1020": [
    "targets/mpc85xx-p1020",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "qualcommax-ipq807x": [
    "targets/qualcommax-ipq807x",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ramips-mt7620": [
    "targets/ramips-mt7620",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ramips-mt7621": [
    "targets/ramips-mt7621",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "ramips-mt76x8": [
    "targets/ramips-mt76x8",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "rockchip-armv8": [
    "targets/rockchip-armv8",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "sunxi-cortexa7": [
    "targets/sunxi-cortexa7",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "x86-generic": [
    "targets/x86-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/x86.inc"
  ],
  "x86-geode": [
    "targets/x86-geode",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "x86-legacy": [
    "targets/x86-legacy",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/x86.inc"
  ],
  "x86-64": [
    "targets/x86-64",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/x86.inc",
    "contrib/ci/minimal-site/**",
    "package/**"
  ],
  "bcm27xx-bcm2710": [
    "targets/bcm27xx-bcm2710",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "bcm27xx-bcm2711": [
    "targets/bcm27xx-bcm2711",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
    "targets/bcm27xx.inc"
  ],
  "ipq40xx-chromium": [
    "targets/ipq40xx-chromium",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "kirkwood-generic": [
    "targets/kirkwood-generic",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ],
  "mvebu-cortexa9": [
    "targets/mvebu-cortexa9",
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk"
  ]
}

.github/labeler.yml

0 → 100644
+89 −0
Original line number Diff line number Diff line
---
"3. topic: batman-adv":
  - changed-files:
    - any-glob-to-any-file:
      - docs/package/gluon-mesh-batman-adv*
      - package/gluon-alfred/**
      - package/gluon-client-bridge/**
      - package/gluon-mesh-batman-adv/**
      - package/libbatadv/**
"3. topic: build":
  - changed-files:
    - any-glob-to-any-file:
      - Makefile
      - scripts/**
"3. topic: config-mode":
  - changed-files:
    - any-glob-to-any-file:
      - docs/dev/web/config-mode.rst
      - docs/package/gluon-config-mode-*
      - package/gluon-config-mode-*/**
      - package/gluon-web*/**
"3. topic: continuous integration":
  - changed-files:
    - any-glob-to-any-file:
      - .github/workflows/*
      - contrib/actions/**
      - contrib/ci/**
"3. topic: docs":
  - changed-files:
    - any-glob-to-any-file:
      - docs/**
"3. topic: fastd":
  - changed-files:
    - any-glob-to-any-file:
      - docs/features/fastd*
      - package/gluon-mesh-vpn-fastd/**
"3. topic: firewall":
  - changed-files:
    - any-glob-to-any-file:
      - package/**/*-firewall
      - package/gluon-ebtables-*/**
"3. topic: hardware":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-core/luasrc/lib/gluon/upgrade/010-primary-mac
      - package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua
      - targets/*
"3. topic: multidomain":
  - changed-files:
    - any-glob-to-any-file:
      - docs/features/multidomain*
      - docs/multidomain-site-example/**
      - package/gluon-config-mode-domain-select/**
      - package/gluon-scheduled-domain-switch/**
"3. topic: olsr":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-l3roamd/**
      - package/gluon-mesh-olsrd/**
      - package/gluon-mmfd/**
"3. topic: package":
  - changed-files:
    - any-glob-to-any-file:
      - package/**
"3. topic: respondd":
  - changed-files:
    - any-glob-to-any-file:
      - package/**/*respondd*
      - package/gluon-respondd/**
"3. topic: status-page":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-status-page/**
"3. topic: tests":
  - changed-files:
    - any-glob-to-any-file:
      - tests/**
"3. topic: wireguard":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-mesh-vpn-wireguard/**
"3. topic: wireless":
  - changed-files:
    - any-glob-to-any-file:
      - package/gluon-mesh-wireless-sae/**
      - package/gluon-private-wifi/**
      - package/gluon-web-private-wifi/**
      - package/gluon-web-wifi-config/**
      - package/gluon-wireless-encryption-wpa3/**
+20 −0
Original line number Diff line number Diff line
name: Backport
on:
  pull_request_target:
    types: [closed, labeled]
permissions:
  contents: write # so it can comment
  pull-requests: write # so it can create pull requests
jobs:
  backport:
    name: Backport Pull Request
    if: github.repository_owner == 'freifunk-gluon' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Create backport PRs
        uses: korthout/backport-action@v3.3.0
        with:
          # Config README: https://github.com/korthout/backport-action#backport-action
          pull_description: |-
            Automatic backport to `${target_branch}`, triggered by a label in #${pull_number}.
+48 −0
Original line number Diff line number Diff line
# Based on the example from https://docs.github.com/en/actions/publishing-packages/publishing-docker-images
name: Create and publish a Docker image

on:
  push:
    branches:
      - 'main'
      - 'next'
      - 'v202[0-9].[0-9].x'
    tags:
      - 'v*'
  pull_request:

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}-build

jobs:
  build-and-push-image:
    runs-on: ubuntu-22.04
    permissions: write-all
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Log in to the Container registry
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
        if: ${{ github.repository_owner == 'freifunk-gluon' && github.event_name == 'push' }}
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
      - name: Build and push Docker image
        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
        with:
          context: ./contrib/docker
          push: ${{ github.repository_owner == 'freifunk-gluon' && github.event_name == 'push' }}
          platforms: linux/amd64,linux/arm64
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
+29 −0
Original line number Diff line number Diff line
name: Build Documentation
on:
  push:
    paths:
      - 'docs/**'
      - '.github/workflows/build-docs.yml'
  pull_request:
    types: [opened, synchronize, reopened]
    paths:
      - 'docs**/'
      - '.github/workflows/build-docs.yml'
permissions:
  contents: read

jobs:
  build-documentation:
    name: docs
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo pip3 install -r docs/requirements.txt
      - name: Build documentation
        run: make -C docs html
      - name: Archive build output
        uses: actions/upload-artifact@v4
        with:
          name: docs_output
          path: docs/_build/html
+80 −0
Original line number Diff line number Diff line
name: Build Gluon
on:
  push:
    branches:
      - main
      - next
      - 'v20[2-9][0-9].[0-9].x'
  pull_request:
    types: [opened, synchronize, reopened]
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ github.event.pull_request.number || github.run_id }}
  cancel-in-progress: true

jobs:
  changed:
    permissions:
      contents: read  # for dorny/paths-filter to fetch a list of changed files
      pull-requests: read  # for dorny/paths-filter to read pull requests
    runs-on: ubuntu-22.04
    outputs:
      targets: ${{ steps.filter.outputs.changes }}
    steps:
      - uses: actions/checkout@v5

      # Filter targets based on changed files
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: .github/filters.yml

  build_firmware:
    needs: changed
    if: ${{ needs.changed.outputs.targets != '[]' && needs.changed.outputs.targets != '' }}
    strategy:
      fail-fast: false
      matrix:
        # Read back changed targets to create build matrix
        target: ${{ fromJSON(needs.changed.outputs.targets) }}
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5

      - name: Show system information
        run: contrib/actions/show-system-info.sh

      - name: Remove non-required software
        run: contrib/actions/free-runner-space.sh

      - name: Build Docker container
        run: docker build -t gluon-ci-container contrib/docker

      - name: Build Gluon
        run: docker run --rm -v $PWD:/gluon-ci -w /gluon-ci --user "$(id -u):$(id -g)" gluon-ci-container contrib/actions/run-build.sh ${{ matrix.target }}

      - name: Check Image size
        run: contrib/check-image-size.py --github-actions --overhead 256 output/meta/openwrt-profiles/${{ matrix.target }}.json

      - name: Archive build logs
        if: ${{ !cancelled() }}
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.target }}_logs
          path: openwrt/logs

      - name: Archive build output
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.target }}_output
          path: output

      - name: Archive metadata
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.target }}_metadata
          path: output/meta
+51 −0
Original line number Diff line number Diff line
---
name: "Update OpenWrt base"

on:
  workflow_dispatch:
    inputs:
      branch:
        description: "Branch to create update for"
        required: true
        default: "main"

jobs:
  update-openwrt:
    runs-on: ubuntu-22.04
    env:
      COMMIT_NAME: Gluon CI Bot
      COMMIT_EMAIL: bot@freifunk-gluon.github.io
    steps:
      - name: Clone Gluon
        uses: actions/checkout@v5
        with:
          ref: ${{ github.event.inputs.branch }}
      
      - name: Configure Git User and E-Mail
        run: git config --global user.name "${{ env.COMMIT_NAME }}" && git config --global user.email "${{ env.COMMIT_EMAIL }}"
      
      - name: Get update branch name
        id: branch-name
        run: echo "branch-name=update-openwrt-${{ github.event.inputs.branch }}-$(date +%s)" >> $GITHUB_OUTPUT

      - name: Link example Site
        run: ln -s docs/site-example site
      
      - name: Invoke update-modules
        run: make update-modules
      
      - name: Refresh patches
        run: make refresh-patches
      
      - name: Check if unstaged commits exist
        run: git diff --exit-code || echo "::warning::Patches need a manual refresh"
      
      - name: Checkout individual branch name
        run: git checkout -b ${{ steps.branch-name.outputs.branch-name }}
      
      - name: Push branch
        run: git push origin HEAD

      - name: Emit PR creation message
        run:
          echo "::notice::Create pull-request at https://github.com/${{ github.repository }}/compare/${{ github.event.inputs.branch }}...${{ steps.branch-name.outputs.branch-name }}?quick_pull=1"
+22 −0
Original line number Diff line number Diff line
name: Check generated CI
on:
  push:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read

jobs:
  check-ci:
    name: Check generated CI
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Update CI
        run: make update-ci
      - name: Show diff
        run: git status; git diff
      - name: Patch status
        run: git diff-files --quiet
+30 −0
Original line number Diff line number Diff line
---
name: Check patches
on:
  push:
    paths:
      - 'modules'
      - 'patches/**'
      - '.github/workflows/check-patches.yml'
  pull_request:
    types: [opened, synchronize, reopened]
    paths:
      - 'modules'
      - 'patches/**'
      - '.github/workflows/check-patches.yml'
permissions:
  contents: read

jobs:
  check-patches:
    name: Check patches
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Refresh patches
        run: make refresh-patches GLUON_SITEDIR="contrib/ci/minimal-site"
      - name: Show diff
        run: git status; git diff
      - name: Patch status
        run: git diff-files --quiet
+21 −0
Original line number Diff line number Diff line
name: "Label PRs"

on:
  # only execute base branch actions
  pull_request_target:

permissions:
  contents: read

jobs:
  labels:
    permissions:
      contents: read  # for actions/labeler to determine modified files
      pull-requests: write  # for actions/labeler to add labels to PRs
    runs-on: ubuntu-22.04
    if: github.repository_owner == 'freifunk-gluon'
    steps:
    - uses: actions/labeler@v6
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        sync-labels: true
+54 −0
Original line number Diff line number Diff line
name: Lint
on:
  push:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read

jobs:
  lua:
    name: Lua
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo apt-get -y update && sudo apt-get -y install lua-check
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Lint Lua code
        run: make lint-lua

  sh:
    name: Shell
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo apt-get -y update && sudo apt-get -y install shellcheck
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Lint shell code
        run: make lint-sh

  editorconfig:
    name: Editorconfig
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v5
      - name: Install Dependencies
        run: sudo apt install curl tar
      - name: Install editorconfig-checker
        env:
          VERSION: 2.7.0
          OS: linux
          ARCH: amd64
        run: |
          curl -O -L -C - https://github.com/editorconfig-checker/editorconfig-checker/releases/download/$VERSION/ec-$OS-$ARCH.tar.gz
          tar xzf ec-$OS-$ARCH.tar.gz
          sudo mv ./bin/ec-$OS-$ARCH /usr/bin/editorconfig-checker
          sudo chmod +x /usr/bin/editorconfig-checker
      - name: Install example site
        run: ln -s ./docs/site-example ./site
      - name: Lint editorconfig
        run: make lint-editorconfig
+5 −1
Original line number Diff line number Diff line
*~
/lede
/openwrt
/output
/site
/tmp
/packages
.bash_history
.subversion
.wget-hsts
/.scmversion

.luacheckrc

0 → 100644
+119 −0
Original line number Diff line number Diff line
codes = true
std = "min"
self = false

read_globals = {
	"getfenv",
	"setfenv",
	"unpack",
}

include_files = {
	"**/*.lua",
	"package/**/luasrc/**/*",
	"targets/*",
	"package/features",
}

exclude_files = {
	"**/*.mk",
}

files["package/**/check_site.lua"] = {
	read_globals = {
		"alternatives",
		"extend",
		"in_domain",
		"in_site",
		"value",
		"need",
		"need_alphanumeric_key",
		"need_array",
		"need_array_elements_exclusive",
		"need_array_of",
		"need_boolean",
		"need_chanlist",
		"need_domain_name",
		"need_number",
		"need_number_range",
		"need_one_of",
		"need_string",
		"need_string_array",
		"need_string_array_match",
		"need_string_match",
		"need_table",
		"need_value",
		"obsolete",
		"table_keys",
		"this_domain",
	},
}

files["package/**/luasrc/lib/gluon/config-mode/*"] = {
	globals = {
		"MultiListValue",
		"DynamicList",
		"Flag",
		"Form",
		"i18n",
		"ListValue",
		"renderer.render",
		"renderer.render_string",
		"Section",
		"TextValue",
		"_translate",
		"translate",
		"translatef",
		"Value",
		"Element",
	},
}

files["package/**/luasrc/lib/gluon/**/controller/*"] = {
	read_globals = {
		"_",
		"alias",
		"call",
		"entry",
		"model",
		"node",
		"template",
	},
}

files["package/**/luasrc/lib/gluon/ebtables/*"] = {
	read_globals = {
		"chain",
		"rule",
	},
	max_line_length = false,
}

files["targets/*"] = {
	read_globals = {
		"class",
		"config",
		"defaults",
		"device",
		"env",
		"exec",
		"exec_capture",
		"exec_capture_raw",
		"exec_raw",
		"factory_image",
		"include",
		"istrue",
		"no_opkg",
		"packages",
		"sysupgrade_image",
		"try_config",
	},
}

files["package/features"] = {
	read_globals = {
		"_",
		"feature",
		"when",
	},
}

.readthedocs.yaml

0 → 100644
+20 −0
Original line number Diff line number Diff line
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Build documentation in the docs/ directory with Sphinx
sphinx:
  configuration: docs/conf.py

# Optionally set the version of Python and requirements required to build your docs
python:
   install:
   - requirements: docs/requirements.txt

build:
    os: ubuntu-22.04
    tools:
        python: "3.11"
+9 −9
Original line number Diff line number Diff line
@@ -23,19 +23,19 @@ using other parts or why the proposed change breaks other parts of the system.
They might even refuse the idea altogether - after all, they have to sleep well
after merging the changes, too.

The preferred way to discuss in the IRC channel ([#gluon] on irc.hackint.org)
or on the [mailing list], however, you can also open a new issue on Github to
The preferred way to discuss is in the IRC channel ([#gluon] on irc.hackint.org)
or on the [mailing list], however, you can also open a new issue on GitHub to
discuss there. We maintain a [list of rejected features] and we'd like to
kindly ask you to review it first. In general, looking for duplicates may save
you some time.

Develop on top of master
------------------------
Develop on top of main
----------------------
If you are not developing something specific to a release (like for example a
security fix to a feature that got completely rewritten since the release),
develop it on top of the master branch. New features and even feature changes
develop it on top of the main branch. New features and even feature changes
aren't usually backported to old releases, but will be included in the upcoming
release, which will be built from master.
release, which will be built from main.

Use descriptive commit messages
-------------------------------
@@ -47,7 +47,7 @@ triggered and what you did to fix it. If in question, have a glance at the
existing commit messages to get the idea.


[packages]: http://gluon.readthedocs.org/en/latest/user/site.html#packages
[#gluon]: https://webirc.hackint.org/#gluon
[packages]: https://gluon.readthedocs.io/en/latest/user/site.html#packages
[#gluon]: https://chat.hackint.org/?join=gluon
[mailing list]: mailto:gluon@luebeck.freifunk.net
[list of rejected features]: https://github.com/freifunk-gluon/gluon/issues?q=label%3Arejected
[list of rejected features]: https://github.com/freifunk-gluon/gluon/issues?q=label%3A%222.+status%3A+rejected%22
+7 −4
Original line number Diff line number Diff line
BSD 2-Clause License

The code of Project Gluon may be distributed under the following terms, unless
noted otherwise in individual files or subtrees.

Copyright (c) 2013-2017, Project Gluon
Copyright (c) Project Gluon
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -25,10 +27,11 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


LEDE and OpenWrt are licensed under the terms of the GNU General Public License
Version 2, which can be found at lede/LICENSE after the lede repository has been
OpenWrt is licensed under the terms of the GNU General Public License Version 2,
which can be found at openwrt/LICENSE after the OpenWrt repository has been
obtained. This applies to the following repositories:
 * lede

 * openwrt
 * packages/openwrt
 * packages/routing
 * packages/luci
+175 −88
Original line number Diff line number Diff line
@@ -4,45 +4,123 @@ LC_ALL:=C
LANG:=C
export LC_ALL LANG

.SHELLFLAGS = -ec

# check for spaces & resolve possibly relative paths
define mkabspath
   ifneq (1,$(words [$($(1))]))
     $$(error $(1) must not contain spaces)
   endif
   override $(1) := $(abspath $($(1)))
endef

GLUON_SITEDIR ?= $(CURDIR)/site
GLUON_TMPDIR ?= $(CURDIR)/tmp

GLUON_OUTPUTDIR ?= $(CURDIR)/output
GLUON_IMAGEDIR ?= $(GLUON_OUTPUTDIR)/images
GLUON_PACKAGEDIR ?= $(GLUON_OUTPUTDIR)/packages

export GLUON_TMPDIR GLUON_IMAGEDIR GLUON_PACKAGEDIR DEVICES
escape = '$(subst ','\'',$(1))'

GLUON_SITEDIR ?= site
$(eval $(call mkabspath,GLUON_SITEDIR))

$(GLUON_SITEDIR)/site.mk:
ifeq ($(realpath $(GLUON_SITEDIR)/site.mk),)
$(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR))
endif

include $(GLUON_SITEDIR)/site.mk


GLUON_RELEASE ?= $(error GLUON_RELEASE not set. GLUON_RELEASE can be set in site.mk or on the command line)

GLUON_DEPRECATED ?= 0

ifneq ($(GLUON_BRANCH),)
  $(warning *** Warning: GLUON_BRANCH has been deprecated, please set GLUON_AUTOUPDATER_BRANCH and GLUON_AUTOUPDATER_ENABLED instead.)
  GLUON_AUTOUPDATER_BRANCH ?= $(GLUON_BRANCH)
  GLUON_AUTOUPDATER_ENABLED ?= 1
endif

export GLUON_RELEASE GLUON_ATH10K_MESH GLUON_REGION GLUON_DEBUG
ifneq ($(GLUON_FEATURES)$(GLUON_FEATURES_standard)$(GLUON_FEATURES_tiny),)
  $(error GLUON_FEATURES is obsolete, please use the image-customization.lua file instead)
endif

ifneq ($(GLUON_SITE_PACKAGES)$(GLUON_SITE_PACKAGES_standard)$(GLUON_SITE_PACKAGES_tiny),)
  $(error GLUON_SITE_PACKAGES is obsolete, please use the image-customization.lua file instead)
endif

GLUON_AUTOUPDATER_ENABLED ?= 0

# initialize (possibly already user set) directory variables
GLUON_TMPDIR ?= tmp
GLUON_OUTPUTDIR ?= output
GLUON_IMAGEDIR ?= $(GLUON_OUTPUTDIR)/images
GLUON_PACKAGEDIR ?= $(GLUON_OUTPUTDIR)/packages
GLUON_DEBUGDIR ?= $(GLUON_OUTPUTDIR)/debug
GLUON_METADIR ?= $(GLUON_OUTPUTDIR)/meta
GLUON_TARGETSDIR ?= targets
GLUON_PATCHESDIR ?= patches

$(eval $(call mkabspath,GLUON_TMPDIR))
$(eval $(call mkabspath,GLUON_OUTPUTDIR))
$(eval $(call mkabspath,GLUON_IMAGEDIR))
$(eval $(call mkabspath,GLUON_PACKAGEDIR))
$(eval $(call mkabspath,GLUON_TARGETSDIR))
$(eval $(call mkabspath,GLUON_PATCHESDIR))

GLUON_VERSION := $(shell scripts/getversion.sh '.')

# Set default SITE_VERSION if not set by user
GLUON_SITE_VERSION ?= $(shell scripts/getversion.sh '$(GLUON_SITEDIR)')

GLUON_MULTIDOMAIN ?= 0
GLUON_AUTOREMOVE ?= 0
GLUON_DEBUG ?= 1
GLUON_MINIFY ?= 1

# Can be overridden via environment/command line/... to use the Gluon
# build system for non-Gluon builds
define GLUON_BASE_FEEDS ?=
src-link gluon_base ../../package
endef

GLUON_VARS = \
	GLUON_VERSION GLUON_SITE_VERSION \
	GLUON_RELEASE GLUON_REGION GLUON_MULTIDOMAIN GLUON_AUTOREMOVE GLUON_DEBUG GLUON_MINIFY GLUON_DEPRECATED \
	GLUON_DEVICES GLUON_TARGETSDIR GLUON_PATCHESDIR GLUON_TMPDIR GLUON_IMAGEDIR GLUON_PACKAGEDIR GLUON_DEBUGDIR \
	GLUON_METADIR GLUON_SITEDIR GLUON_AUTOUPDATER_BRANCH GLUON_AUTOUPDATER_ENABLED GLUON_LANGS GLUON_BASE_FEEDS \
	GLUON_TARGET BOARD SUBTARGET

unexport $(GLUON_VARS)
GLUON_ENV = $(foreach var,$(GLUON_VARS),$(var)=$(call escape,$($(var))))

show-release:
	@echo '$(GLUON_RELEASE)'


update: FORCE
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/update.sh
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/patch.sh
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/feeds.sh
	@
	export $(GLUON_ENV)
	scripts/update.sh
	scripts/patch.sh
	scripts/feeds.sh

update-patches: FORCE
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/update.sh
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/update-patches.sh
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/patch.sh
	@
	export $(GLUON_ENV)
	scripts/update.sh
	scripts/update-patches.sh
	scripts/patch.sh

refresh-patches: FORCE
	@
	export $(GLUON_ENV)
	scripts/update.sh
	scripts/patch.sh
	scripts/update-patches.sh

update-feeds: FORCE
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/feeds.sh
	@$(GLUON_ENV) scripts/feeds.sh

update-modules: FORCE
	@scripts/update-modules.sh

update-ci: FORCE
	@$(GLUON_ENV) scripts/update-ci.sh

GLUON_TARGETS :=

@@ -50,112 +128,121 @@ define GluonTarget
gluon_target := $(1)$$(if $(2),-$(2))
GLUON_TARGETS += $$(gluon_target)
GLUON_TARGET_$$(gluon_target)_BOARD := $(1)
GLUON_TARGET_$$(gluon_target)_SUBTARGET := $(if $(3),$(3),$(2))
GLUON_TARGET_$$(gluon_target)_SUBTARGET := $(2)
endef

include targets/targets.mk
include $(GLUON_TARGETSDIR)/targets.mk


LEDEMAKE = $(MAKE) -C lede
OPENWRTMAKE = $(MAKE) -C openwrt

BOARD := $(GLUON_TARGET_$(GLUON_TARGET)_BOARD)
SUBTARGET := $(GLUON_TARGET_$(GLUON_TARGET)_SUBTARGET)
LEDE_TARGET := $(BOARD)$(if $(SUBTARGET),-$(SUBTARGET))

export LEDE_TARGET

define CheckTarget
	if [ -z '$(BOARD)' ]; then
		echo 'Please set GLUON_TARGET to a valid target. Gluon supports the following targets:'
		for target in $(GLUON_TARGETS); do
			echo " * $$target"
		done
		exit 1
	fi
endef

CheckTarget := [ '$(LEDE_TARGET)' ] \
	|| (echo 'Please set GLUON_TARGET to a valid target. Gluon supports the following targets:'; $(foreach target,$(GLUON_TARGETS),echo ' * $(target)';) false)
define CheckSite
	if ! GLUON_SITEDIR='$(GLUON_SITEDIR)' GLUON_SITE_CONFIG='$(1).conf' $(LUA) -e 'assert(dofile("scripts/site_config.lua")(os.getenv("GLUON_SITE_CONFIG")))'; then
		echo 'Your site configuration ($(1).conf) did not pass validation'
		exit 1
	fi
endef

CheckExternal := test -d lede || (echo 'You don'"'"'t seem to have obtained the external repositories needed by Gluon; please call `make update` first!'; false)
list-targets: FORCE
	@for target in $(GLUON_TARGETS); do
		echo "$$target"
	done

lint: lint-editorconfig lint-lua lint-sh

list-targets: FORCE
	@$(foreach target,$(GLUON_TARGETS),echo '$(target)';)
lint-editorconfig: FORCE
	@scripts/lint-editorconfig.sh

lint-lua: FORCE
	@scripts/lint-lua.sh

GLUON_DEFAULT_PACKAGES := -odhcpd -ppp -ppp-mod-pppoe -wpad-mini gluon-core ip6tables hostapd-mini
lint-sh: FORCE
	@scripts/lint-sh.sh

GLUON_PACKAGES :=
define merge_packages
  $(foreach pkg,$(1),
    GLUON_PACKAGES := $$(strip $$(filter-out -$$(patsubst -%,%,$(pkg)) $$(patsubst -%,%,$(pkg)),$$(GLUON_PACKAGES)) $(pkg))
  )
endef
$(eval $(call merge_packages,$(GLUON_DEFAULT_PACKAGES) $(GLUON_SITE_PACKAGES)))

GLUON_PACKAGES_YES := $(filter-out -%,$(GLUON_PACKAGES))
GLUON_PACKAGES_NO := $(patsubst -%,%,$(filter -%,$(GLUON_PACKAGES)))
LUA := openwrt/staging_dir/hostpkg/bin/lua

$(LUA):
	+@

config: FORCE
	@$(CheckExternal)
	@$(CheckTarget)
	scripts/module_check.sh

	@( \
		echo 'CONFIG_TARGET_$(BOARD)=y' \
		$(if $(SUBTARGET),&& echo 'CONFIG_TARGET_$(BOARD)_$(SUBTARGET)=y') \
		$(foreach pkg,$(GLUON_PACKAGES_NO),&& echo '# CONFIG_PACKAGE_$(pkg) is not set') \
		&& scripts/target_config.sh generic \
		&& GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/target_config.sh '$(GLUON_TARGET)' \
		$(foreach pkg,$(GLUON_PACKAGES_YES),&& echo 'CONFIG_PACKAGE_$(pkg)=y') \
		$(foreach lang,$(GLUON_LANGS),&& echo 'CONFIG_GLUON_WEB_LANG_$(lang)=y') \
		&& echo 'CONFIG_GLUON_RELEASE="$(GLUON_RELEASE)"' \
		&& echo 'CONFIG_GLUON_SITEDIR="$(GLUON_SITEDIR)"' \
		&& echo 'CONFIG_GLUON_BRANCH="$(GLUON_BRANCH)"' \
	) > lede/.config
	+@$(LEDEMAKE) defconfig
	$(GLUON_ENV) scripts/basic_openwrt_config.sh > openwrt/.config
	$(OPENWRTMAKE) defconfig
	$(OPENWRTMAKE) tools/install
	$(OPENWRTMAKE) package/lua/host/compile

	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/target_config_check.sh '$(GLUON_TARGET)' '$(GLUON_PACKAGES_YES)'

config: $(LUA) FORCE
	+@

LUA := lede/staging_dir/hostpkg/bin/lua
	scripts/module_check.sh
	$(CheckTarget)
	$(foreach conf,site $(patsubst $(GLUON_SITEDIR)/%.conf,%,$(wildcard $(GLUON_SITEDIR)/domains/*.conf)),\
		$(call CheckSite,$(conf)); \
	)

$(LUA):
	@$(CheckExternal)
	$(OPENWRTMAKE) prepare-tmpinfo
	$(GLUON_ENV) $(LUA) scripts/target_config.lua > openwrt/.config
	$(OPENWRTMAKE) defconfig
	$(GLUON_ENV) $(LUA) scripts/target_config_check.lua

	+@[ -e lede/.config ] || $(LEDEMAKE) defconfig
	+@$(LEDEMAKE) tools/install
	+@$(LEDEMAKE) package/lua/host/install

prepare-target: config $(LUA) ;
container: FORCE
	@scripts/container.sh

all: prepare-target
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' $(LUA) scripts/site_config.lua \
                || (echo 'Your site configuration did not pass validation.'; false)

	@scripts/clean_output.sh
	+@$(LEDEMAKE)
	@GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/copy_output.sh '$(GLUON_TARGET)'
all: config
	+@
	$(GLUON_ENV) $(LUA) scripts/clean_output.lua
	$(OPENWRTMAKE)
	$(GLUON_ENV) $(LUA) scripts/copy_output.lua

clean download: config
	+@$(LEDEMAKE) $@
	+@$(OPENWRTMAKE) $@

dirclean: FORCE
	+@[ -e lede/.config ] || $(LEDEMAKE) defconfig
	+@$(LEDEMAKE) dirclean
	@rm -rf $(GLUON_TMPDIR) $(GLUON_OUTPUTDIR)
	+@
	[ -e openwrt/.config ] || $(OPENWRTMAKE) defconfig
	$(OPENWRTMAKE) dirclean
	rm -rf $(GLUON_TMPDIR) $(GLUON_OUTPUTDIR)

manifest: $(LUA) FORCE
	@[ '$(GLUON_BRANCH)' ] || (echo 'Please set GLUON_BRANCH to create a manifest.'; false)
	@echo '$(GLUON_PRIORITY)' | grep -qE '^([0-9]*\.)?[0-9]+$$' || (echo 'Please specify a numeric value for GLUON_PRIORITY to create a manifest.'; false)
	@$(CheckExternal)

	@( \
		echo 'BRANCH=$(GLUON_BRANCH)' && \
		echo "DATE=$$($(LUA) scripts/rfc3339date.lua)" && \
		echo 'PRIORITY=$(GLUON_PRIORITY)' && \
		echo && \
		$(foreach GLUON_TARGET,$(GLUON_TARGETS), \
			GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/generate_manifest.sh '$(GLUON_TARGET)' && \
		) : \
	) > 'tmp/$(GLUON_BRANCH).manifest.tmp'

	@mkdir -p '$(GLUON_IMAGEDIR)/sysupgrade'
	@mv 'tmp/$(GLUON_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_BRANCH).manifest'
	@
	[ '$(GLUON_AUTOUPDATER_BRANCH)' ] || (echo 'Please set GLUON_AUTOUPDATER_BRANCH to create a manifest.'; false)
	echo '$(GLUON_PRIORITY)' | grep -qE '^([0-9]*\.)?[0-9]+$$' || (echo 'Please specify a numeric value for GLUON_PRIORITY to create a manifest.'; false)
	scripts/module_check.sh

	(
		export $(GLUON_ENV)
		echo 'BRANCH=$(GLUON_AUTOUPDATER_BRANCH)'
		echo "DATE=$$($(LUA) scripts/rfc3339date.lua)"
		echo 'PRIORITY=$(GLUON_PRIORITY)'
		echo
		for target in $(GLUON_TARGETS); do
			$(LUA) scripts/generate_manifest.lua "$$target"
		done
	) > 'tmp/$(GLUON_AUTOUPDATER_BRANCH).manifest.tmp'

	mkdir -p '$(GLUON_IMAGEDIR)/sysupgrade'
	mv 'tmp/$(GLUON_AUTOUPDATER_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_AUTOUPDATER_BRANCH).manifest'

FORCE: ;

.PHONY: FORCE
.NOTPARALLEL:
.ONESHELL:
+48 −8
Original line number Diff line number Diff line
Documentation (incomplete at this time, contribute if you can!) may be found at
http://gluon.readthedocs.org/.
[![Build Gluon](https://github.com/freifunk-gluon/gluon/actions/workflows/build-gluon.yml/badge.svg?branch=main)](https://github.com/freifunk-gluon/gluon/actions/workflows/build-gluon.yml)
[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/license/bsd-2-clause/)
[![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/freifunk-gluon/gluon?sort=semver)](https://github.com/freifunk-gluon/gluon/releases/latest)

# Gluon

Gluon is a firmware framework to build preconfigured OpenWrt images for public mesh networks.

## Overview

Gluon provides an easy-to-use firmware for a public, decentral WLAN and/or wire based mesh network.
Common network capable devices, like smartphones, laptops or desktop PCs can connect to the mesh network and communicate over it, without the need of passwords for access and without the need of installing special software.
Additionally, internet access and merging mesh clouds can be accomplished over a WAN through VPN connected gateways.

Gluon's features include:

* a decentral mesh network
* easy configuration mode for less techy users
* community-specific technical settings and customizations through a common site.conf and site.mk
* ecdsa signature-based autoupdater
* node status web page
* publication of node information + statistics through respondd
* a variety of preconfigured mesh and VPN protocols:


Supported mesh protocols:

* batman-adv (BATMAN IV fully, BATMAN V partially)
* OLSRv2 (partially)


Supported protocols for node-to-node connections:

* WLAN: 802.11s (with forwarding disabled)
* WAN: VPNs via fastd and Wireguard
* LAN: via VXLAN

## Getting started

We have a huge amount of documentation over at https://gluon.readthedocs.io/.

If you're new to Gluon and ready to get your feet wet, have a look at the
[Getting Started Guide](http://gluon.readthedocs.org/en/latest/user/getting_started.html).
[Getting Started Guide](https://gluon.readthedocs.io/en/latest/user/getting_started.html).

**Gluon IRC channel: `#gluon` in [hackint](http://hackint.org/)**
Gluon's developers frequent an IRC chatroom at [#gluon](ircs://irc.hackint.org/#gluon)
on [hackint](https://hackint.org/). There is also a [webchat](https://chat.hackint.org/?join=gluon)
that allows for uncomplicated access from within your browser. This channel is also available as a bridged Matrix Room at [#gluon:hackint.org](https://matrix.to/#/#gluon:hackint.org).

## Issues & Feature requests

@@ -17,12 +57,12 @@ the future development of Gluon.

## Use a release!

Please refrain from using the `master` branch for anything else but development purposes!
Use the most recent release instead. You can list all relaseses by running `git tag`
and switch to one by running `git checkout v2017.1 && make update`.
Please refrain from using the `main` branch for anything else but development purposes!
Use the most recent release instead. You can list all releases by running `git tag`
and switch to one by running `git checkout v2023.2.5 && make update`.

If you're using the autoupdater, do not autoupdate nodes with anything but releases.
If you upgrade using random master commits the nodes *will break* eventually.
If you upgrade using random main commits the nodes *might break* eventually.

## Mailinglist

+23 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

# For a List of pre-installed packages on the runner image see
# https://github.com/actions/runner-images/tree/main?tab=readme-ov-file#available-images

echo "Disk space before cleanup"
df -h

# Remove packages not required to run the Gluon build CI
sudo apt-get -y remove \
	dotnet-* \
	firefox \
	google-chrome-stable \
	kubectl \
	microsoft-edge-stable \
	temurin-*-jdk

# Remove Android SDK tools
sudo rm -rf /usr/local/lib/android

echo "Disk space after cleanup"
df -h
+54 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3

# Update target filters using
#   make update-ci

import re
import os
import sys
import json

# these changes trigger rebuilds on all targets
common = [
    ".github/workflows/build-gluon.yml",
    "modules",
    "Makefile",
    "patches/**",
    "scripts/**",
    "targets/generic",
    "targets/targets.mk",
]

# these changes are only built on x86-64
extra = [
    "contrib/ci/minimal-site/**",
    "package/**"
]

_filter = dict()

# INCLUDE_PATTERN matches:
# include '...'
# include "..."
# include("...")
# include('...')
INCLUDE_PATTERN = "^\\s*include *\\(? *[\"']([^\"']+)[\"']"

# construct filters map from stdin
for target in sys.stdin:
    target = target.strip()

    _filter[target] = [
        f"targets/{target}"
    ] + common

    target_file = os.path.join(os.environ['GLUON_TARGETSDIR'], target)
    with open(target_file) as f:
        includes = re.findall(INCLUDE_PATTERN, f.read(), re.MULTILINE)
        _filter[target].extend([f"targets/{i}" for i in includes])

    if target == "x86-64":
        _filter[target].extend(extra)

# print filters to stdout in json format, because json is stdlib and yaml compatible.
print(json.dumps(_filter, indent=2))
+17 −0
Original line number Diff line number Diff line
#!/bin/sh

set -e

export BROKEN=1
export GLUON_AUTOREMOVE=1
export GLUON_DEPRECATED=1
export GLUON_SITEDIR="contrib/ci/minimal-site"
export GLUON_TARGET="$1"
export BUILD_LOG=1

BUILD_THREADS="$(($(nproc) + 1))"

echo "Building Gluon with $BUILD_THREADS threads"

make update
make -j$BUILD_THREADS V=s
+16 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash

echo "-- CPU --"
cat /proc/cpuinfo

echo "-- Memory --"
cat /proc/meminfo

echo "-- Disk --"
df -h

echo "-- Kernel --"
uname -a

echo "-- Network --"
ip addr
+146 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3

import argparse
import json
import sys
from enum import Enum

# Enum Class for checking image size
class ImageSizeCheck(Enum):
    OK = "OK"
    TOO_BIG = "TOO_BIG"
    IGNORED = "IGNORED"
    UNKNOWN = "UNKNOWN"


# Some devices pad their images to IMAGE_SIZE and apply a firmware header.
# Exclude this from the image size check.
excluded_devices = [
    "tplink_cpe210-v1",
    "tplink_cpe210-v2",
    "tplink_cpe210-v3",
    "tplink_cpe220-v3",
    "tplink_cpe510-v1",
    "tplink_cpe510-v2",
    "tplink_cpe510-v3",
    "tplink_cpe710-v1",
    "tplink_wbs210-v1",
    "tplink_wbs210-v2",
    "tplink_wbs510-v1"
]


def open_json(file_path):
    with open(file_path, 'r') as f:
        return json.load(f)


def load_openwrt_profile_json(json_path):
    profiles = []
    profile_json = open_json(json_path)
    for profile_name, profile_data in profile_json["profiles"].items():
        device_profile = {
            "name": profile_name,
        }
        if "image" in profile_data.get("file_size_limits", {}):
            device_profile["max_image_size"] = profile_data["file_size_limits"]["image"]

        for image in profile_data["images"]:
            if image["type"] != "sysupgrade":
                continue
            if "size" in image:
                device_profile["image_size"] = image["size"]
        
        profiles.append(device_profile)
    
    return profiles


def check_image_size_below_limit(profile, overhead=0):
    # Skip devices that pad their images
    if profile["name"] in excluded_devices:
        return ImageSizeCheck.IGNORED

    if "max_image_size" in profile and "image_size" in profile:
        if profile["image_size"] + (overhead * 1024) > profile["max_image_size"]:
            return ImageSizeCheck.TOO_BIG
        else:	
            return ImageSizeCheck.OK
    
    return ImageSizeCheck.UNKNOWN


def print_github_actions_warning(message):
    print('::warning::{}'.format(message))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Check image size of OpenWrt profiles')
    parser.add_argument(
        'profile_json',
        help='Path to profile.json',
        nargs='+'
    )
    parser.add_argument(
        '--github-actions',
        help='Generate warnings for use with GitHub Actions',
        action='store_true'
    )
    parser.add_argument(
        '--overhead',
        type=int,
        help='Additional size to add to the image size in kilobyte',
        default=0
    )
    args = parser.parse_args()

    if args.profile_json is None:
        print('Error: profile.json not specified')
        sys.exit(1)
    
    # Load all profile.json files
    profiles = []
    for profile_file in args.profile_json:
        profiles.extend(load_openwrt_profile_json(profile_file))

    # Initialize results with all available ImageSizeCheck values
    results = {}
    for check_result in ImageSizeCheck:
        results[check_result] = []

    for profile in profiles:
        check_result = check_image_size_below_limit(profile, args.overhead)
        results[check_result].append(profile)
    
    for check_result, profiles in results.items():
        if len(profiles) == 0:
            continue

        # Group by result type for GitHub Actions
        if args.github_actions:
            print('::group::{}'.format(check_result.value))

        for profile in profiles:
            if check_result == ImageSizeCheck.TOO_BIG:
                msg = 'Image size of profile {} is too big ({} > {})'.format(
                    profile["name"],
                    profile["image_size"] + (args.overhead * 1024),
                    profile["max_image_size"])
                if args.github_actions:
                    print_github_actions_warning(msg)
                else:
                    print("Warning: {}".format(msg))
            elif check_result == ImageSizeCheck.UNKNOWN:
                msg = 'Image size of profile {} is unknown'.format(
                    profile["name"])
                print(msg)
            elif check_result == ImageSizeCheck.IGNORED:
                msg = 'Image size of profile {} is ignored (Image size {})'.format(
                    profile["name"], profile.get("image_size", "unknown"))
                print(msg)
            else:
                msg = 'Image size of profile {} is OK ({} < {})'.format(
                    profile["name"], 
                    profile["image_size"] + (args.overhead * 1024),
                    profile["max_image_size"])
                print(msg)
+1 −0
Original line number Diff line number Diff line
../../../docs/site-example/i18n/
 No newline at end of file
+16 −0
Original line number Diff line number Diff line
features {
	'autoupdater',
	'ebtables-filter-multicast',
	'ebtables-filter-ra-dhcp',
	'ebtables-limit-arp',
	'mesh-batman-adv-15',
	'mesh-vpn-fastd',
	'respondd',
	'status-page',
	'web-advanced',
	'web-wizard',
}

if not device_class('tiny') then
	features {'wireless-encryption-wpa3'}
end
+1 −0
Original line number Diff line number Diff line
../../../docs/site-example/modules
 No newline at end of file
+180 −0
Original line number Diff line number Diff line
-- This is an example site configuration
--
-- Take a look at the documentation located at
-- https://gluon.readthedocs.io/ for details.
--
-- This configuration will not work as is. You're required to make
-- community specific changes to it!
{
  -- Used for generated hostnames, e.g. freifunk-abcdef123456. (optional)
  -- hostname_prefix = 'freifunk-',

  -- Name of the community.
  site_name = 'Continuous Integration',

  -- Shorthand of the community.
  site_code = 'ci',

  -- 32 bytes of random data, encoded in hexadecimal
  -- This data must be unique among all sites and domains!
  -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' </dev/urandom)
  domain_seed = 'e9608c4ff338b920992d629190e9ff11049de1dfc3f299eac07792dfbcda341c',

  -- Prefixes used within the mesh.
  -- prefix6 is required, prefix4 can be omitted if next_node.ip4
  -- is not set.
  prefix4 = '10.0.0.0/20',
  prefix6 = 'fd::/64',

  -- Timezone of your community.
  -- See https://openwrt.org/docs/guide-user/base-system/system_configuration#time_zones
  timezone = 'CET-1CEST,M3.5.0,M10.5.0/3',

  -- List of NTP servers in your community.
  -- Must be reachable using IPv6!
  --  ntp_servers = {'1.ntp.services.ffxx'},

  -- Wireless regulatory domain of your community.
  regdom = 'DE',

  -- Wireless configuration for 2.4 GHz interfaces.
  wifi24 = {
    -- Wireless channel.
    channel = 1,

    -- ESSIDs used for client network.
    ap = {
      ssid = 'gluon-ci-ssid',
      -- disabled = true, -- (optional)

      -- Configuration for a backward compatible OWE network below.
      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
    },

    mesh = {
      -- Adjust these values!
      id = 'ueH3uXjdp', -- usually you don't want users to connect to this mesh-SSID, so use a cryptic id that no one will accidentally mistake for the client WiFi
      mcast_rate = 12000,
      -- disabled = true, -- (optional)
    },
  },

  -- Wireless configuration for 5 GHz interfaces.
  -- This should be equal to the 2.4 GHz variant, except
  -- for channel.
  wifi5 = {
    channel = 44,
    outdoor_chanlist = '100-140',
    ap = {
      ssid = 'gluon-ci-ssid',
    },
    mesh = {
      -- Adjust these values!
      id = 'ueH3uXjdp',
      mcast_rate = 12000,
    },
  },

  mesh = {
    vxlan = true,
    batman_adv = {
      routing_algo = 'BATMAN_IV',
    },
  },

  -- The next node feature allows clients to always reach the node it is
  -- connected to using a known IP address.
  next_node = {
    -- anycast IPs of all nodes
    -- name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
    ip4 = '10.0.0.1',
    ip6 = 'fd::1',
  },

  -- Options specific to routing protocols (optional)
  -- mesh = {
    -- Options specific to the batman-adv routing protocol (optional)
    -- batman_adv = {
      -- Gateway selection class (optional)
      -- The default class 20 is based on the link quality (TQ) only,
      -- class 1 is calculated from both the TQ and the announced bandwidth
      -- gw_sel_class = 1,
    -- },
  -- },

  mesh_vpn = {
    -- enabled = true,

    fastd = {
      -- Refer to https://fastd.readthedocs.io/en/latest/ to better understand
      -- what these options do.

      -- List of crypto-methods to use.
      methods = {'salsa2012+umac'},
      mtu = 1312,
      -- configurable = true,
      -- syslog_level = 'warn',

      groups = {
        backbone = {
          -- Limit number of connected peers to reduce bandwidth.
          limit = 1,

          -- List of peers.
          peers = {
          },

          -- Optional: nested peer groups
          -- groups = {
            -- backbone_sub = {
              -- ...
            -- },
          -- ...
          -- },
        },
        -- Optional: additional peer groups, possibly with other limits
        -- backbone2 = {
          -- ...
        -- },
      },
    },

    bandwidth_limit = {
      -- The bandwidth limit can be enabled by default here.
      enabled = false,

      -- Default upload limit (kbit/s).
      egress = 200,

      -- Default download limit (kbit/s).
      ingress = 3000,
    },
  },

  autoupdater = {
    -- Default branch (optional), can be overridden by setting GLUON_AUTOUPDATER_BRANCH when building.
    -- Set GLUON_AUTOUPDATER_ENABLED to enable the autoupdater by default for newly installed nodes.
    branch = 'stable',

    -- List of branches. You may define multiple branches.
    branches = {
      stable = {
        name = 'stable',

        -- List of mirrors to fetch images from. IPv6 required!
        mirrors = {'http://1.updates.services.ffhl/stable/sysupgrade'},

        -- Number of good signatures required.
        -- Have multiple maintainers sign your build and only
        -- accept it when a sufficient number of them have
        -- signed it.
        good_signatures = 0,

        -- List of public keys of maintainers.
        pubkeys = {
        },
      },
    },
  },
}
+1 −0
Original line number Diff line number Diff line
../../../docs/site-example/site.mk
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
../minimal-site/i18n
 No newline at end of file
+20 −0
Original line number Diff line number Diff line
features {
	'autoupdater',
	'ebtables-filter-multicast',
	'ebtables-filter-ra-dhcp',
	'ebtables-limit-arp',
	'mesh-olsrd',
	'mesh-vpn-fastd',
	'respondd',
	'status-page',
	'web-advanced',
	'web-wizard',
}

packages {
	'iwinfo',
}

if not device_class('tiny') then
	features {'wireless-encryption-wpa3'}
end
+1 −0
Original line number Diff line number Diff line
../minimal-site/modules
 No newline at end of file
+176 −0
Original line number Diff line number Diff line
-- This is an example site configuration
--
-- Take a look at the documentation located at
-- https://gluon.readthedocs.io/ for details.
--
-- This configuration will not work as is. You're required to make
-- community specific changes to it!
{
  -- Used for generated hostnames, e.g. freifunk-abcdef123456. (optional)
  -- hostname_prefix = 'freifunk-',

  -- Name of the community.
  site_name = 'Continuous Integration',

  -- Shorthand of the community.
  site_code = 'ci',

  -- 32 bytes of random data, encoded in hexadecimal
  -- This data must be unique among all sites and domains!
  -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' </dev/urandom)
  domain_seed = 'e9608c4ff338b920992d629190e9ff11049de1dfc3f299eac07792dfbcda341c',

  -- Prefixes used by clients within the mesh.
  -- prefix6 is required, prefix4 can be omitted if next_node.ip4
  -- is not set.
  prefix6 = 'fdff:cafe:cafe:cafe::/64',

  -- Prefixes used by nodes within the mesh
  node_prefix6 = 'fdff:cafe:cafe:cafe::/64',

  -- Timezone of your community.
  -- See https://openwrt.org/docs/guide-user/base-system/system_configuration#time_zones
  timezone = 'CET-1CEST,M3.5.0,M10.5.0/3',

  -- List of NTP servers in your community.
  -- Must be reachable using IPv6!
  --  ntp_servers = {'1.ntp.services.ffxx'},

  -- Wireless regulatory domain of your community.
  regdom = 'DE',

  -- Wireless configuration for 2.4 GHz interfaces.
  wifi24 = {
    -- Wireless channel.
    channel = 1,

    -- ESSIDs used for client network.
    ap = {
      ssid = 'gluon-ci-ssid',
      -- disabled = true, -- (optional)

      -- Configuration for a backward compatible OWE network below.
      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
    },

    mesh = {
      -- Adjust these values!
      id = 'ueH3uXjdp', -- usually you don't want users to connect to this mesh-SSID, so use a cryptic id that no one will accidentally mistake for the client WiFi
      mcast_rate = 12000,
      -- disabled = true, -- (optional)
    },
  },

  -- Wireless configuration for 5 GHz interfaces.
  -- This should be equal to the 2.4 GHz variant, except
  -- for channel.
  wifi5 = {
    channel = 44,
    outdoor_chanlist = '100-140',
    ap = {
      ssid = 'gluon-ci-ssid',
      -- disabled = true, -- (optional)

      -- Configuration for a backward compatible OWE network below.
      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
    },
    mesh = {
      -- Adjust these values!
      id = 'ueH3uXjdp',
      mcast_rate = 12000,
    },
  },


  -- The next node feature allows clients to always reach the node it is
  -- connected to using a known IP address.
  next_node = {
    -- anycast IPs of all nodes
    name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
    ip4 = '10.0.0.1',
    ip6 = 'fd::1',
  },

  -- Options specific to routing protocols (optional)
  mesh = {
    vxlan = true,
    olsrd = {},
  },

  mesh_vpn = {
    -- enabled = true,

    fastd = {
      -- Refer to https://fastd.readthedocs.io/en/latest/ to better understand
      -- what these options do.

      -- List of crypto-methods to use.
      methods = {'salsa2012+umac'},
      mtu = 1312,
      -- configurable = true,
      -- syslog_level = 'warn',

      groups = {
        backbone = {
          -- Limit number of connected peers to reduce bandwidth.
          limit = 1,

          -- List of peers.
          peers = {
          },

          -- Optional: nested peer groups
          -- groups = {
            -- backbone_sub = {
              -- ...
            -- },
          -- ...
          -- },
        },
        -- Optional: additional peer groups, possibly with other limits
        -- backbone2 = {
          -- ...
        -- },
      },
    },

    bandwidth_limit = {
      -- The bandwidth limit can be enabled by default here.
      enabled = false,

      -- Default upload limit (kbit/s).
      egress = 200,

      -- Default download limit (kbit/s).
      ingress = 3000,
    },
  },

  autoupdater = {
    -- Default branch (optional), can be overridden by setting GLUON_AUTOUPDATER_BRANCH when building.
    -- Set GLUON_AUTOUPDATER_ENABLED to enable the autoupdater by default for newly installed nodes.
    branch = 'stable',

    -- List of branches. You may define multiple branches.
    branches = {
      stable = {
        name = 'stable',

        -- List of mirrors to fetch images from. IPv6 required!
        mirrors = {'http://1.updates.services.ffhl/stable/sysupgrade'},

        -- Number of good signatures required.
        -- Have multiple maintainers sign your build and only
        -- accept it when a sufficient number of them have
        -- signed it.
        good_signatures = 0,

        -- List of public keys of maintainers.
        pubkeys = {
        },
      },
    },
  },
}
+29 −0
Original line number Diff line number Diff line
##	gluon site.mk makefile example

##	DEFAULT_GLUON_RELEASE
#		version string to use for images
#		gluon relies on
#			opkg compare-versions "$1" '>>' "$2"
#		to decide if a version is newer or not.

DEFAULT_GLUON_RELEASE := 0.6+exp$(shell date '+%Y%m%d')

# Variables set with ?= can be overwritten from the command line

##	GLUON_RELEASE
#		call make with custom GLUON_RELEASE flag, to use your own release version scheme.
#		e.g.:
#			$ make images GLUON_RELEASE=23.42+5
#		would generate images named like this:
#			gluon-ff%site_code%-23.42+5-%router_model%.bin

GLUON_RELEASE ?= $(DEFAULT_GLUON_RELEASE)

# Default priority for updates.
GLUON_PRIORITY ?= 0

# Region code required for some images; supported values: us eu
GLUON_REGION ?= eu

# Languages to include
GLUON_LANGS ?= en de
+26 −13
Original line number Diff line number Diff line
#!/bin/bash
#!/usr/bin/env bash

# Script to output the dependency graph of Gluon's packages
# Limitations:
#  * Works only if directory names and package names are the same (true for all Gluon packages)
#  * Doesn't show dependencies through virtual packages correctly



set -e
shopt -s nullglob


@@ -25,19 +23,34 @@ print_dep() {
	echo "$(escape_name "$1") -> $(escape_name "$2");"
}

echo 'digraph G {'

for makefile in ./package/*/Makefile; do
	dir="$(dirname "$makefile")"
	package="$(basename "$dir")"

	deps=$(grep -w DEPENDS "$makefile" | cut -d= -f2 | tr -d +)
print_package() {
	local package="$1" depends="$2"
	# shellcheck disable=SC2086
	set -- $depends

	print_node "$package"
	for dep in $deps; do
	for dep in "$@"; do
		print_node "$dep"
		print_dep "$package" "$dep"
	done
}

make -C openwrt -s prepare-tmpinfo

echo 'digraph G {'

cat ./openwrt/tmp/info/.packageinfo-feeds_gluon_base_* | while read -r key value; do
	case "$key" in
	'Package:')
		package="$value"
		;;
	'Depends:')
		depends="${value//+/}"
		;;
	'@@')
		print_package "$package" "$depends"
		;;
	esac
done | sort -u

popd >/dev/null
+47 −0
Original line number Diff line number Diff line
FROM debian:bookworm-slim

ARG TARGETOS
ARG TARGETARCH

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential \
    ca-certificates \
    clang \
    ecdsautils \
    file \
    gawk \
    git \
    libelf-dev \
    libncurses5-dev \
    libnss-unknown \
    libssl-dev \
    llvm \
    lua-check \
    openssh-client \
    python3 \
    python3-dev \
    python3-pyelftools \
    python3-setuptools \
    qemu-utils \
    rsync \
    shellcheck \
    swig \
    time \
    unzip \
    wget \
    zlib1g-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN mkdir /tmp/ec &&\
    wget -O /tmp/ec/ec-${TARGETOS}-${TARGETARCH}.tar.gz https://github.com/editorconfig-checker/editorconfig-checker/releases/download/2.7.0/ec-${TARGETOS}-${TARGETARCH}.tar.gz &&\
    tar -xvzf /tmp/ec/ec-${TARGETOS}-${TARGETARCH}.tar.gz &&\
    mv bin/ec-${TARGETOS}-${TARGETARCH} /usr/local/bin/editorconfig-checker &&\
    rm -rf /tmp/ec

RUN useradd -m -d /gluon -u 100 -g 100 -o gluon
USER gluon

VOLUME /gluon
WORKDIR /gluon
+3 −3
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ use strict;
use warnings;
use Text::Balanced qw(extract_bracketed extract_delimited extract_tagged);

@ARGV >= 1 || die "Usage: $0 <source direcory>\n";
@ARGV >= 1 || die "Usage: $0 <source directory>\n";


my %stringtable;
@@ -48,7 +48,7 @@ if( open F, "find @ARGV -type f '(' -name '*.html' -o -name '*.lua' ')' |" )

			my $text = $raw;

			while( $text =~ s/ ^ .*? (?:translate|translatef|i18n|_) [\n\s]* \( /(/sgx )
			while( $text =~ s/ ^ .*? (?:translate|translatef|_) [\n\s]* \( /(/sgx )
			{
				( my $code, $text ) = extract_bracketed($text, q{('")});

+8 −8
Original line number Diff line number Diff line
#!/bin/bash
#!/usr/bin/env bash

set -e
# Script to list all upgrade scripts in a clear manner
# Limitations:
#  * Does only show scripts of packages whose `files'/`luasrc' directories represent the whole image filesystem (which are all Gluon packages)
@@ -27,7 +28,7 @@ fi

pushd "$(dirname "$0")/.." >/dev/null

find ./package packages -name Makefile | while read makefile; do
find ./package packages -name Makefile | grep -v '^packages/packages/' | while read -r makefile; do
	dir="$(dirname "$makefile")"

	pushd "$dir" >/dev/null
@@ -36,13 +37,12 @@ find ./package packages -name Makefile | while read makefile; do
	dirname="$(dirname "$dir" | cut -d/ -f 3-)"
	package="$(basename "$dir")"

	for file in "${SUFFIX1}"/*; do
		echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX1})"
	done
	for file in "${SUFFIX2}"/*; do
		echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX2})"
	for file in "${SUFFIX1}"/* "${SUFFIX2}"/*; do
		basename="$(basename "${file}")"
		suffix="$(dirname "${file}")"
		printf "%s\t%s\n" "${basename}" "${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${suffix}/${GREEN}${basename}${RESET}"
	done
	popd >/dev/null
done | sort
done | sort | cut -f2-

popd >/dev/null

contrib/push_pkg.sh

0 → 100755
+149 −0
Original line number Diff line number Diff line
#!/bin/sh

set -e

topdir="$(realpath "$(dirname "${0}")/../openwrt")"

# defaults to qemu run script
ssh_host=localhost
build_only=0
preserve_config=1

print_help() {
	echo "$0 [OPTIONS] PACKAGE_DIR [PACKAGE_DIR] ..."
	echo ""
	echo " -h          print this help"
	echo " -r HOST     use a remote machine as target machine. By default if this"
	echo "             option is not given, push_pkg.sh will use a locally"
	echo "             running qemu instance started by run_qemu.sh."
	echo " -p PORT     use PORT as ssh port (default is 22)"
	echo " -b          build only, do not push"
	echo " -P          do not preserve /etc/config. By default, if a package"
	echo "             defines a config file in /etc/config, this config file"
	echo "             will be preserved. If you specify this flag, the package"
	echo "             default will be installed instead."
	echo ""
	echo ' To change gluon variables, run e.g. "make config GLUON_MINIFY=0"'
	echo ' because then the gluon logic will be triggered, and openwrt/.config'
	echo ' will be regenerated. The variables from openwrt/.config are already'
	echo ' automatically used for this script.'
	echo
}

while getopts "p:r:hbP" opt
do
	case $opt in
		P) preserve_config=0;;
		p) ssh_port="${OPTARG}";;
		r) ssh_host="${OPTARG}"; [ -z "$ssh_port" ] && ssh_port=22;;
		b) build_only=1;;
		h) print_help; exit 0;;
		*) ;;
	esac
done
shift $(( OPTIND - 1 ))

[ -z "$ssh_port" ] && ssh_port=2223

if [ "$build_only" -eq 0 ]; then
	remote_info=$(ssh -p "${ssh_port}" "root@${ssh_host}" '
		source /etc/os-release
		printf "%s\\t%s\\n" "$OPENWRT_BOARD" "$OPENWRT_ARCH"
	')
	REMOTE_OPENWRT_BOARD="$(echo "$remote_info" | cut -f 1)"
	REMOTE_OPENWRT_ARCH="$(echo "$remote_info" | cut -f 2)"

	# check target
	if ! grep -q "CONFIG_TARGET_ARCH_PACKAGES=\"${REMOTE_OPENWRT_ARCH}\"" "${topdir}/.config"; then
		echo "Configured OpenWrt Target is not matching with the target machine!" 1>&2
		echo
		printf "%s" "    Configured architecture: " 1>&2
		grep "CONFIG_TARGET_ARCH_PACKAGES" "${topdir}/.config" 1>&2
		echo "Target machine architecture: ${REMOTE_OPENWRT_ARCH}" 1>&2
		echo 1>&2
		echo "To switch the local with the run with the corresponding GLUON_TARGET:"  1>&2
		echo "  make GLUON_TARGET=... config" 1>&2
		exit 1
	fi
fi

if [ $# -lt 1 ]; then
	echo ERROR: Please specify a PACKAGE_DIR. For example:
	echo
	echo " \$ $0 package/gluon-core"
	exit 1
fi

while [ $# -gt 0 ]; do

	pkgdir="$1"; shift
	echo "Package: ${pkgdir}"

	if ! [ -f "${pkgdir}/Makefile" ]; then
		echo "ERROR: ${pkgdir} does not contain a Makefile"
		exit 1
	fi

	if ! grep -q BuildPackage "${pkgdir}/Makefile"; then
		echo "ERROR: ${pkgdir}/Makefile does not contain a BuildPackage command"
		exit 1
	fi

	opkg_packages="$(make TOPDIR="${topdir}" -C "${pkgdir}" DUMP=1 | awk '/^Package: / { print $2 }')"

	search_package() {
		find "$2" -name "$1_*.ipk" -printf '%f\n'
	}

	make TOPDIR="${topdir}" -C "${pkgdir}" clean
	make TOPDIR="${topdir}" -C "${pkgdir}" compile

	if [ "$build_only" -eq 1 ]; then
		continue
	fi

	# IPv6 addresses need brackets around the ${ssh_host} for scp!
	if echo "${ssh_host}" | grep -q :; then
		BL=[
		BR=]
	fi

	for pkg in ${opkg_packages}; do

		for feed in "${topdir}/bin/packages/${REMOTE_OPENWRT_ARCH}/"*/ "${topdir}/bin/targets/${REMOTE_OPENWRT_BOARD}/packages/"; do
			printf "%s" "searching ${pkg} in ${feed}: "
			filename=$(search_package "${pkg}" "${feed}")
			if [ -n "${filename}" ]; then
				echo found!
				break
			else
				echo not found
			fi
		done

		if [ "$preserve_config" -eq 0 ]; then
			opkg_flags=" --force-maintainer"
		fi

		# shellcheck disable=SC2029
		if [ -n "$filename" ]; then
			scp -O -P "${ssh_port}" "$feed/$filename" "root@${BL}${ssh_host}${BR}:/tmp/${filename}"
			ssh -p "${ssh_port}" "root@${ssh_host}" "
				set -e
				echo Running opkg:
				opkg install --force-reinstall ${opkg_flags} '/tmp/${filename}'
				rm '/tmp/${filename}'
				gluon-reconfigure
			"
		else
			# Some packages (e.g. procd-seccomp) seem to contain BuildPackage commands
			# which do not generate *.ipk files. Till this point, I am not aware why
			# this is happening. However, dropping a warning if the corresponding
			# *.ipk is not found (maybe due to other reasons as well), seems to
			# be more reasonable than aborting. Before this commit, the command
			# has failed.
			echo "Warning: ${pkg}*.ipk not found! Ignoring." 1>&2
		fi

	done
done

contrib/run_qemu.sh

0 → 100755
+15 −0
Original line number Diff line number Diff line
#!/bin/sh

# Note: You can exit the qemu instance by first pressing "CTRL + a" then "c".
#       Then you enter the command mode of qemu and can exit by typing "quit".

qemu-system-x86_64 \
	-d 'cpu_reset' \
	-enable-kvm \
	-gdb tcp::1234 \
	-nographic \
	-netdev user,id=wan,hostfwd=tcp::2223-10.0.2.15:22 \
	-device virtio-net-pci,netdev=wan,addr=0x06,id=nic1 \
	-netdev user,id=lan,hostfwd=tcp::6080-192.168.1.1:80,hostfwd=tcp::2222-192.168.1.1:22,net=192.168.1.100/24 \
	-device virtio-net-pci,netdev=lan,addr=0x05,id=nic2 \
	"$@"
+18 −7
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

set -e

if [ $# -ne 2 -o "-h" = "$1" -o "--help" = "$1" -o ! -r "$1" -o ! -r "$2" ]; then
if [ $# -ne 2 ] || [ "-h" = "$1" ] || [ "--help" = "$1" ] || [ ! -r "$1" ] || [ ! -r "$2" ]; then
	cat <<EOHELP
Usage: $0 <secret> <manifest>

@@ -15,7 +15,7 @@ The script may be performed multiple times to the same document
to indicate an approval by multiple developers.

See also
 * edcsautils on https://github.com/tcatm/ecdsautils
 * ecdsautils on https://github.com/freifunk-gluon/ecdsautils

EOHELP
	exit 1
@@ -29,11 +29,22 @@ lower="$(mktemp)"

trap 'rm -f "$upper" "$lower"' EXIT

awk 'BEGIN    { sep=0 }
     /^---$/ { sep=1; next }
              { if(sep==0) print > "'"$upper"'";
                else       print > "'"$lower"'"}' \
    "$manifest"
awk 'BEGIN    {
	sep = 0
}

/^---$/ {
	sep = 1;
	next
}

{
	if(sep == 0) {
		print > "'"$upper"'"
	} else {
		print > "'"$lower"'"
	}
}' "$manifest"

ecdsasign "$upper" < "$SECRET" >> "$lower"

+26 −15
Original line number Diff line number Diff line
#!/bin/sh

if [ $# -eq 0 -o "-h" = "$1" -o "-help" = "$1" -o "--help" = "$1" ]; then
if [ $# -eq 0 ] || [ "-h" = "$1" ] || [ "-help" = "$1" ] || [ "--help" = "$1" ]; then
	cat <<EOHELP
Usage: $0 <public> <signed manifest>

@@ -8,8 +8,8 @@ sigtest.sh checks if a manifest is signed by the public key <public>. There is
no output, success or failure is indicated via the return code.

See also:
 * ecdsautils in https://github.com/tcatm/ecdsautils
 * http://gluon.readthedocs.org/en/latest/features/autoupdater.html
 * ecdsautils in https://github.com/freifunk-gluon/ecdsautils
 * https://gluon.readthedocs.io/en/latest/features/autoupdater.html

EOHELP
	exit 1
@@ -21,13 +21,24 @@ upper="$(mktemp)"
lower="$(mktemp)"
ret=1

awk "BEGIN    { sep=0 }
    /^---\$/ { sep=1; next }
              { if(sep==0) print > \"$upper\";
                else       print > \"$lower\"}" \
    "$manifest"
awk 'BEGIN    {
	sep = 0
}

while read line
/^---$/ {
	sep = 1;
	next
}

{
	if(sep == 0) {
		print > "'"$upper"'"
	} else {
		print > "'"$lower"'"
	}
}' "$manifest"

while read -r line
do
	if ecdsaverify -s "$line" -p "$public" "$upper"; then
		ret=0
+10 −168
Original line number Diff line number Diff line
# Makefile for Sphinx documentation
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXOPTS    = -W --keep-going
SPHINXBUILD   = sphinx-build
PAPER         =
SOURCEDIR     = .
BUILDDIR      = _build

# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif

# Internal variables.
PAPEROPT_a4     = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .

.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext

# Put it first so that "make" without argument is like "make help".
help:
	@echo "Please use \`make <target>' where <target> is one of"
	@echo "  html       to make standalone HTML files"
	@echo "  dirhtml    to make HTML files named index.html in directories"
	@echo "  singlehtml to make a single large HTML file"
	@echo "  pickle     to make pickle files"
	@echo "  json       to make JSON files"
	@echo "  htmlhelp   to make HTML files and a HTML help project"
	@echo "  qthelp     to make HTML files and a qthelp project"
	@echo "  devhelp    to make HTML files and a Devhelp project"
	@echo "  epub       to make an epub"
	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
	@echo "  text       to make text files"
	@echo "  man        to make manual pages"
	@echo "  texinfo    to make Texinfo files"
	@echo "  info       to make Texinfo files and run them through makeinfo"
	@echo "  gettext    to make PO message catalogs"
	@echo "  changes    to make an overview of all changed/added/deprecated items"
	@echo "  xml        to make Docutils-native XML files"
	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
	@echo "  linkcheck  to check all external links for integrity"
	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"

clean:
	rm -rf $(BUILDDIR)/*

html:
	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

dirhtml:
	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."

singlehtml:
	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
	@echo
	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."

pickle:
	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
	@echo
	@echo "Build finished; now you can process the pickle files."

json:
	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
	@echo
	@echo "Build finished; now you can process the JSON files."

htmlhelp:
	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
	@echo
	@echo "Build finished; now you can run HTML Help Workshop with the" \
	      ".hhp project file in $(BUILDDIR)/htmlhelp."

qthelp:
	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
	@echo
	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Gluon.qhcp"
	@echo "To view the help file:"
	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Gluon.qhc"

devhelp:
	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
	@echo
	@echo "Build finished."
	@echo "To view the help file:"
	@echo "# mkdir -p $$HOME/.local/share/devhelp/Gluon"
	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Gluon"
	@echo "# devhelp"

epub:
	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
	@echo
	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."

latex:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo
	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
	@echo "Run \`make' in that directory to run these through (pdf)latex" \
	      "(use \`make latexpdf' here to do that automatically)."

latexpdf:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo "Running LaTeX files through pdflatex..."
	$(MAKE) -C $(BUILDDIR)/latex all-pdf
	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

latexpdfja:
	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
	@echo "Running LaTeX files through platex and dvipdfmx..."
	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."

text:
	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
	@echo
	@echo "Build finished. The text files are in $(BUILDDIR)/text."

man:
	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
	@echo
	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."

texinfo:
	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
	@echo
	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
	@echo "Run \`make' in that directory to run these through makeinfo" \
	      "(use \`make info' here to do that automatically)."

info:
	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
	@echo "Running Texinfo files through makeinfo..."
	make -C $(BUILDDIR)/texinfo info
	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."

gettext:
	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
	@echo
	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."

changes:
	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
	@echo
	@echo "The overview file is in $(BUILDDIR)/changes."

linkcheck:
	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
	@echo
	@echo "Link check complete; look for any errors in the above output " \
	      "or in $(BUILDDIR)/linkcheck/output.txt."

doctest:
	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
	@echo "Testing of doctests in the sources finished, look at the " \
	      "results in $(BUILDDIR)/doctest/output.txt."
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

xml:
	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
	@echo
	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: help Makefile

pseudoxml:
	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
	@echo
	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+3 −0
Original line number Diff line number Diff line
.strike {
	text-decoration: line-through;
}
+102 −175
Original line number Diff line number Diff line
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Gluon documentation build configuration file, created by
# sphinx-quickstart on Wed Jan 29 00:45:53 2014.
# Configuration file for the Sphinx documentation builder.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config

import sys
import os
# -- Path setup --------------------------------------------------------------