Compare commits
4
Commits
acb7532a4f
..
v0.8.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f3793d468c | ||
|
|
dbfb104d89 | ||
|
|
125f9027c4 | ||
|
|
fe043711a0 |
@@ -0,0 +1,39 @@
|
|||||||
|
# Builds the Das OS packages and both ISO images on the CI host (see ci/runner).
|
||||||
|
# Build output stays on the host in DASOS_OUT, set in the runner's config.
|
||||||
|
# A v* tag also publishes the images as a release (ci/release.sh).
|
||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, dev]
|
||||||
|
tags: ["v*"]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: build-${{ gitea.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: dasci
|
||||||
|
permissions:
|
||||||
|
contents: write # ci/release.sh creates releases
|
||||||
|
steps:
|
||||||
|
- uses: builtin:checkout
|
||||||
|
|
||||||
|
# One make run builds the packages once for both images.
|
||||||
|
# Go tests run inside the das-tools and das-theme package builds.
|
||||||
|
- name: Packages and ISO images
|
||||||
|
run: make iso iso-server
|
||||||
|
|
||||||
|
- name: Result
|
||||||
|
run: ls -lh "$DASOS_OUT/iso/"*-"$(cat VERSION)"-x86_64.iso
|
||||||
|
|
||||||
|
# A v* tag publishes both images and their checksums as a release
|
||||||
|
- name: Release
|
||||||
|
if: startsWith(gitea.ref, 'refs/tags/v')
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ gitea.token }}
|
||||||
|
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||||
|
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||||
|
run: ci/release.sh "${{ gitea.ref_name }}" "$DASOS_OUT/iso"
|
||||||
@@ -40,5 +40,5 @@ test:
|
|||||||
|
|
||||||
# Build output may be owned by root when a build was interrupted, so remove it from the container
|
# Build output may be owned by root when a build was interrupted, so remove it from the container
|
||||||
clean:
|
clean:
|
||||||
scripts/builder.sh rm -rf /work/out/hostdir/binpkgs /work/out/iso
|
scripts/builder.sh rm -rf /work/out/hostdir/binpkgs /work/out/hostdir/stamps /work/out/iso
|
||||||
rm -rf out/qemu
|
rm -rf out/qemu
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
## Das OS
|
## Das OS
|
||||||
### _A light, friendly Void Linux–based desktop with Xfce and a Ukrainian touch, plus a console server edition_
|
### _A light, friendly Void Linux–based desktop with Xfce and a Ukrainian touch, plus a console server edition_
|
||||||
|
|
||||||
[](https://voidlinux.org) [](https://xfce.org) [](https://docs.voidlinux.org/config/services/) [](https://go.dev) [](https://www.docker.com) [](#)
|
[](https://voidlinux.org) [](https://xfce.org) [](https://docs.voidlinux.org/config/services/) [](https://go.dev) [](https://www.docker.com) [](#)
|
||||||
|
|
||||||
🇺🇦 [Українська версія](README_ua.md)
|
🇺🇦 [Українська версія](README_ua.md)
|
||||||
|
|
||||||
@@ -13,13 +13,15 @@ Void Linux is fast, simple and independent: runit instead of systemd, and its ow
|
|||||||
- [Graphical installer](#Installer) (Calamares) set up for Void and runit
|
- [Graphical installer](#Installer) (Calamares) set up for Void and runit
|
||||||
- [Snapshots and rollback](#Snapshots): hourly Btrfs snapshots, bootable from the GRUB menu
|
- [Snapshots and rollback](#Snapshots): hourly Btrfs snapshots, bootable from the GRUB menu
|
||||||
- [System update](#Update) with a snapshot taken before it: a window, a tray icon and a terminal mode
|
- [System update](#Update) with a snapshot taken before it: a window, a tray icon and a terminal mode
|
||||||
- [Welcome window](#Welcome) at the first login: language, home folders, updates and help
|
- [Welcome window](#Welcome) at the first login: language, home folders, updates, the developer profile and help
|
||||||
- [Server image](#Server): a console live ISO with a text installer, SSH, firewall, fail2ban and Docker
|
- [Server image](#Server): a console live ISO with a text installer, SSH, firewall, fail2ban and Docker
|
||||||
- [Command-line helpers](#Helpers) for everyday admin tasks: services (`dsv`), users (`duser`), firewall (`dfw`) and system settings (`dsys`)
|
- [Command-line helpers](#Helpers) for everyday admin tasks: services (`dsv`), users (`duser`), firewall (`dfw`) and system settings (`dsys`)
|
||||||
|
- [Developer profile](#DevProfile) in one command: Go, Python, Node.js, Docker, rootless Podman, VS Code and IDEs from Flathub
|
||||||
- [Das OS look](#Look): light and dark themes, generated window frames, wallpapers and logo
|
- [Das OS look](#Look): light and dark themes, generated window frames, wallpapers and logo
|
||||||
- [Desktop defaults](#Defaults) for Xfce that don't overwrite stock files
|
- [Desktop defaults](#Defaults) for Xfce that don't overwrite stock files
|
||||||
- [Own package repository](#Repository) built by xbps-src from in-tree templates
|
- [Own package repository](#Repository) built by xbps-src from in-tree templates
|
||||||
- [Containerised build](#Build) that runs on any Linux host with Docker, and QEMU scripts for testing
|
- [Containerised build](#Build) that runs on any Linux host with Docker, and QEMU scripts for testing
|
||||||
|
- [CI build](#CI) of the packages and both ISOs on every push, on a self-hosted Gitea Actions runner
|
||||||
|
|
||||||
### ⭐ Advantages
|
### ⭐ Advantages
|
||||||
- **Void underneath** – a fast runit boot, the xbps package manager and fresh software, with none of the manual setup.
|
- **Void underneath** – a fast runit boot, the xbps package manager and fresh software, with none of the manual setup.
|
||||||
@@ -119,6 +121,7 @@ Void Linux is fast, simple and independent: runit instead of systemd, and its ow
|
|||||||
- In the live session it offers to install Das OS.
|
- In the live session it offers to install Das OS.
|
||||||
- The interface language can be chosen when the system has more than one locale built. It is stored in AccountsService and `~/.dmrc` and takes effect at the next login.
|
- The interface language can be chosen when the system has more than one locale built. It is stored in AccountsService and `~/.dmrc` and takes effect at the next login.
|
||||||
- If the home folders still have English names (`Documents`, `Downloads`…), it offers to rename them to the system language, together with `user-dirs.dirs` and the file manager bookmarks. Folders the user moved, and those whose new name is already taken, are left alone.
|
- If the home folders still have English names (`Documents`, `Downloads`…), it offers to rename them to the system language, together with `user-dirs.dirs` and the file manager bookmarks. Folders the user moved, and those whose new name is already taken, are left alone.
|
||||||
|
- It installs the [developer profile](#DevProfile) in a terminal window, where the IDEs and the password are asked for, and once the profile is installed, adds IDEs from Flathub.
|
||||||
- It links to the system update, Xfce settings and help.
|
- It links to the system update, Xfce settings and help.
|
||||||
- It opens by itself only once. The *Show at login* check box keeps it opening at every login.
|
- It opens by itself only once. The *Show at login* check box keeps it opening at every login.
|
||||||
|
|
||||||
@@ -143,6 +146,15 @@ Void Linux is fast, simple and independent: runit instead of systemd, and its ow
|
|||||||
- `dsys` replaces hostnamectl, timedatectl and localectl: `info` (time sync, language, console, addresses), `hostname`, `timezone` (part of the name will do: `dsys timezone Kyiv`), `locale` (builds the glibc locale if needed) and `keymap` (with a Cyrillic console font for Cyrillic layouts).
|
- `dsys` replaces hostnamectl, timedatectl and localectl: `info` (time sync, language, console, addresses), `hostname`, `timezone` (part of the name will do: `dsys timezone Kyiv`), `locale` (builds the glibc locale if needed) and `keymap` (with a Cyrillic console font for Cyrillic layouts).
|
||||||
- They come in the `das-helpers` package and are on the desktop too. Both images also include `xtools-minimal` from Void for package work: `xi` installs, `xrs` searches, `xq` shows package details and `xcheckrestart` finds programs to restart after an update.
|
- They come in the `das-helpers` package and are on the desktop too. Both images also include `xtools-minimal` from Void for package work: `xi` installs, `xrs` searches, `xq` shows package details and `xcheckrestart` finds programs to restart after an update.
|
||||||
|
|
||||||
|
#### Developer profile<a id='DevProfile' />
|
||||||
|
**_`dprofile install dev` turns a desktop or a server into a development machine, with a snapshot taken before it._**
|
||||||
|
- Packages from the Void repository: `base-devel`, gdb, strace, Git with LFS, GitHub CLI, lazygit, Go with gopls, delve and golangci-lint, Python with pip, virtualenv and uv, Node.js, Docker with Compose and Buildx, lazydocker, Podman with podman-compose, jq, ripgrep, fd, fzf, direnv, shellcheck and SQLite.
|
||||||
|
- On a desktop also VS Code (Void's open-source build `code-oss`, extensions come from Open VSX), Meld, Flatpak with the Flathub remote and the desktop portals.
|
||||||
|
- It enables Docker and adds the user who runs it to the `docker` group, gives them subordinate IDs for rootless Podman and makes `/` a shared mount at every boot (`/etc/runit/core-services/60-das-shared-root.sh`), which rootless containers need.
|
||||||
|
- Before installing, it asks which IDEs to add from Flathub: Android Studio, IntelliJ IDEA Open and Ultimate, PyCharm, GoLand, WebStorm or Microsoft's Visual Studio Code. Later they are added with `dprofile app add GoLand` and removed with `dprofile app rm`, which also removes the Flatpak runtimes nothing else uses.
|
||||||
|
- The packages are installed between a snapper pre/post snapshot pair, like with `das-update`, and the command prints how to roll back. `dprofile list` and `dprofile show dev` show what is installed already; `--yes` and `--apps ID,...|all|none` make it work without questions.
|
||||||
|
- The profile is a plain list in `/usr/share/das/profiles/dev.conf`. The desktop installer doesn't offer it because the installation copies the live image without a network, and the profile downloads about 550 MB of packages (an IDE from Flathub takes 1–4 GB more with its runtimes).
|
||||||
|
|
||||||
#### Das OS look<a id='Look' />
|
#### Das OS look<a id='Look' />
|
||||||
**_A modern minimal style with a blue and yellow eight-petal star from Ukrainian embroidery._**
|
**_A modern minimal style with a blue and yellow eight-petal star from Ukrainian embroidery._**
|
||||||
- The GTK themes `DasOS` and `DasOS-Dark` build on adw-gtk3 and add the Das OS accent colours. They also style the Xfce panel, which adw-gtk3 leaves black.
|
- The GTK themes `DasOS` and `DasOS-Dark` build on adw-gtk3 and add the Das OS accent colours. They also style the Xfce panel, which adw-gtk3 leaves black.
|
||||||
@@ -165,9 +177,10 @@ Void Linux is fast, simple and independent: runit instead of systemd, and its ow
|
|||||||
- `srcpkgs/das-tools` contains `das-welcome` and the update window and tray icon (Go, GTK 3 through gotk3) with their menu and autostart entries. Its subpackage `das-update` is the update command and polkit action, without GTK.
|
- `srcpkgs/das-tools` contains `das-welcome` and the update window and tray icon (Go, GTK 3 through gotk3) with their menu and autostart entries. Its subpackage `das-update` is the update command and polkit action, without GTK.
|
||||||
- `srcpkgs/das-snapshots` contains the snapper configuration, `das-snapper-setup` and the dracut module for booting snapshots.
|
- `srcpkgs/das-snapshots` contains the snapper configuration, `das-snapper-setup` and the dracut module for booting snapshots.
|
||||||
- `srcpkgs/das-installer` contains the Calamares settings and branding, `srcpkgs/das-server-installer` the console installer. The steps both share (`mount-source`, `postinstall`) are in `srcpkgs/das-install-common`. They exist only on the live ISOs.
|
- `srcpkgs/das-installer` contains the Calamares settings and branding, `srcpkgs/das-server-installer` the console installer. The steps both share (`mount-source`, `postinstall`) are in `srcpkgs/das-install-common`. They exist only on the live ISOs.
|
||||||
- `srcpkgs/das-server` is the server metapackage with the nftables, fail2ban, sshd and Docker defaults. `srcpkgs/das-helpers` contains `dsv`, `duser`, `dfw` and `dsys`.
|
- `srcpkgs/das-server` is the server metapackage with the nftables, fail2ban, sshd and Docker defaults. `srcpkgs/das-helpers` contains `dsv`, `duser`, `dfw`, `dsys`, `dprofile` and the profiles.
|
||||||
- `srcpkgs/calamares`, `srcpkgs/adw-gtk3` and `srcpkgs/font-jetbrains-mono` package upstream releases that Void does not have.
|
- `srcpkgs/calamares`, `srcpkgs/adw-gtk3` and `srcpkgs/font-jetbrains-mono` package upstream releases that Void does not have.
|
||||||
- `make packages` lays the templates over a shallow clone of void-packages and builds them with `xbps-src` into `out/hostdir/binpkgs`. The ISO build installs them from there.
|
- `make packages` lays the templates over a shallow clone of void-packages and builds them with `xbps-src` into `out/hostdir/binpkgs`. The ISO build installs them from there.
|
||||||
|
- A package is rebuilt only when its directory in `srcpkgs/` changed, its binary package is missing, or Void no longer provides a shared library it links to (checked with a dry-run install). `DASOS_REBUILD=1 make packages` rebuilds everything.
|
||||||
|
|
||||||
#### Containerised build<a id='Build' />
|
#### Containerised build<a id='Build' />
|
||||||
**_The whole build runs in a Docker container, so only Docker and QEMU are needed on the host._**
|
**_The whole build runs in a Docker container, so only Docker and QEMU are needed on the host._**
|
||||||
@@ -175,6 +188,14 @@ Void Linux is fast, simple and independent: runit instead of systemd, and its ow
|
|||||||
2. `make iso` builds the packages and then the ISO with `void-mklive`, using the profile in `live/` (package list, services, root file system overlay). `make iso-server` does the same for the server profile in `server/`.
|
2. `make iso` builds the packages and then the ISO with `void-mklive`, using the profile in `live/` (package list, services, root file system overlay). `make iso-server` does the same for the server profile in `server/`.
|
||||||
3. `make qemu` boots the newest ISO with UEFI. `make qemu-bios` uses legacy BIOS, and `make qemu-disk` also attaches a 20 GB virtual disk to install on. `make qemu-server` boots the server ISO with the disk on a serial console in the terminal (Ctrl-A X quits).
|
3. `make qemu` boots the newest ISO with UEFI. `make qemu-bios` uses legacy BIOS, and `make qemu-disk` also attaches a 20 GB virtual disk to install on. `make qemu-server` boots the server ISO with the disk on a serial console in the terminal (Ctrl-A X quits).
|
||||||
|
|
||||||
|
#### CI build<a id='CI' />
|
||||||
|
**_Every push to `main` or `dev` and every `v*` tag builds the packages and both ISOs on git.das.org.ua._**
|
||||||
|
- The workflow `.gitea/workflows/build.yml` runs `make iso iso-server` on a self-hosted runner with the `dasci` label.
|
||||||
|
- The runner is a WSL2 distro on a Windows machine: Ubuntu 24.04 with Docker Engine and `gitea-runner` as a systemd service. A scheduled task starts it when Windows boots, no login needed.
|
||||||
|
- `ci/runner/setup.sh` installs Docker, the runner and its `config.yaml`; `setup.sh register <token>` registers it, `autostart.ps1` creates the scheduled task.
|
||||||
|
- `DASOS_OUT` moves `out/` out of the checkout, so void-packages, the bootstrapped masterdir and the download cache survive between builds.
|
||||||
|
- A `v*` tag that matches `VERSION` also publishes both ISOs and `SHA256SUMS` as a release (`ci/release.sh`, with the job's own token): `git tag v0.8.0 && git push origin v0.8.0`. Other builds keep the ISOs on the CI host in `/var/lib/dasos-ci/out/iso`.
|
||||||
|
|
||||||
### 🚀 Building the application
|
### 🚀 Building the application
|
||||||
Requirements: Linux with Docker (the user must be in the `docker` group), QEMU and OVMF for testing, and Go 1.24+ with the GTK 3 development files for `make test`. About 10 GB of free disk space.
|
Requirements: Linux with Docker (the user must be in the `docker` group), QEMU and OVMF for testing, and Go 1.24+ with the GTK 3 development files for `make test`. About 10 GB of free disk space.
|
||||||
```shell
|
```shell
|
||||||
@@ -187,6 +208,6 @@ make clean # remove build output, keep the download cache
|
|||||||
```
|
```
|
||||||
The ISOs appear in `out/iso/dasos-<version>-x86_64.iso` and `out/iso/dasos-server-<version>-x86_64.iso`. Write them to a USB stick with `dd` or Ventoy.
|
The ISOs appear in `out/iso/dasos-<version>-x86_64.iso` and `out/iso/dasos-server-<version>-x86_64.iso`. Write them to a USB stick with `dd` or Ventoy.
|
||||||
|
|
||||||
**Note:** Das OS is an early version (0.5.0). The developer profile and signed repository hosting are planned for upcoming stages. Until the repository is hosted, an installed system gets updates from Void only. Das OS is based on Void Linux but is not affiliated with it.
|
**Note:** Das OS is an early version (0.8.0). Packages and ISOs are built in CI; signed repository hosting is planned for an upcoming stage. Until the repository is hosted, an installed system gets updates from Void only. Das OS is based on Void Linux but is not affiliated with it.
|
||||||
|
|
||||||
###### _Made by -=:dAs:=-_
|
###### _Made by -=:dAs:=-_
|
||||||
|
|||||||
+25
-4
@@ -1,7 +1,7 @@
|
|||||||
## Das OS
|
## Das OS
|
||||||
### _Легкий і дружній десктоп на базі Void Linux з Xfce та українським колоритом, а також консольна серверна версія_
|
### _Легкий і дружній десктоп на базі Void Linux з Xfce та українським колоритом, а також консольна серверна версія_
|
||||||
|
|
||||||
[](https://voidlinux.org) [](https://xfce.org) [](https://docs.voidlinux.org/config/services/) [](https://go.dev) [](https://www.docker.com) [](#)
|
[](https://voidlinux.org) [](https://xfce.org) [](https://docs.voidlinux.org/config/services/) [](https://go.dev) [](https://www.docker.com) [](#)
|
||||||
|
|
||||||
🇬🇧 [English version](README.md)
|
🇬🇧 [English version](README.md)
|
||||||
|
|
||||||
@@ -13,13 +13,15 @@ Void Linux швидкий, простий і незалежний: runit зам
|
|||||||
- [Графічний інсталятор](#Installer) Calamares, налаштований під Void і runit
|
- [Графічний інсталятор](#Installer) Calamares, налаштований під Void і runit
|
||||||
- [Знімки й відкат](#Snapshots): щогодинні знімки Btrfs, які можна завантажити з меню GRUB
|
- [Знімки й відкат](#Snapshots): щогодинні знімки Btrfs, які можна завантажити з меню GRUB
|
||||||
- [Оновлення системи](#Update) зі знімком перед ним: вікно, значок у треї та консольний режим
|
- [Оновлення системи](#Update) зі знімком перед ним: вікно, значок у треї та консольний режим
|
||||||
- [Вікно привітання](#Welcome) під час першого входу: мова, теки, оновлення та довідка
|
- [Вікно привітання](#Welcome) під час першого входу: мова, теки, оновлення, профіль розробника та довідка
|
||||||
- [Серверний образ](#Server): консольний live ISO з текстовим інсталятором, SSH, файрволом, fail2ban і Docker
|
- [Серверний образ](#Server): консольний live ISO з текстовим інсталятором, SSH, файрволом, fail2ban і Docker
|
||||||
- [Консольні помічники](#Helpers) для щоденного адміністрування: служби (`dsv`), користувачі (`duser`), брандмауер (`dfw`) і системні налаштування (`dsys`)
|
- [Консольні помічники](#Helpers) для щоденного адміністрування: служби (`dsv`), користувачі (`duser`), брандмауер (`dfw`) і системні налаштування (`dsys`)
|
||||||
|
- [Профіль розробника](#DevProfile) однією командою: Go, Python, Node.js, Docker, rootless Podman, VS Code і середовища з Flathub
|
||||||
- [Оформлення Das OS](#Look): світла й темна теми, згенеровані рамки вікон, шпалери та логотип
|
- [Оформлення Das OS](#Look): світла й темна теми, згенеровані рамки вікон, шпалери та логотип
|
||||||
- [Налаштування за замовчуванням](#Defaults) для Xfce, які не перезаписують стандартні файли
|
- [Налаштування за замовчуванням](#Defaults) для Xfce, які не перезаписують стандартні файли
|
||||||
- [Власний репозиторій пакетів](#Repository), який xbps-src збирає з шаблонів у дереві проєкту
|
- [Власний репозиторій пакетів](#Repository), який xbps-src збирає з шаблонів у дереві проєкту
|
||||||
- [Збирання в контейнері](#Build), яке працює на будь-якому Linux із Docker, і скрипти QEMU для тестування
|
- [Збирання в контейнері](#Build), яке працює на будь-якому Linux із Docker, і скрипти QEMU для тестування
|
||||||
|
- [Збирання в CI](#CI) пакетів і обох ISO після кожного push на власному runner Gitea Actions
|
||||||
|
|
||||||
### ⭐ Переваги
|
### ⭐ Переваги
|
||||||
- **Void усередині** – швидке завантаження з runit, менеджер пакетів xbps і свіжі програми без ручного налаштування.
|
- **Void усередині** – швидке завантаження з runit, менеджер пакетів xbps і свіжі програми без ручного налаштування.
|
||||||
@@ -119,6 +121,7 @@ Void Linux швидкий, простий і незалежний: runit зам
|
|||||||
- У live-сесії пропонує встановити Das OS.
|
- У live-сесії пропонує встановити Das OS.
|
||||||
- Мову інтерфейсу можна вибрати, якщо в системі зібрано більше однієї локалі. Вона зберігається в AccountsService і `~/.dmrc` і діє з наступного входу.
|
- Мову інтерфейсу можна вибрати, якщо в системі зібрано більше однієї локалі. Вона зберігається в AccountsService і `~/.dmrc` і діє з наступного входу.
|
||||||
- Якщо теки домашнього каталогу лишилися з англійськими назвами (`Documents`, `Downloads`…), пропонує перейменувати їх мовою системи разом із `user-dirs.dirs` і закладками файлового менеджера. Теки, які користувач переніс, і ті, чия нова назва вже зайнята, не чіпає.
|
- Якщо теки домашнього каталогу лишилися з англійськими назвами (`Documents`, `Downloads`…), пропонує перейменувати їх мовою системи разом із `user-dirs.dirs` і закладками файлового менеджера. Теки, які користувач переніс, і ті, чия нова назва вже зайнята, не чіпає.
|
||||||
|
- Встановлює [профіль розробника](#DevProfile) у вікні термінала, де питає про середовища й пароль, а коли профіль встановлено, додає середовища з Flathub.
|
||||||
- Містить посилання на оновлення системи, налаштування Xfce і довідку.
|
- Містить посилання на оновлення системи, налаштування Xfce і довідку.
|
||||||
- Сам відкривається лише один раз. Прапорець *Показувати під час входу* залишає його на кожен вхід.
|
- Сам відкривається лише один раз. Прапорець *Показувати під час входу* залишає його на кожен вхід.
|
||||||
|
|
||||||
@@ -143,6 +146,15 @@ Void Linux швидкий, простий і незалежний: runit зам
|
|||||||
- `dsys` замінює hostnamectl, timedatectl і localectl: `info` (синхронізація часу, мова, консоль, адреси), `hostname`, `timezone` (досить частини назви: `dsys timezone Kyiv`), `locale` (збирає локаль glibc, якщо треба) і `keymap` (з кириличним шрифтом консолі для кириличних розкладок).
|
- `dsys` замінює hostnamectl, timedatectl і localectl: `info` (синхронізація часу, мова, консоль, адреси), `hostname`, `timezone` (досить частини назви: `dsys timezone Kyiv`), `locale` (збирає локаль glibc, якщо треба) і `keymap` (з кириличним шрифтом консолі для кириличних розкладок).
|
||||||
- Вони входять у пакет `das-helpers` і є й на десктопі. Обидва образи також містять `xtools-minimal` з Void для роботи з пакетами: `xi` встановлює, `xrs` шукає, `xq` показує відомості про пакет, а `xcheckrestart` знаходить програми, які треба перезапустити після оновлення.
|
- Вони входять у пакет `das-helpers` і є й на десктопі. Обидва образи також містять `xtools-minimal` з Void для роботи з пакетами: `xi` встановлює, `xrs` шукає, `xq` показує відомості про пакет, а `xcheckrestart` знаходить програми, які треба перезапустити після оновлення.
|
||||||
|
|
||||||
|
#### Профіль розробника<a id='DevProfile' />
|
||||||
|
**_`dprofile install dev` перетворює десктоп чи сервер на машину для розробки, перед цим створивши знімок системи._**
|
||||||
|
- Пакети з репозиторію Void: `base-devel`, gdb, strace, Git з LFS, GitHub CLI, lazygit, Go з gopls, delve і golangci-lint, Python з pip, virtualenv і uv, Node.js, Docker з Compose і Buildx, lazydocker, Podman з podman-compose, jq, ripgrep, fd, fzf, direnv, shellcheck і SQLite.
|
||||||
|
- На десктопі ще VS Code (відкрита збірка Void `code-oss`, розширення з Open VSX), Meld, Flatpak з репозиторієм Flathub і порталами робочого столу.
|
||||||
|
- Вмикає Docker і додає користувача, який його запустив, до групи `docker`, дає йому підлеглі ідентифікатори для rootless Podman і під час кожного завантаження робить `/` спільним монтуванням (`/etc/runit/core-services/60-das-shared-root.sh`), без чого rootless-контейнери працюють з попередженнями.
|
||||||
|
- Перед встановленням питає, які середовища додати з Flathub: Android Studio, IntelliJ IDEA Open та Ultimate, PyCharm, GoLand, WebStorm чи Visual Studio Code від Microsoft. Пізніше їх додає `dprofile app add GoLand`, а видаляє `dprofile app rm`, разом із рантаймами Flatpak, які більше нічому не потрібні.
|
||||||
|
- Пакети встановлюються між парою знімків snapper pre/post, як і в `das-update`, а наприкінці команда підказує, як відкотитися. `dprofile list` і `dprofile show dev` показують, що вже встановлено; з `--yes` і `--apps ID,...|all|none` команда працює без запитань.
|
||||||
|
- Профіль — звичайний список у `/usr/share/das/profiles/dev.conf`. Десктопний інсталятор його не пропонує: встановлення копіює live-образ без мережі, а профіль завантажує близько 550 МБ пакетів (середовище з Flathub разом із рантаймами — ще 1–4 ГБ).
|
||||||
|
|
||||||
#### Оформлення Das OS<a id='Look' />
|
#### Оформлення Das OS<a id='Look' />
|
||||||
**_Сучасний мінімалізм із синьо-жовтою восьмипелюстковою зіркою з української вишивки._**
|
**_Сучасний мінімалізм із синьо-жовтою восьмипелюстковою зіркою з української вишивки._**
|
||||||
- GTK-теми `DasOS` і `DasOS-Dark` побудовані на adw-gtk3 і додають акцентні кольори Das OS. Вони також оформлюють панель Xfce, яку adw-gtk3 лишає чорною.
|
- GTK-теми `DasOS` і `DasOS-Dark` побудовані на adw-gtk3 і додають акцентні кольори Das OS. Вони також оформлюють панель Xfce, яку adw-gtk3 лишає чорною.
|
||||||
@@ -165,9 +177,10 @@ Void Linux швидкий, простий і незалежний: runit зам
|
|||||||
- `srcpkgs/das-tools` містить `das-welcome`, вікно оновлення і значок у треї (Go, GTK 3 через gotk3) з пунктами меню й автозапуском. Його підпакет `das-update` — сама команда оновлення й дія polkit, без GTK.
|
- `srcpkgs/das-tools` містить `das-welcome`, вікно оновлення і значок у треї (Go, GTK 3 через gotk3) з пунктами меню й автозапуском. Його підпакет `das-update` — сама команда оновлення й дія polkit, без GTK.
|
||||||
- `srcpkgs/das-snapshots` містить конфігурацію snapper, `das-snapper-setup` і dracut-модуль для завантаження знімків.
|
- `srcpkgs/das-snapshots` містить конфігурацію snapper, `das-snapper-setup` і dracut-модуль для завантаження знімків.
|
||||||
- `srcpkgs/das-installer` містить налаштування й брендинг Calamares, `srcpkgs/das-server-installer` — консольний інсталятор. Спільні для обох кроки (`mount-source`, `postinstall`) лежать у `srcpkgs/das-install-common`. Вони є лише на live-ISO.
|
- `srcpkgs/das-installer` містить налаштування й брендинг Calamares, `srcpkgs/das-server-installer` — консольний інсталятор. Спільні для обох кроки (`mount-source`, `postinstall`) лежать у `srcpkgs/das-install-common`. Вони є лише на live-ISO.
|
||||||
- `srcpkgs/das-server` — серверний метапакет із налаштуваннями nftables, fail2ban, sshd і Docker. `srcpkgs/das-helpers` містить `dsv`, `duser`, `dfw` і `dsys`.
|
- `srcpkgs/das-server` — серверний метапакет із налаштуваннями nftables, fail2ban, sshd і Docker. `srcpkgs/das-helpers` містить `dsv`, `duser`, `dfw`, `dsys`, `dprofile` і профілі.
|
||||||
- `srcpkgs/calamares`, `srcpkgs/adw-gtk3` і `srcpkgs/font-jetbrains-mono` пакують релізи, яких немає у Void.
|
- `srcpkgs/calamares`, `srcpkgs/adw-gtk3` і `srcpkgs/font-jetbrains-mono` пакують релізи, яких немає у Void.
|
||||||
- `make packages` накладає шаблони на неглибокий клон void-packages і збирає їх через `xbps-src` в `out/hostdir/binpkgs`. Збирання ISO встановлює їх звідти.
|
- `make packages` накладає шаблони на неглибокий клон void-packages і збирає їх через `xbps-src` в `out/hostdir/binpkgs`. Збирання ISO встановлює їх звідти.
|
||||||
|
- Пакет перезбирається, лише коли змінився його каталог у `srcpkgs/`, зник бінарний пакет або Void більше не надає бібліотеку, з якою він зібраний (перевіряється пробним встановленням). `DASOS_REBUILD=1 make packages` перезбирає все.
|
||||||
|
|
||||||
#### Збирання в контейнері<a id='Build' />
|
#### Збирання в контейнері<a id='Build' />
|
||||||
**_Усе збирання відбувається в Docker-контейнері, тож на хості потрібні лише Docker і QEMU._**
|
**_Усе збирання відбувається в Docker-контейнері, тож на хості потрібні лише Docker і QEMU._**
|
||||||
@@ -175,6 +188,14 @@ Void Linux швидкий, простий і незалежний: runit зам
|
|||||||
2. `make iso` збирає пакети, а потім ISO через `void-mklive` за профілем у `live/` (список пакетів, сервіси, оверлей кореневої файлової системи). `make iso-server` робить те саме для серверного профілю в `server/`.
|
2. `make iso` збирає пакети, а потім ISO через `void-mklive` за профілем у `live/` (список пакетів, сервіси, оверлей кореневої файлової системи). `make iso-server` робить те саме для серверного профілю в `server/`.
|
||||||
3. `make qemu` завантажує найновіший ISO з UEFI. `make qemu-bios` використовує старий BIOS, а `make qemu-disk` ще й підключає віртуальний диск на 20 ГБ для встановлення. `make qemu-server` завантажує серверний ISO з диском на послідовній консолі прямо в терміналі (вихід — Ctrl-A X).
|
3. `make qemu` завантажує найновіший ISO з UEFI. `make qemu-bios` використовує старий BIOS, а `make qemu-disk` ще й підключає віртуальний диск на 20 ГБ для встановлення. `make qemu-server` завантажує серверний ISO з диском на послідовній консолі прямо в терміналі (вихід — Ctrl-A X).
|
||||||
|
|
||||||
|
#### Збирання в CI<a id='CI' />
|
||||||
|
**_Кожен push у `main` чи `dev` і кожен тег `v*` збирає пакети й обидва ISO на git.das.org.ua._**
|
||||||
|
- Workflow `.gitea/workflows/build.yml` запускає `make iso iso-server` на власному runner з міткою `dasci`.
|
||||||
|
- Runner — дистрибутив WSL2 на Windows-машині: Ubuntu 24.04 з Docker Engine і `gitea-runner` як службою systemd. Завдання планувальника запускає його під час завантаження Windows, вхід у систему не потрібен.
|
||||||
|
- `ci/runner/setup.sh` встановлює Docker, runner і його `config.yaml`; `setup.sh register <токен>` реєструє його, `autostart.ps1` створює завдання планувальника.
|
||||||
|
- `DASOS_OUT` виносить `out/` за межі робочої копії, тож void-packages, підготовлений masterdir і кеш завантажень зберігаються між збираннями.
|
||||||
|
- Тег `v*`, що збігається з `VERSION`, ще й публікує обидва ISO та `SHA256SUMS` як реліз (`ci/release.sh`, з власним токеном завдання): `git tag v0.8.0 && git push origin v0.8.0`. Інші збирання залишають ISO на CI-хості в `/var/lib/dasos-ci/out/iso`.
|
||||||
|
|
||||||
### 🚀 Збирання застосунку
|
### 🚀 Збирання застосунку
|
||||||
Вимоги: Linux із Docker (користувач має бути в групі `docker`), QEMU та OVMF для тестування, Go 1.24+ і файли розробки GTK 3 для `make test`. Приблизно 10 ГБ вільного місця.
|
Вимоги: Linux із Docker (користувач має бути в групі `docker`), QEMU та OVMF для тестування, Go 1.24+ і файли розробки GTK 3 для `make test`. Приблизно 10 ГБ вільного місця.
|
||||||
```shell
|
```shell
|
||||||
@@ -187,6 +208,6 @@ make clean # видалити результати збиранн
|
|||||||
```
|
```
|
||||||
ISO з'являються в `out/iso/dasos-<версія>-x86_64.iso` і `out/iso/dasos-server-<версія>-x86_64.iso`. Записати їх на флешку можна через `dd` або Ventoy.
|
ISO з'являються в `out/iso/dasos-<версія>-x86_64.iso` і `out/iso/dasos-server-<версія>-x86_64.iso`. Записати їх на флешку можна через `dd` або Ventoy.
|
||||||
|
|
||||||
**Примітка:** Das OS — рання версія (0.5.0). Профіль розробника та підписаний репозиторій на хостингу заплановані на наступні етапи. Поки репозиторій не розміщено на хостингу, встановлена система отримує оновлення лише з Void. Das OS базується на Void Linux, але не пов'язана з ним офіційно.
|
**Примітка:** Das OS — рання версія (0.8.0). Пакети й ISO збираються в CI; підписаний репозиторій на хостингу заплановано на наступний етап. Поки репозиторій не розміщено на хостингу, встановлена система отримує оновлення лише з Void. Das OS базується на Void Linux, але не пов'язана з ним офіційно.
|
||||||
|
|
||||||
###### _Made by -=:dAs:=-_
|
###### _Made by -=:dAs:=-_
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Das OS — що зробити далі
|
# Das OS — що зробити далі
|
||||||
|
|
||||||
Стан на 2026-10-20: версія 0.5.0, етапи 1–7 готові (live ISO, власний репозиторій, оформлення, інсталятор Calamares зі знімками Btrfs, Go-утиліти `das-update` і `das-welcome`, серверний образ з консольним інсталятором, менші ISO, консольні помічники). Далі: профіль розробника (етап 8).
|
Стан на 2026-10-20: версія 0.8.0, етапи 1–8 готові (live ISO, власний репозиторій, оформлення, інсталятор Calamares зі знімками Btrfs, Go-утиліти `das-update` і `das-welcome`, серверний образ з консольним інсталятором, менші ISO, консольні помічники, профіль розробника), CI (етап 9: пакети й обидва ISO збираються на власному runner, ~45 хв).
|
||||||
|
|
||||||
## Етап 5. Go-утиліти (готово, лишилися перевірки)
|
## Етап 5. Go-утиліти (готово, лишилися перевірки)
|
||||||
- [x] `das-update`: вікно, значок у треї (лише коли є оновлення), консольний режим `--cli`, знімок snapper pre/post, встановлення через pkexec, підказка про відкат.
|
- [x] `das-update`: вікно, значок у треї (лише коли є оновлення), консольний режим `--cli`, знімок snapper pre/post, встановлення через pkexec, підказка про відкат.
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
- [x] Live ISO 0.4.0: екран не блокується під час встановлення.
|
- [x] Live ISO 0.4.0: екран не блокується під час встановлення.
|
||||||
- [ ] Вікно автентифікації polkit (`xfce-polkit`) англійською: перекласти або замінити агент.
|
- [ ] Вікно автентифікації polkit (`xfce-polkit`) англійською: перекласти або замінити агент.
|
||||||
- [ ] Повідомити авторів xdg-user-dirs про помилку з `XDG_DATA_DIRS`.
|
- [ ] Повідомити авторів xdg-user-dirs про помилку з `XDG_DATA_DIRS`.
|
||||||
- [ ] Пункт «Профіль розробника» в `das-welcome` (разом з етапом 8).
|
- [x] Пункт «Профіль розробника» в `das-welcome` (етап 8).
|
||||||
|
|
||||||
## Етап 6. Серверний образ (готово)
|
## Етап 6. Серверний образ (готово)
|
||||||
Live ISO без графіки з консольним інсталятором: `dasos-server-<версія>-x86_64.iso`.
|
Live ISO без графіки з консольним інсталятором: `dasos-server-<версія>-x86_64.iso`.
|
||||||
@@ -49,13 +49,25 @@ Live ISO без графіки з консольним інсталятором:
|
|||||||
- [x] Перевірено на встановленому сервері: `dsv new` з Python-сервером на 8080, доступ з хоста після `dfw allow` і закриття після `dfw deny`; `duser add` з ключем, вхід, `lock` блокує й вхід за ключем; `dsys` (часовий пояс, ім'я, мова, розкладка); `dfw reload` поруч із контейнером nginx.
|
- [x] Перевірено на встановленому сервері: `dsv new` з Python-сервером на 8080, доступ з хоста після `dfw allow` і закриття після `dfw deny`; `duser add` з ключем, вхід, `lock` блокує й вхід за ключем; `dsys` (часовий пояс, ім'я, мова, розкладка); `dfw reload` поруч із контейнером nginx.
|
||||||
- [x] Повідомлення наприкінці `das-server-install` згадує `dsv`, `duser`, `dfw`, `dsys`.
|
- [x] Повідомлення наприкінці `das-server-install` згадує `dsv`, `duser`, `dfw`, `dsys`.
|
||||||
|
|
||||||
## Етап 8. Профіль розробника
|
## Етап 8. Профіль розробника (готово)
|
||||||
- [ ] Метапакет `das-dev`: go, git, docker, podman, vscode.
|
Не метапакет, а `dprofile` у `das-helpers` зі списком пакетів Void у `/usr/share/das/profiles/dev.conf`: встановлена система поки не бачить репозиторію Das OS, тож метапакет `das-dev` звідти не встановився б, а пакети Void доступні завжди.
|
||||||
- [ ] Android Studio та JetBrains на вимогу через Flatpak.
|
- [x] `dprofile install dev`: base-devel, gdb, strace, git, git-lfs, github-cli, lazygit, go, gopls, delve, golangci-lint, python3-pip, virtualenv, uv, nodejs, docker, docker-compose, docker-buildx, lazydocker, podman, podman-compose, jq, ripgrep, fd, fzf, direnv, shellcheck, sqlite; на десктопі ще vscode (`code-oss`), meld, flatpak і портали. Пара знімків snapper pre/post, підказка про відкат; спершу оновлює xbps, якщо треба.
|
||||||
- [ ] Вибір профілю в інсталяторі (модуль packagechooser) або в `das-welcome`.
|
- [x] Налаштування: служба docker, група `docker` для того, хто запустив, `/etc/subuid`/`subgid` для rootless Podman, `/` як спільне монтування (`/etc/runit/core-services/60-das-shared-root.sh`; runit лишає його приватним, і Podman попереджає).
|
||||||
|
- [x] Flathub на вимогу (лише десктоп): Android Studio, IntelliJ IDEA Open/Ultimate, PyCharm, GoLand, WebStorm, VS Code від Microsoft; вибір номерами перед встановленням, `dprofile app add|rm` (з `--unused`, бо рантайми займають 1–4 ГБ). PyCharm Community на Flathub застарів (2024.3), тому `PyCharm-Professional` (безкоштовний режим).
|
||||||
|
- [x] Запитання й план — до `sudo`, пароль питається після них; `--yes`, `--apps ID,...|all|none` для скриптів.
|
||||||
|
- [x] `das-welcome`: рядок «Профіль розробника» відкриває `xfce4-terminal` з `dprofile install dev`; після встановлення — «Додати середовища».
|
||||||
|
- [x] Calamares packagechooser не додаємо: інсталятор копіює live-образ без мережі, а профіль завантажує ≈ 550 МБ.
|
||||||
|
- [x] Перевірено: сервер (QEMU) — `go run`, Node.js, uv, `docker run`, rootless `podman run` без попередження після перезавантаження; десктоп — встановлення з `das-welcome`, Code - OSS і VS Code з Flathub у меню після входу, `dprofile app rm` звільняє рантайми.
|
||||||
|
- [x] Повідомлення наприкінці `das-server-install` згадує `dprofile install dev`.
|
||||||
|
|
||||||
## Етап 9. CI
|
## Етап 9. CI (готово)
|
||||||
- [ ] Збирання пакетів і обох ISO (десктоп і сервер) в контейнері Void (Gitea Actions на git.das.org.ua або GitHub Actions).
|
- [x] Workflow `.gitea/workflows/build.yml`: `make iso iso-server` на власному runner `dasci:host` (push у `main`/`dev`, теги `v*`, ручний запуск).
|
||||||
|
- [x] CI-хост: Windows-машина (192.168.88.193), WSL2 Ubuntu 24.04 `dasci` у `D:\DasOS\wsl`, Docker Engine, `gitea-runner` 5.1.1 як служба systemd, автозапуск завданням планувальника (`ci/runner`).
|
||||||
|
- [x] `DASOS_OUT` у `scripts/builder.sh`: кеш `out/` на CI-хості в `/var/lib/dasos-ci/out`.
|
||||||
|
- [x] Runner зареєстровано, перший запуск у Gitea (run 1) успішний за 46 хв.
|
||||||
|
- [x] Після перезавантаження Windows runner піднімається сам, без входу в систему (завдання S4U).
|
||||||
|
- [x] Тег `v*` публікує обидва ISO і `SHA256SUMS` як реліз Gitea (`ci/release.sh`). Ліміт вкладення релізу — 2 ГБ на файл (`[repository.release] FILE_MAX_SIZE`).
|
||||||
|
- [ ] Перевірити першу публікацію на справжньому тегу.
|
||||||
|
|
||||||
## Репозиторій пакетів
|
## Репозиторій пакетів
|
||||||
- [ ] Підпис через `xbps-rindex --sign`, ключ поза репозиторієм.
|
- [ ] Підпис через `xbps-rindex --sign`, ключ поза репозиторієм.
|
||||||
@@ -78,7 +90,7 @@ Live ISO без графіки з консольним інсталятором:
|
|||||||
- [ ] Прибрати значки томів live-носія («Том 6,6 ГБ») з робочого столу live-сесії.
|
- [ ] Прибрати значки томів live-носія («Том 6,6 ГБ») з робочого столу live-сесії.
|
||||||
- [ ] Тема GRUB у встановленій системі (зараз стандартний чорний екран).
|
- [ ] Тема GRUB у встановленій системі (зараз стандартний чорний екран).
|
||||||
- [ ] Перевірити меню Whisker вручну.
|
- [ ] Перевірити меню Whisker вручну.
|
||||||
- [ ] Прискорити `make packages`: не перезбирати Calamares, якщо його версія не змінилася.
|
- [x] Прискорити `make packages`: пакет перезбирається лише після змін у `srcpkgs/<назва>`, без бінарного пакета або коли у Void зникла потрібна йому бібліотека (`xbps-install -n`). `DASOS_REBUILD=1` перезбирає все.
|
||||||
|
|
||||||
## Відкладено
|
## Відкладено
|
||||||
- [ ] ARM-образ для Raspberry Pi.
|
- [ ] ARM-образ для Raspberry Pi.
|
||||||
|
|||||||
Executable
+41
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Publishes the ISO images of the current version as a Gitea release:
|
||||||
|
# release.sh <tag> <iso dir>
|
||||||
|
# Needs GITEA_TOKEN, GITEA_SERVER_URL and GITEA_REPOSITORY (owner/name); in CI
|
||||||
|
# the job provides them. Running it again for the same tag replaces the files.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
tag=$1
|
||||||
|
dir=$2
|
||||||
|
version=$(cat VERSION)
|
||||||
|
[ "$tag" = "v$version" ] || { echo "release: tag $tag does not match VERSION $version" >&2; exit 1; }
|
||||||
|
|
||||||
|
api=$GITEA_SERVER_URL/api/v1/repos/$GITEA_REPOSITORY
|
||||||
|
auth="Authorization: token $GITEA_TOKEN"
|
||||||
|
json() { python3 -c "import json,sys; d=json.load(sys.stdin); $1"; }
|
||||||
|
|
||||||
|
isos="dasos-$version-x86_64.iso dasos-server-$version-x86_64.iso"
|
||||||
|
cd "$dir"
|
||||||
|
sha256sum $isos >SHA256SUMS
|
||||||
|
|
||||||
|
if ! id=$(curl -fsS -H "$auth" "$api/releases/tags/$tag" 2>/dev/null | json 'print(d["id"])' 2>/dev/null); then
|
||||||
|
id=$(curl -fsS -H "$auth" -H 'Content-Type: application/json' \
|
||||||
|
-d "{\"tag_name\":\"$tag\",\"name\":\"Das OS $version\",\"body\":\"Desktop and server live ISO images. Check them with sha256sum -c SHA256SUMS.\"}" \
|
||||||
|
"$api/releases" | json 'print(d["id"])')
|
||||||
|
echo "release: created $tag (id $id)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Files left from an earlier run for this tag are replaced
|
||||||
|
curl -fsS -H "$auth" "$api/releases/$id/assets" |
|
||||||
|
json '[print(a["id"], a["name"]) for a in d]' |
|
||||||
|
while read -r asset name; do
|
||||||
|
case " $isos SHA256SUMS " in
|
||||||
|
*" $name "*) curl -fsS -X DELETE -H "$auth" "$api/releases/$id/assets/$asset" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
for f in $isos SHA256SUMS; do
|
||||||
|
echo "release: uploading $f"
|
||||||
|
curl -fsS -o /dev/null -H "$auth" -F "attachment=@$f" "$api/releases/$id/assets?name=$f"
|
||||||
|
done
|
||||||
|
echo "release: $GITEA_SERVER_URL/$GITEA_REPOSITORY/releases/tag/$tag"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Starts the dasci WSL distro (Docker and gitea-runner inside) when Windows
|
||||||
|
# boots, without anyone logging in. Run once in an elevated PowerShell.
|
||||||
|
# The task keeps a process attached so WSL never stops the distro as idle.
|
||||||
|
$wsl = 'C:\Program Files\WSL\wsl.exe'
|
||||||
|
$action = New-ScheduledTaskAction -Execute $wsl -Argument '-d dasci --exec /bin/sleep infinity'
|
||||||
|
$trigger = New-ScheduledTaskTrigger -AtStartup
|
||||||
|
$principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType S4U -RunLevel Highest
|
||||||
|
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 0 -AllowStartIfOnBatteries `
|
||||||
|
-DontStopIfGoingOnBatteries -RestartCount 999 -RestartInterval (New-TimeSpan -Minutes 1)
|
||||||
|
Register-ScheduledTask -TaskName 'DasOS CI (WSL dasci)' -Action $action -Trigger $trigger `
|
||||||
|
-Principal $principal -Settings $settings -Force | Out-Null
|
||||||
|
Get-ScheduledTask -TaskName 'DasOS CI (WSL dasci)' | Select-Object TaskName, State
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# gitea-runner configuration for the Das OS CI host (WSL2 distro "dasci").
|
||||||
|
# Jobs run directly on the host: scripts/builder.sh needs the host's Docker
|
||||||
|
# and paths it can bind-mount into the privileged Void builder container.
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
|
||||||
|
runner:
|
||||||
|
file: /var/lib/gitea-runner/.runner
|
||||||
|
# One build at a time: packages and ISOs share the cache in DASOS_OUT
|
||||||
|
capacity: 1
|
||||||
|
# Matches Gitea's default job timeout; the first build bootstraps void-packages
|
||||||
|
timeout: 3h
|
||||||
|
envs:
|
||||||
|
DASOS_OUT: /var/lib/dasos-ci/out
|
||||||
|
labels:
|
||||||
|
- "dasci:host"
|
||||||
|
|
||||||
|
cache:
|
||||||
|
# Build caches live in DASOS_OUT, the workflow does not use actions/cache
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
host:
|
||||||
|
workdir_parent: /var/lib/gitea-runner/work
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Gitea Actions runner for Das OS
|
||||||
|
After=docker.service network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=runner
|
||||||
|
Group=runner
|
||||||
|
WorkingDirectory=/var/lib/gitea-runner
|
||||||
|
ExecStart=/usr/local/bin/gitea-runner -c /etc/gitea-runner/config.yaml daemon
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Sets up the Das OS CI host: Docker Engine, the runner user and gitea-runner.
|
||||||
|
# Run as root inside a fresh Ubuntu 24.04 WSL2 distro with systemd enabled:
|
||||||
|
# sh setup.sh install everything
|
||||||
|
# sh setup.sh register <token> register the runner with git.das.org.ua
|
||||||
|
# Safe to run again.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
RUNNER_VERSION=5.1.1
|
||||||
|
INSTANCE=https://git.das.org.ua
|
||||||
|
here=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
|
||||||
|
if [ "${1:-}" = register ]; then
|
||||||
|
[ -n "${2:-}" ] || { echo "usage: setup.sh register <token>" >&2; exit 1; }
|
||||||
|
sudo -u runner /usr/local/bin/gitea-runner -c /etc/gitea-runner/config.yaml \
|
||||||
|
register --no-interactive --instance "$INSTANCE" --token "$2" --name dasci
|
||||||
|
systemctl restart gitea-runner
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -q
|
||||||
|
apt-get install -yq ca-certificates curl git make xz-utils
|
||||||
|
|
||||||
|
# Docker Engine from Docker's repository (Ubuntu's docker.io lags behind)
|
||||||
|
install -m 0755 -d /etc/apt/keyrings
|
||||||
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
. /etc/os-release
|
||||||
|
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $VERSION_CODENAME stable" \
|
||||||
|
>/etc/apt/sources.list.d/docker.list
|
||||||
|
apt-get update -q
|
||||||
|
apt-get install -yq docker-ce docker-ce-cli containerd.io docker-buildx-plugin
|
||||||
|
systemctl enable --now docker
|
||||||
|
|
||||||
|
# Jobs run as an unprivileged user: build-packages.sh creates its xbps-src user
|
||||||
|
# with the caller's UID, which must not be root
|
||||||
|
id runner >/dev/null 2>&1 || useradd --create-home --shell /bin/bash --groups docker runner
|
||||||
|
install -d -o runner -g runner /var/lib/gitea-runner /var/lib/dasos-ci /var/lib/dasos-ci/out
|
||||||
|
|
||||||
|
url=https://gitea.com/gitea/runner/releases/download/v$RUNNER_VERSION/gitea-runner-$RUNNER_VERSION-linux-amd64.xz
|
||||||
|
tmp=$(mktemp -d)
|
||||||
|
curl -fsSL -o "$tmp/gitea-runner.xz" "$url"
|
||||||
|
curl -fsSL -o "$tmp/gitea-runner.xz.sha256" "$url.sha256"
|
||||||
|
(cd "$tmp" && echo "$(cut -d' ' -f1 gitea-runner.xz.sha256) gitea-runner.xz" | sha256sum -c --quiet)
|
||||||
|
xz -d "$tmp/gitea-runner.xz"
|
||||||
|
install -m 0755 "$tmp/gitea-runner" /usr/local/bin/gitea-runner
|
||||||
|
rm -rf "$tmp"
|
||||||
|
|
||||||
|
install -D -m 0644 "$here/config.yaml" /etc/gitea-runner/config.yaml
|
||||||
|
install -m 0644 "$here/gitea-runner.service" /etc/systemd/system/gitea-runner.service
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable gitea-runner
|
||||||
|
# The runner starts once it is registered
|
||||||
|
if [ -f /var/lib/gitea-runner/.runner ]; then
|
||||||
|
systemctl restart gitea-runner
|
||||||
|
else
|
||||||
|
echo "Now register: sh setup.sh register <token>"
|
||||||
|
fi
|
||||||
|
gitea-runner --version
|
||||||
+6
-2
@@ -1,18 +1,22 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Runs a command inside the Void Linux builder container.
|
# Runs a command inside the Void Linux builder container.
|
||||||
# The project is mounted at /work; downloaded packages are cached in out/cache/xbps.
|
# The project is mounted at /work; downloaded packages are cached in out/cache/xbps.
|
||||||
|
# DASOS_OUT puts out/ elsewhere (CI keeps it between checkouts).
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
root=$(cd "$(dirname "$0")/.." && pwd)
|
root=$(cd "$(dirname "$0")/.." && pwd)
|
||||||
|
out=${DASOS_OUT:-$root/out}
|
||||||
image=dasos-builder
|
image=dasos-builder
|
||||||
|
|
||||||
docker build --quiet --tag "$image" "$root/docker/builder" >/dev/null
|
docker build --quiet --tag "$image" "$root/docker/builder" >/dev/null
|
||||||
mkdir -p "$root/out/cache/xbps"
|
mkdir -p "$out/cache/xbps"
|
||||||
|
|
||||||
# --privileged: mklive mounts /proc, /sys, /dev and a loop device for the root image
|
# --privileged: mklive mounts /proc, /sys, /dev and a loop device for the root image
|
||||||
exec docker run --rm --privileged \
|
exec docker run --rm --privileged \
|
||||||
--volume "$root:/work" \
|
--volume "$root:/work" \
|
||||||
--volume "$root/out/cache/xbps:/var/cache/xbps" \
|
${DASOS_OUT:+--volume "$out:/work/out"} \
|
||||||
|
--volume "$out/cache/xbps:/var/cache/xbps" \
|
||||||
--env HOST_UID="$(id -u)" \
|
--env HOST_UID="$(id -u)" \
|
||||||
--env HOST_GID="$(id -g)" \
|
--env HOST_GID="$(id -g)" \
|
||||||
|
--env DASOS_REBUILD \
|
||||||
"$image" "$@"
|
"$image" "$@"
|
||||||
|
|||||||
@@ -34,6 +34,30 @@ XBPS_CHROOT_CMD=uchroot
|
|||||||
XBPS_MAKEJOBS=$(nproc)
|
XBPS_MAKEJOBS=$(nproc)
|
||||||
CONF
|
CONF
|
||||||
|
|
||||||
|
# A package is rebuilt only when its directory in srcpkgs/ changed since the last
|
||||||
|
# build, its binary package is gone, or Void no longer provides a shared library
|
||||||
|
# it links to (a soname bump there needs a rebuild here). DASOS_REBUILD=1 rebuilds all.
|
||||||
|
stamps=$hostdir/stamps
|
||||||
|
mkdir -p "$stamps"
|
||||||
|
srchash() {
|
||||||
|
(cd "$vp/srcpkgs/$1" && find . -type f -print0 | sort -z | xargs -0 sha256sum) | sha256sum | cut -d' ' -f1
|
||||||
|
}
|
||||||
|
# An empty root to dry-run installs into: xbps refuses unresolved shared libraries
|
||||||
|
checkroot=$(mktemp -d)
|
||||||
|
mkdir -p "$checkroot/var/db/xbps/keys"
|
||||||
|
cp -a /var/db/xbps/keys/. "$checkroot/var/db/xbps/keys/"
|
||||||
|
voidrepo=$(sed -n 's/^repository=//p' /usr/share/xbps.d/*-repository-main.conf | head -1)
|
||||||
|
xbps-install -S -r "$checkroot" -R "$voidrepo" >/dev/null
|
||||||
|
up_to_date() {
|
||||||
|
local info version revision
|
||||||
|
[[ ${DASOS_REBUILD:-} != 1 && -f $stamps/$1 && $(< "$stamps/$1") == "$(srchash "$1")" ]] || return 1
|
||||||
|
info=$(as_builder ./xbps-src show "$1")
|
||||||
|
version=$(sed -n 's/^version:[[:space:]]*//p' <<<"$info")
|
||||||
|
revision=$(sed -n 's/^revision:[[:space:]]*//p' <<<"$info")
|
||||||
|
compgen -G "$hostdir/binpkgs/$1-${version}_$revision.*.xbps" >/dev/null || return 1
|
||||||
|
xbps-install -n -y -r "$checkroot" -R "$hostdir/binpkgs" -R "$voidrepo" "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
names=()
|
names=()
|
||||||
for dir in /work/srcpkgs/*/; do
|
for dir in /work/srcpkgs/*/; do
|
||||||
name=$(basename "$dir")
|
name=$(basename "$dir")
|
||||||
@@ -59,9 +83,16 @@ fi
|
|||||||
# (also as a dependency of another one) would package the stale files
|
# (also as a dependency of another one) would package the stale files
|
||||||
rm -rf masterdir-x86_64/destdir/*
|
rm -rf masterdir-x86_64/destdir/*
|
||||||
for name in "${names[@]}"; do
|
for name in "${names[@]}"; do
|
||||||
|
if up_to_date "$name"; then
|
||||||
|
echo "==> $name is up to date"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
echo "==> Building $name"
|
echo "==> Building $name"
|
||||||
as_builder ./xbps-src -H "$hostdir" -f pkg "$name"
|
as_builder ./xbps-src -H "$hostdir" -f pkg "$name"
|
||||||
|
srchash "$name" >"$stamps/$name"
|
||||||
done
|
done
|
||||||
|
rm -rf "$checkroot"
|
||||||
|
chown -R "$HOST_UID:$HOST_GID" "$stamps"
|
||||||
|
|
||||||
echo "==> Repository: $hostdir/binpkgs"
|
echo "==> Repository: $hostdir/binpkgs"
|
||||||
ls -1 "$hostdir"/binpkgs/*.xbps
|
ls -1 "$hostdir"/binpkgs/*.xbps
|
||||||
|
|||||||
Executable
+416
@@ -0,0 +1,416 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# dprofile - install Das OS profiles: sets of packages from the Void
|
||||||
|
# repository with their services and groups, plus optional applications from
|
||||||
|
# Flathub. The profiles are in /usr/share/das/profiles/NAME.conf.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# shellcheck source=helpers.sh
|
||||||
|
. "${DAS_HELPERS:-/usr/lib/das/helpers.sh}"
|
||||||
|
|
||||||
|
profiles_dir=${DAS_PROFILES:-/usr/share/das/profiles}
|
||||||
|
flathub=https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
if [[ -n $uk ]]; then
|
||||||
|
cat <<'EOF'
|
||||||
|
Використання: dprofile КОМАНДА [ПРОФІЛЬ] [...]
|
||||||
|
|
||||||
|
list профілі та їхній стан (типова команда)
|
||||||
|
show ПРОФІЛЬ пакети, служби й додаткові застосунки профілю
|
||||||
|
install ПРОФІЛЬ встановити профіль (зі знімком системи для відкату):
|
||||||
|
-y, --yes без запитань
|
||||||
|
--apps ID,...|all|none
|
||||||
|
які застосунки з Flathub додати (інакше запитає)
|
||||||
|
apps ПРОФІЛЬ додаткові застосунки профілю з Flathub
|
||||||
|
app add ID... встановити застосунки з Flathub (ID або його кінець:
|
||||||
|
AndroidStudio, GoLand)
|
||||||
|
app rm ID... видалити їх
|
||||||
|
|
||||||
|
Профіль dev: dprofile install dev
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: dprofile COMMAND [PROFILE] [...]
|
||||||
|
|
||||||
|
list profiles and their state (the default)
|
||||||
|
show PROFILE the profile's packages, services and optional apps
|
||||||
|
install PROFILE install a profile (with a system snapshot to roll back to):
|
||||||
|
-y, --yes ask nothing
|
||||||
|
--apps ID,...|all|none
|
||||||
|
which Flathub applications to add (asks otherwise)
|
||||||
|
apps PROFILE the profile's optional applications from Flathub
|
||||||
|
app add ID... install applications from Flathub (an ID or its end:
|
||||||
|
AndroidStudio, GoLand)
|
||||||
|
app rm ID... remove them
|
||||||
|
|
||||||
|
The dev profile: dprofile install dev
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
desktop() {
|
||||||
|
command -v Xorg >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
live() {
|
||||||
|
grep -q 'root=live:' /proc/cmdline 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
profile_names() {
|
||||||
|
local f
|
||||||
|
for f in "$profiles_dir"/*.conf; do
|
||||||
|
[[ -e $f ]] || continue
|
||||||
|
f=${f##*/}
|
||||||
|
echo "${f%.conf}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# load NAME: reads the profile into title, desc, packages, services, groups,
|
||||||
|
# subids, shared_root and apps (one "ID NAME" per line)
|
||||||
|
load() {
|
||||||
|
local f=$profiles_dir/$1.conf
|
||||||
|
[[ $1 =~ ^[a-z0-9-]+$ && -r $f ]] ||
|
||||||
|
die "немає профілю '$1' (dprofile list)" "no profile '$1' (dprofile list)"
|
||||||
|
title_uk="" title_en="" desc_uk="" desc_en="" server_desc_uk="" server_desc_en=""
|
||||||
|
packages="" desktop_packages="" services="" groups="" subids="" shared_root="" apps=""
|
||||||
|
# shellcheck source=profiles/dev.conf
|
||||||
|
. "$f"
|
||||||
|
title=$(say "$title_uk" "$title_en")
|
||||||
|
desc=$(say "$desc_uk" "$desc_en")
|
||||||
|
if desktop; then
|
||||||
|
packages+=" $desktop_packages"
|
||||||
|
else
|
||||||
|
apps=""
|
||||||
|
[[ -z $server_desc_en ]] || desc=$(say "$server_desc_uk" "$server_desc_en")
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
packages=$(printf '%s\n' $packages)
|
||||||
|
apps=$(grep . <<<"$apps" || true)
|
||||||
|
}
|
||||||
|
|
||||||
|
installed() {
|
||||||
|
xbps-query "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Packages of the loaded profile that are not installed yet
|
||||||
|
missing_packages() {
|
||||||
|
local p
|
||||||
|
while read -r p; do
|
||||||
|
installed "$p" || echo "$p"
|
||||||
|
done <<<"$packages"
|
||||||
|
}
|
||||||
|
|
||||||
|
app_installed() {
|
||||||
|
command -v flatpak >/dev/null && flatpak info --system "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_list() {
|
||||||
|
local name total missing state
|
||||||
|
for name in $(profile_names); do
|
||||||
|
load "$name"
|
||||||
|
total=$(grep -c . <<<"$packages")
|
||||||
|
missing=$(missing_packages | grep -c . || true)
|
||||||
|
if ((missing == 0)); then
|
||||||
|
state=$(say "встановлено" "installed")
|
||||||
|
elif ((missing < total)); then
|
||||||
|
state=$(say "частково: бракує $missing з $total пакетів" "partly: $missing of $total packages missing")
|
||||||
|
else
|
||||||
|
state=$(say "не встановлено" "not installed")
|
||||||
|
fi
|
||||||
|
pad "$name" 8
|
||||||
|
echo "$title — $state"
|
||||||
|
echo " $desc"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_show() {
|
||||||
|
local p id name
|
||||||
|
load "$1"
|
||||||
|
echo "$title: $desc"
|
||||||
|
say "Пакети (* — уже встановлені):" "Packages (* marks the installed ones):"
|
||||||
|
while read -r p; do
|
||||||
|
if installed "$p"; then echo " * $p"; else echo " $p"; fi
|
||||||
|
done <<<"$packages"
|
||||||
|
[[ -z $services ]] || say "Служби: $services" "Services: $services"
|
||||||
|
[[ -z $groups ]] || say "Групи користувача: $groups" "User groups: $groups"
|
||||||
|
if [[ -n $apps ]]; then
|
||||||
|
say "Додатково з Flathub (dprofile app add ID):" "Optional, from Flathub (dprofile app add ID):"
|
||||||
|
while read -r id name; do
|
||||||
|
if app_installed "$id"; then echo " * $(pad "$name" 30)$id"; else echo " $(pad "$name" 30)$id"; fi
|
||||||
|
done <<<"$apps"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_apps() {
|
||||||
|
local id name
|
||||||
|
load "$1"
|
||||||
|
[[ -n $apps ]] || {
|
||||||
|
say "У профілю $1 немає додаткових застосунків (або тут немає графічного сеансу)." \
|
||||||
|
"The $1 profile has no optional applications (or there is no graphical session here)."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
while read -r id name; do
|
||||||
|
if app_installed "$id"; then echo "* $(pad "$name" 30)$id"; else echo " $(pad "$name" 30)$id"; fi
|
||||||
|
done <<<"$apps"
|
||||||
|
}
|
||||||
|
|
||||||
|
# resolve_app SPEC: the Flathub ID of SPEC, a full ID or its last part in any case
|
||||||
|
resolve_app() {
|
||||||
|
local spec=$1 name id found=""
|
||||||
|
if [[ $spec == *.*.* ]]; then
|
||||||
|
echo "$spec"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
shopt -s nocasematch
|
||||||
|
for name in $(profile_names); do
|
||||||
|
load "$name"
|
||||||
|
while read -r id _; do
|
||||||
|
[[ -n $id && ${id##*.} == "$spec" ]] && found=$id
|
||||||
|
done <<<"$apps"
|
||||||
|
done
|
||||||
|
shopt -u nocasematch
|
||||||
|
[[ -n $found ]] || die "невідомий застосунок '$spec': повний ID з Flathub або назва з dprofile apps" \
|
||||||
|
"unknown application '$spec': a full Flathub ID or a name from dprofile apps"
|
||||||
|
echo "$found"
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_flathub() {
|
||||||
|
flatpak remote-add --system --if-not-exists flathub "$flathub"
|
||||||
|
}
|
||||||
|
|
||||||
|
# app_add ID...: installs Flathub applications system-wide
|
||||||
|
app_add() {
|
||||||
|
(($# > 0)) || return 0
|
||||||
|
command -v flatpak >/dev/null ||
|
||||||
|
die "немає flatpak: спершу dprofile install dev" "flatpak is missing: dprofile install dev first"
|
||||||
|
setup_flathub
|
||||||
|
say "Встановлюю з Flathub: $*" "Installing from Flathub: $*"
|
||||||
|
# The exports are in the users' XDG_DATA_DIRS (/etc/profile.d/flatpak.sh),
|
||||||
|
# not in root's: without them flatpak warns that the menu won't find the apps
|
||||||
|
XDG_DATA_DIRS=/var/lib/flatpak/exports/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share} \
|
||||||
|
flatpak install --system --noninteractive -y flathub "$@"
|
||||||
|
say "Застосунки з'являться в меню після наступного входу." "The applications appear in the menu after the next login."
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_app() {
|
||||||
|
local action=${1:-} ids=() spec
|
||||||
|
shift || true
|
||||||
|
desktop || die "застосунки з Flathub — лише для системи з графічним сеансом" \
|
||||||
|
"Flathub applications are only for a system with a graphical session"
|
||||||
|
(($# > 0)) || die "вкажіть застосунок: dprofile app $action GoLand" "give an application: dprofile app $action GoLand"
|
||||||
|
for spec in "$@"; do
|
||||||
|
ids+=("$(resolve_app "$spec")")
|
||||||
|
done
|
||||||
|
case $action in
|
||||||
|
add | install)
|
||||||
|
need_root app add "${ids[@]}"
|
||||||
|
app_add "${ids[@]}"
|
||||||
|
;;
|
||||||
|
rm | remove)
|
||||||
|
need_root app rm "${ids[@]}"
|
||||||
|
flatpak uninstall --system --noninteractive -y "${ids[@]}"
|
||||||
|
# The runtimes no other application uses take most of the space
|
||||||
|
flatpak uninstall --system --noninteractive -y --unused
|
||||||
|
;;
|
||||||
|
*) die "dprofile app add|rm ID..." "dprofile app add|rm ID..." ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# choose_apps: asks which optional applications to install into "chosen"
|
||||||
|
choose_apps() {
|
||||||
|
local i=0 id name ids=() reply n ok
|
||||||
|
say "Додаткові середовища з Flathub (великі: 1–4 ГБ разом із рантаймами Flatpak):" \
|
||||||
|
"Optional IDEs from Flathub (large: 1-4 GB with the Flatpak runtimes):"
|
||||||
|
while read -r id name; do
|
||||||
|
ids+=("$id")
|
||||||
|
i=$((i + 1))
|
||||||
|
if app_installed "$id"; then
|
||||||
|
echo " $i) $(pad "$name" 30)$(say "уже встановлено" "already installed")"
|
||||||
|
else
|
||||||
|
echo " $i) $name"
|
||||||
|
fi
|
||||||
|
done <<<"$apps"
|
||||||
|
while true; do
|
||||||
|
chosen=()
|
||||||
|
ok=1
|
||||||
|
read -r -p "$(say "Номери через пробіл (Enter — жодного): " "Numbers separated by spaces (Enter for none): ")" reply || return 0
|
||||||
|
for n in ${reply//,/ }; do
|
||||||
|
if [[ $n =~ ^[0-9]+$ ]] && ((n >= 1 && n <= ${#ids[@]})); then
|
||||||
|
chosen+=("${ids[n - 1]}")
|
||||||
|
else
|
||||||
|
warn "'$n': номер від 1 до ${#ids[@]}" "'$n': a number from 1 to ${#ids[@]}"
|
||||||
|
ok=""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[[ -z $ok ]] || return 0
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# snapper pre/post pair around the installation, when snapshots are set up
|
||||||
|
snapshot_pre() {
|
||||||
|
[[ -e /etc/snapper/configs/root ]] || return 0
|
||||||
|
snapper -c root create --type pre --print-number --cleanup-algorithm number \
|
||||||
|
--description "dprofile install $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot_post() {
|
||||||
|
[[ -n $1 ]] || return 0
|
||||||
|
snapper -c root create --type post --pre-number "$1" --cleanup-algorithm number \
|
||||||
|
--description "dprofile install $2" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# add_subids USER: subordinate IDs for rootless containers, after the
|
||||||
|
# highest range already given out
|
||||||
|
add_subids() {
|
||||||
|
local user=$1 file start
|
||||||
|
for file in /etc/subuid /etc/subgid; do
|
||||||
|
touch "$file"
|
||||||
|
grep -q "^$user:" "$file" && continue
|
||||||
|
start=$(awk -F: 'BEGIN { m = 100000 } { if ($2 + $3 > m) m = $2 + $3 } END { print m }' "$file")
|
||||||
|
if [[ $file == /etc/subuid ]]; then
|
||||||
|
usermod --add-subuids "$start-$((start + 65535))" "$user"
|
||||||
|
else
|
||||||
|
usermod --add-subgids "$start-$((start + 65535))" "$user"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mount propagation for rootless containers, at every boot and right now
|
||||||
|
make_root_shared() {
|
||||||
|
local f=/etc/runit/core-services/60-das-shared-root.sh
|
||||||
|
[[ -e $f ]] && return
|
||||||
|
cat >"$f" <<'EOF'
|
||||||
|
# Created by dprofile: rootless Podman wants / to be a shared mount
|
||||||
|
mount --make-rshared /
|
||||||
|
EOF
|
||||||
|
mount --make-rshared /
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_install() {
|
||||||
|
local name="" yes="" asked="" app_spec="" user=${SUDO_USER:-} missing chosen=() id pre="" sv g joined=""
|
||||||
|
while (($# > 0)); do
|
||||||
|
case $1 in
|
||||||
|
-y | --yes) yes=1 ;;
|
||||||
|
--asked) asked=1 ;;
|
||||||
|
--apps) app_spec=${2:-}; shift ;;
|
||||||
|
--apps=*) app_spec=${1#--apps=} ;;
|
||||||
|
-*) die "невідомий параметр $1" "unknown option $1" ;;
|
||||||
|
*) name=$1 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
[[ -n $name ]] || die "вкажіть профіль: dprofile install dev" "give a profile: dprofile install dev"
|
||||||
|
load "$name"
|
||||||
|
live && die "це live-сесія: спершу встановіть Das OS на диск" "this is a live session: install Das OS to a disk first"
|
||||||
|
[[ $user == root ]] && user=""
|
||||||
|
missing=$(missing_packages | xargs)
|
||||||
|
|
||||||
|
# The questions come before sudo, so the password is asked for a known plan;
|
||||||
|
# --asked is the run through sudo after them
|
||||||
|
if [[ -z $asked ]]; then
|
||||||
|
echo "$title: $desc"
|
||||||
|
if [[ -n $missing ]]; then
|
||||||
|
say "Буде встановлено: $missing" "To be installed: $missing"
|
||||||
|
else
|
||||||
|
say "Усі пакети вже встановлено." "All packages are installed already."
|
||||||
|
fi
|
||||||
|
if [[ -n $apps && -z $app_spec && -z $yes ]] && interactive; then
|
||||||
|
choose_apps
|
||||||
|
app_spec=$(IFS=,; echo "${chosen[*]}")
|
||||||
|
app_spec=${app_spec:-none}
|
||||||
|
fi
|
||||||
|
if [[ -z $yes ]] && interactive; then
|
||||||
|
confirm "Продовжити?" "Continue?" || exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
need_root install "$name" --asked ${app_spec:+--apps "$app_spec"}
|
||||||
|
|
||||||
|
chosen=()
|
||||||
|
if [[ -n $apps ]]; then
|
||||||
|
case $app_spec in
|
||||||
|
"" | none) ;;
|
||||||
|
all) mapfile -t chosen < <(awk '{ print $1 }' <<<"$apps") ;;
|
||||||
|
*)
|
||||||
|
for id in ${app_spec//,/ }; do
|
||||||
|
chosen+=("$(resolve_app "$id")")
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $missing ]]; then
|
||||||
|
xbps-install -S
|
||||||
|
# xbps refuses to install anything while an update of itself is pending
|
||||||
|
if xbps-install -un 2>/dev/null | grep -q '^xbps-[0-9]'; then
|
||||||
|
xbps-install -uy xbps
|
||||||
|
fi
|
||||||
|
pre=$(snapshot_pre "$name") ||
|
||||||
|
die "не вдалося створити знімок системи, нічого не встановлено" "could not take a system snapshot, nothing was installed"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
if ! xbps-install -y $missing; then
|
||||||
|
snapshot_post "$pre" "$name"
|
||||||
|
die "xbps-install не вдався" "xbps-install failed"
|
||||||
|
fi
|
||||||
|
snapshot_post "$pre" "$name"
|
||||||
|
fi
|
||||||
|
|
||||||
|
for sv in $services; do
|
||||||
|
if [[ -d /etc/sv/$sv && ! -e /etc/runit/runsvdir/default/$sv ]]; then
|
||||||
|
ln -s "/etc/sv/$sv" /etc/runit/runsvdir/default/
|
||||||
|
say "Служба $sv увімкнена" "Service $sv enabled"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -z $shared_root ]] || make_root_shared
|
||||||
|
|
||||||
|
if [[ -n $user ]]; then
|
||||||
|
for g in $groups; do
|
||||||
|
if getent group "$g" >/dev/null && ! id -nG "$user" | grep -qw "$g"; then
|
||||||
|
gpasswd -a "$user" "$g" >/dev/null
|
||||||
|
joined+=" $g"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[[ -n $subids ]] && add_subids "$user"
|
||||||
|
[[ -z $joined ]] || say "$user тепер у групах:$joined (діє з наступного входу)" \
|
||||||
|
"$user is now in the groups:$joined (from the next login)"
|
||||||
|
elif [[ -n $groups ]]; then
|
||||||
|
say "Додайте користувачів до груп самі: duser groups КОРИСТУВАЧ +${groups// / +}" \
|
||||||
|
"Add users to the groups yourself: duser groups USER +${groups// / +}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v flatpak >/dev/null && desktop; then
|
||||||
|
setup_flathub
|
||||||
|
app_add "${chosen[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
say "Профіль $name встановлено." "The $name profile is installed."
|
||||||
|
[[ -z $pre ]] || say "Відкат: у меню завантаження «Das OS snapshots» → знімок №$pre, потім sudo snapper-rollback $pre." \
|
||||||
|
"To roll back: \"Das OS snapshots\" → snapshot #$pre in the boot menu, then sudo snapper-rollback $pre."
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd=${1:-list}
|
||||||
|
[[ $# -gt 0 ]] && shift
|
||||||
|
|
||||||
|
case $cmd in
|
||||||
|
list | ls) cmd_list ;;
|
||||||
|
show | info)
|
||||||
|
[[ $# -gt 0 ]] || die "вкажіть профіль: dprofile show dev" "give a profile: dprofile show dev"
|
||||||
|
cmd_show "$1"
|
||||||
|
;;
|
||||||
|
# Quiet, for das-welcome: success when every package is installed
|
||||||
|
check)
|
||||||
|
load "${1:-}"
|
||||||
|
[[ -z $(missing_packages) ]]
|
||||||
|
;;
|
||||||
|
install) cmd_install "$@" ;;
|
||||||
|
apps)
|
||||||
|
[[ $# -gt 0 ]] || die "вкажіть профіль: dprofile apps dev" "give a profile: dprofile apps dev"
|
||||||
|
cmd_apps "$1"
|
||||||
|
;;
|
||||||
|
app) cmd_app "$@" ;;
|
||||||
|
-h | --help | help) usage ;;
|
||||||
|
*)
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# bash completion for dprofile
|
||||||
|
# shellcheck shell=bash
|
||||||
|
_dprofile() {
|
||||||
|
local cur=${COMP_WORDS[COMP_CWORD]} cmd=${COMP_WORDS[1]:-} dir=/usr/share/das/profiles
|
||||||
|
local profiles
|
||||||
|
profiles=$(find "$dir" -maxdepth 1 -name '*.conf' -printf '%f\n' 2>/dev/null | sed 's/\.conf$//')
|
||||||
|
if ((COMP_CWORD == 1)); then
|
||||||
|
mapfile -t COMPREPLY < <(compgen -W "list show install apps app help" -- "$cur")
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
case $cmd in
|
||||||
|
show | apps | check)
|
||||||
|
((COMP_CWORD == 2)) && mapfile -t COMPREPLY < <(compgen -W "$profiles" -- "$cur")
|
||||||
|
;;
|
||||||
|
install)
|
||||||
|
if [[ ${COMP_WORDS[COMP_CWORD - 1]} == --apps ]]; then
|
||||||
|
mapfile -t COMPREPLY < <(compgen -W "all none" -- "$cur")
|
||||||
|
else
|
||||||
|
mapfile -t COMPREPLY < <(compgen -W "$profiles --yes --apps" -- "$cur")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
app)
|
||||||
|
if ((COMP_CWORD == 2)); then
|
||||||
|
mapfile -t COMPREPLY < <(compgen -W "add rm" -- "$cur")
|
||||||
|
else
|
||||||
|
# the last part of the IDs in the profiles: AndroidStudio, GoLand
|
||||||
|
mapfile -t COMPREPLY < <(compgen -W "$(sed -n 's/^[a-z]*\.[A-Za-z0-9.-]*\.\([A-Za-z0-9-]*\) .*/\1/p' "$dir"/*.conf 2>/dev/null)" -- "$cur")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
complete -F _dprofile dprofile
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Das OS developer profile, installed with "dprofile install dev".
|
||||||
|
# shellcheck shell=bash disable=SC2034
|
||||||
|
|
||||||
|
title_uk="Розробник"
|
||||||
|
title_en="Developer"
|
||||||
|
desc_uk="Go, Python, Node.js, Git, Docker і Podman, VS Code; середовища JetBrains і Android Studio з Flathub"
|
||||||
|
desc_en="Go, Python, Node.js, Git, Docker and Podman, VS Code; JetBrains IDEs and Android Studio from Flathub"
|
||||||
|
# Without a graphical session
|
||||||
|
server_desc_uk="Go, Python, Node.js, Git, Docker і Podman, консольні інструменти"
|
||||||
|
server_desc_en="Go, Python, Node.js, Git, Docker and Podman, command-line tools"
|
||||||
|
|
||||||
|
# Packages from the Void repository, on every system
|
||||||
|
packages="
|
||||||
|
base-devel gdb strace
|
||||||
|
git git-lfs github-cli lazygit
|
||||||
|
go gopls delve golangci-lint
|
||||||
|
python3-pip python3-virtualenv uv
|
||||||
|
nodejs
|
||||||
|
docker docker-compose docker-buildx lazydocker
|
||||||
|
podman podman-compose
|
||||||
|
jq ripgrep fd fzf direnv shellcheck sqlite"
|
||||||
|
|
||||||
|
# Only with a graphical session
|
||||||
|
desktop_packages="
|
||||||
|
vscode meld
|
||||||
|
flatpak xdg-desktop-portal xdg-desktop-portal-gtk"
|
||||||
|
|
||||||
|
# runit services to enable
|
||||||
|
services="docker"
|
||||||
|
|
||||||
|
# Groups the user who installs the profile joins (docker is root-equivalent)
|
||||||
|
groups="docker"
|
||||||
|
|
||||||
|
# Rootless Podman needs subordinate user and group IDs, and a shared root
|
||||||
|
# mount (runit leaves / private)
|
||||||
|
subids=yes
|
||||||
|
shared_root=yes
|
||||||
|
|
||||||
|
# Optional applications from Flathub (desktop only): ID and name
|
||||||
|
apps="
|
||||||
|
com.google.AndroidStudio Android Studio
|
||||||
|
com.jetbrains.IntelliJ-IDEA-Community IntelliJ IDEA Open
|
||||||
|
com.jetbrains.IntelliJ-IDEA-Ultimate IntelliJ IDEA Ultimate
|
||||||
|
com.jetbrains.PyCharm-Professional PyCharm
|
||||||
|
com.jetbrains.GoLand GoLand
|
||||||
|
com.jetbrains.WebStorm WebStorm
|
||||||
|
com.visualstudio.code Visual Studio Code (Microsoft)"
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
# Template file for 'das-helpers'
|
# Template file for 'das-helpers'
|
||||||
pkgname=das-helpers
|
pkgname=das-helpers
|
||||||
version=0.1.0
|
version=0.2.0
|
||||||
revision=1
|
revision=1
|
||||||
depends="bash runit sudo shadow openssh nftables kbd"
|
depends="bash runit sudo shadow openssh nftables kbd"
|
||||||
short_desc="Das OS helpers: services (dsv), users (duser), firewall (dfw), system (dsys)"
|
short_desc="Das OS helpers: services, users, firewall, system settings, profiles"
|
||||||
maintainer="Das <anry.das@gmail.com>"
|
maintainer="Das <anry.das@gmail.com>"
|
||||||
license="MIT"
|
license="MIT"
|
||||||
homepage="https://git.das.org.ua/das/Das-OS"
|
homepage="https://git.das.org.ua/das/Das-OS"
|
||||||
@@ -13,7 +13,8 @@ provides="dsv-${version}_${revision}"
|
|||||||
|
|
||||||
do_install() {
|
do_install() {
|
||||||
vinstall ${FILESDIR}/helpers.sh 644 usr/lib/das
|
vinstall ${FILESDIR}/helpers.sh 644 usr/lib/das
|
||||||
for tool in dsv duser dfw dsys; do
|
vinstall ${FILESDIR}/profiles/dev.conf 644 usr/share/das/profiles
|
||||||
|
for tool in dsv duser dfw dsys dprofile; do
|
||||||
vbin ${FILESDIR}/${tool}
|
vbin ${FILESDIR}/${tool}
|
||||||
vcompletion ${FILESDIR}/${tool}.bash-completion bash ${tool}
|
vcompletion ${FILESDIR}/${tool}.bash-completion bash ${tool}
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ t() {
|
|||||||
s_config) echo "Налаштування системи..." ;;
|
s_config) echo "Налаштування системи..." ;;
|
||||||
s_post) echo "Локалі, знімки, initramfs (кілька хвилин)..." ;;
|
s_post) echo "Локалі, знімки, initramfs (кілька хвилин)..." ;;
|
||||||
s_boot) echo "Встановлення завантажувача..." ;;
|
s_boot) echo "Встановлення завантажувача..." ;;
|
||||||
finished) echo "Das OS Server встановлено. Вийміть інсталяційний носій і перезавантажте сервер.\n\nВхід: %s, далі sudo. Служби: dsv. Користувачі: duser. Порти: dfw. Налаштування: dsys. Оновлення: das-update." ;;
|
finished) echo "Das OS Server встановлено. Вийміть інсталяційний носій і перезавантажте сервер.\n\nВхід: %s, далі sudo. Служби: dsv. Користувачі: duser. Порти: dfw. Налаштування: dsys. Оновлення: das-update. Профіль розробника: dprofile install dev." ;;
|
||||||
reboot) echo "Перезавантажити зараз?" ;;
|
reboot) echo "Перезавантажити зараз?" ;;
|
||||||
failed) echo "Помилка встановлення. Журнал: %s" ;;
|
failed) echo "Помилка встановлення. Журнал: %s" ;;
|
||||||
root) echo "Інсталятор треба запускати від root (sudo das-server-install)." ;;
|
root) echo "Інсталятор треба запускати від root (sudo das-server-install)." ;;
|
||||||
@@ -105,7 +105,7 @@ t() {
|
|||||||
s_config) echo "Configuring the system..." ;;
|
s_config) echo "Configuring the system..." ;;
|
||||||
s_post) echo "Locales, snapshots, initramfs (a few minutes)..." ;;
|
s_post) echo "Locales, snapshots, initramfs (a few minutes)..." ;;
|
||||||
s_boot) echo "Installing the boot loader..." ;;
|
s_boot) echo "Installing the boot loader..." ;;
|
||||||
finished) echo "Das OS Server is installed. Remove the installation medium and reboot.\n\nLog in as %s, then use sudo. Services: dsv. Users: duser. Ports: dfw. Settings: dsys. Updates: das-update." ;;
|
finished) echo "Das OS Server is installed. Remove the installation medium and reboot.\n\nLog in as %s, then use sudo. Services: dsv. Users: duser. Ports: dfw. Settings: dsys. Updates: das-update. Developer profile: dprofile install dev." ;;
|
||||||
reboot) echo "Reboot now?" ;;
|
reboot) echo "Reboot now?" ;;
|
||||||
failed) echo "Installation failed. Log: %s" ;;
|
failed) echo "Installation failed. Log: %s" ;;
|
||||||
root) echo "The installer must run as root (sudo das-server-install)." ;;
|
root) echo "The installer must run as root (sudo das-server-install)." ;;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Template file for 'das-server-installer'
|
# Template file for 'das-server-installer'
|
||||||
pkgname=das-server-installer
|
pkgname=das-server-installer
|
||||||
version=0.2.0
|
version=0.3.0
|
||||||
revision=1
|
revision=1
|
||||||
depends="bash dialog das-install-common btrfs-progs dosfstools gptfdisk parted
|
depends="bash dialog das-install-common btrfs-progs dosfstools gptfdisk parted
|
||||||
rsync util-linux grub grub-x86_64-efi efibootmgr"
|
rsync util-linux grub grub-x86_64-efi efibootmgr"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Command das-welcome is the Das OS first-login window: interface language,
|
// Command das-welcome is the Das OS first-login window: interface language,
|
||||||
// home folder names, updates, settings and help.
|
// home folder names, updates, the developer profile, settings and help.
|
||||||
//
|
//
|
||||||
// das-welcome show the window
|
// das-welcome show the window
|
||||||
// das-welcome --autostart show it only if the user did not turn that off
|
// das-welcome --autostart show it only if the user did not turn that off
|
||||||
@@ -207,6 +207,9 @@ func newWindow(app *gtk.Application) (*gtk.ApplicationWindow, error) {
|
|||||||
row, _ := b.row("software-update-available", i18n.T("welcome.update"), i18n.T("welcome.update.desc"),
|
row, _ := b.row("software-update-available", i18n.T("welcome.update"), i18n.T("welcome.update.desc"),
|
||||||
b.button(i18n.T("welcome.update.open"), func() { launch("das-update") }))
|
b.button(i18n.T("welcome.update.open"), func() { launch("das-update") }))
|
||||||
add(row)
|
add(row)
|
||||||
|
if row := profileRow(b); row != nil {
|
||||||
|
add(row)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
row, _ := b.row("preferences-desktop", i18n.T("welcome.settings"), i18n.T("welcome.settings.desc"),
|
row, _ := b.row("preferences-desktop", i18n.T("welcome.settings"), i18n.T("welcome.settings.desc"),
|
||||||
b.button(i18n.T("welcome.open"), func() { launch("xfce4-settings-manager") }))
|
b.button(i18n.T("welcome.open"), func() { launch("xfce4-settings-manager") }))
|
||||||
@@ -249,6 +252,23 @@ func launch(name string, args ...string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// profileRow installs the developer profile in a terminal, where dprofile
|
||||||
|
// asks for the password and which IDEs to add. It returns nil without dprofile.
|
||||||
|
func profileRow(b *builder) *gtk.Box {
|
||||||
|
if _, err := exec.LookPath("dprofile"); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
desc, label := i18n.T("welcome.dev.desc"), i18n.T("welcome.dev.install")
|
||||||
|
if exec.Command("dprofile", "check", "dev").Run() == nil {
|
||||||
|
desc, label = i18n.T("welcome.dev.installed"), i18n.T("welcome.dev.apps")
|
||||||
|
}
|
||||||
|
row, _ := b.row("applications-development", i18n.T("welcome.dev"), desc,
|
||||||
|
b.button(label, func() {
|
||||||
|
launch("xfce4-terminal", "--hold", "--title", i18n.T("welcome.dev"), "-x", "dprofile", "install", "dev")
|
||||||
|
}))
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
// languageRow offers the UTF-8 locales the system has built. It returns nil
|
// languageRow offers the UTF-8 locales the system has built. It returns nil
|
||||||
// when there is nothing to choose from.
|
// when there is nothing to choose from.
|
||||||
func languageRow(b *builder) *gtk.Box {
|
func languageRow(b *builder) *gtk.Box {
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ var messages = map[string]message{
|
|||||||
"welcome.update": {"Оновлення", "Updates"},
|
"welcome.update": {"Оновлення", "Updates"},
|
||||||
"welcome.update.desc": {"Перед кожним оновленням створюється знімок системи для відкату.", "A system snapshot is taken before every update so it can be rolled back."},
|
"welcome.update.desc": {"Перед кожним оновленням створюється знімок системи для відкату.", "A system snapshot is taken before every update so it can be rolled back."},
|
||||||
"welcome.update.open": {"Перевірити", "Check"},
|
"welcome.update.open": {"Перевірити", "Check"},
|
||||||
|
"welcome.dev": {"Профіль розробника", "Developer profile"},
|
||||||
|
"welcome.dev.desc": {"Go, Python, Node.js, Git, Docker і Podman, VS Code; за бажанням JetBrains і Android Studio з Flathub.", "Go, Python, Node.js, Git, Docker and Podman, VS Code; JetBrains IDEs and Android Studio from Flathub if you like."},
|
||||||
|
"welcome.dev.installed": {"Встановлено. Середовища JetBrains і Android Studio можна додати з Flathub.", "Installed. JetBrains IDEs and Android Studio can be added from Flathub."},
|
||||||
|
"welcome.dev.install": {"Встановити", "Install"},
|
||||||
|
"welcome.dev.apps": {"Додати середовища", "Add IDEs"},
|
||||||
"welcome.settings": {"Налаштування", "Settings"},
|
"welcome.settings": {"Налаштування", "Settings"},
|
||||||
"welcome.settings.desc": {"Тема, екран, клавіатура, принтери та інше.", "Theme, display, keyboard, printers and more."},
|
"welcome.settings.desc": {"Тема, екран, клавіатура, принтери та інше.", "Theme, display, keyboard, printers and more."},
|
||||||
"welcome.open": {"Відкрити", "Open"},
|
"welcome.open": {"Відкрити", "Open"},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Template file for 'das-tools'
|
# Template file for 'das-tools'
|
||||||
# In-tree package: Go sources are in files/src (FILESDIR).
|
# In-tree package: Go sources are in files/src (FILESDIR).
|
||||||
pkgname=das-tools
|
pkgname=das-tools
|
||||||
version=0.3.0
|
version=0.4.0
|
||||||
revision=1
|
revision=1
|
||||||
create_wrksrc=yes
|
create_wrksrc=yes
|
||||||
# Like build_style=go: the Go linker decides about PIE, xbps-src must not check it
|
# Like build_style=go: the Go linker decides about PIE, xbps-src must not check it
|
||||||
|
|||||||
Reference in New Issue
Block a user