Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
ef052e9f66 | |||
c53576a700
|
|||
3d74ec37e4 | |||
c4855ed3fb
|
|||
07ee03b6be
|
|||
fb2a62d984
|
|||
113103f368
|
|||
f112002249 | |||
0c1d8be79f
|
@@ -4,7 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- '**'
|
- "**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
detect-version-change:
|
detect-version-change:
|
||||||
@@ -125,7 +125,7 @@ jobs:
|
|||||||
if: steps.restore-cliff.outputs.cache-hit != 'true'
|
if: steps.restore-cliff.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
cargo install git-cliff --version "${{ steps.cliff_version.outputs.version }}" --features gitea
|
cargo install git-cliff --version "${{ steps.cliff_version.outputs.version }}" --features gitea
|
||||||
|
|
||||||
- name: Generate changelog for release and tag
|
- name: Generate changelog for release and tag
|
||||||
id: generate-changelog
|
id: generate-changelog
|
||||||
run: |
|
run: |
|
||||||
@@ -152,7 +152,6 @@ jobs:
|
|||||||
|
|
||||||
echo "changelog_body_path=$BODY" >> $GITHUB_OUTPUT
|
echo "changelog_body_path=$BODY" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
|
||||||
- name: Commit updated CHANGELOG
|
- name: Commit updated CHANGELOG
|
||||||
run: |
|
run: |
|
||||||
git add CHANGELOG.md
|
git add CHANGELOG.md
|
||||||
@@ -169,12 +168,14 @@ jobs:
|
|||||||
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
|
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
|
||||||
echo "Tag v$VERSION already exists, skipping tag creation."
|
echo "Tag v$VERSION already exists, skipping tag creation."
|
||||||
else
|
else
|
||||||
|
export GIT_AUTHOR_DATE="$(date --iso-8601=seconds)"
|
||||||
|
export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
|
||||||
git tag -a "v$VERSION" -F "${{ steps.generate-changelog.outputs.changelog_body_path }}" --cleanup=verbatim
|
git tag -a "v$VERSION" -F "${{ steps.generate-changelog.outputs.changelog_body_path }}" --cleanup=verbatim
|
||||||
git push origin "v$VERSION"
|
git push origin "v$VERSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create Gitea release
|
- name: Create Gitea release
|
||||||
env:
|
env:
|
||||||
RELEASE_PUBLISH_TOKEN: ${{ secrets.RELEASE_PUBLISH_TOKEN }}
|
RELEASE_PUBLISH_TOKEN: ${{ secrets.RELEASE_PUBLISH_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ steps.version.outputs.value }}
|
VERSION=${{ steps.version.outputs.value }}
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
name: Sync Release to GitHub
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
tag:
|
|
||||||
description: "Release tag to synchronize"
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
release:
|
|
||||||
types: [published, edited]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync-github:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Run Releases Sync Action
|
|
||||||
uses: https://git.0xmax42.io/actions/releases-sync@main
|
|
||||||
with:
|
|
||||||
gitea_token: ${{ secrets.RELEASE_PUBLISH_TOKEN }}
|
|
||||||
gitea_url: https://git.0xmax42.io
|
|
||||||
gitea_owner: maxp
|
|
||||||
gitea_repo: systemd-timer
|
|
||||||
tag_name: ${{ inputs.tag || github.event.release.tag_name }}
|
|
||||||
github_token: ${{ secrets.SYNC_GITHUB_TOKEN }}
|
|
||||||
github_owner: 0xmax42
|
|
||||||
github_repo: systemd-timer
|
|
@@ -42,3 +42,15 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload SHA256 for ${{ matrix.target }}-${{ matrix.arch }}
|
- name: Upload SHA256 for ${{ matrix.target }}-${{ matrix.arch }}
|
||||||
run: .gitea/scripts/upload-asset.sh ./dist/systemd-timer-${{ matrix.target }}-${{ matrix.arch }}.sha256 systemd-timer-${{ matrix.target }}-${{ matrix.arch }}.sha256
|
run: .gitea/scripts/upload-asset.sh ./dist/systemd-timer-${{ matrix.target }}-${{ matrix.arch }}.sha256 systemd-timer-${{ matrix.target }}-${{ matrix.arch }}.sha256
|
||||||
|
|
||||||
|
- name: Run Releases Sync Action
|
||||||
|
uses: https://git.0xmax42.io/actions/releases-sync@main
|
||||||
|
with:
|
||||||
|
gitea_token: ${{ secrets.RELEASE_PUBLISH_TOKEN }}
|
||||||
|
gitea_url: https://git.0xmax42.io
|
||||||
|
gitea_owner: maxp
|
||||||
|
gitea_repo: systemd-timer
|
||||||
|
tag_name: ${{ github.event.release.tag_name }}
|
||||||
|
github_token: ${{ secrets.SYNC_GITHUB_TOKEN }}
|
||||||
|
github_owner: 0xmax42
|
||||||
|
github_repo: systemd-timer
|
||||||
|
18
CHANGELOG.md
18
CHANGELOG.md
@@ -2,6 +2,24 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [0.3.1](https://git.0xmax42.io/maxp/systemd-timer/compare/v0.2.3..v0.3.1) - 2025-05-28
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- *(cli)* Add options for user, home, and working directory - ([113103f](https://git.0xmax42.io/maxp/systemd-timer/commit/113103f368ead3014165cc708f016a04749f59be))
|
||||||
|
|
||||||
|
### 📚 Documentation
|
||||||
|
|
||||||
|
- *(readme)* Expand CLI option descriptions for clarity - ([fb2a62d](https://git.0xmax42.io/maxp/systemd-timer/commit/fb2a62d984615caa4035fd5c1e8e64d245499e47))
|
||||||
|
|
||||||
|
### 🎨 Styling
|
||||||
|
|
||||||
|
- *(workflows)* Fix formatting and whitespace issues - ([c4855ed](https://git.0xmax42.io/maxp/systemd-timer/commit/c4855ed3fbc0ada208690f90932710983daef392))
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(workflows)* Consolidate release sync into upload workflow - ([0c1d8be](https://git.0xmax42.io/maxp/systemd-timer/commit/0c1d8be79f0cc331db9029beb46384659f465f6e))
|
||||||
|
|
||||||
## [0.2.3](https://git.0xmax42.io/maxp/systemd-timer/compare/v0.2.2..v0.2.3) - 2025-05-26
|
## [0.2.3](https://git.0xmax42.io/maxp/systemd-timer/compare/v0.2.2..v0.2.3) - 2025-05-26
|
||||||
|
|
||||||
### 🚀 Features
|
### 🚀 Features
|
||||||
|
18
README.DE.md
18
README.DE.md
@@ -12,13 +12,17 @@ Ein einfaches CLI-Tool zum schnellen Erzeugen von systemd `.service` und `.timer
|
|||||||
- Unterstützt `--user` Timer (für `~/.config/systemd/user/`)
|
- Unterstützt `--user` Timer (für `~/.config/systemd/user/`)
|
||||||
- Optionales Logging (`StandardOutput/StandardError`)
|
- Optionales Logging (`StandardOutput/StandardError`)
|
||||||
- Unterstützt:
|
- Unterstützt:
|
||||||
- `--calendar`
|
- `--calendar`: Zeitplan für den Timer (systemd `OnCalendar`)
|
||||||
- `--exec`
|
- `--exec`: Auszuführendes Kommando (`ExecStart`)
|
||||||
- `--after`
|
- `--description`: Beschreibung für die Unit
|
||||||
- `--environment`
|
- `--after`: `After=`-Abhängigkeiten in der Service-Unit
|
||||||
- `--output`
|
- `--environment`: Beliebige `Environment=KEY=VALUE` Einträge
|
||||||
- `--dry-run`
|
- `--output`: Zielverzeichnis für die generierten Unit-Dateien
|
||||||
- Getestet und typisiert mit Deno + Cliffy
|
- `--run-as`: Setzt `User=` in der Service-Unit (nur systemweite Timer)
|
||||||
|
- `--home`: Setzt `Environment=HOME=…`
|
||||||
|
- `--cwd`: Arbeitsverzeichnis des Prozesses (`WorkingDirectory`)
|
||||||
|
- `--dry-run`: Gibt nur die generierten Inhalte aus, ohne sie zu schreiben
|
||||||
|
- Getestet und typisiert mit **Deno** + **Cliffy**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
19
README.md
19
README.md
@@ -13,14 +13,17 @@ A simple CLI tool for quickly generating systemd `.service` and `.timer` units
|
|||||||
* Supports `--user` timers (for `~/.config/systemd/user/`)
|
* Supports `--user` timers (for `~/.config/systemd/user/`)
|
||||||
* Optional logging (`StandardOutput/StandardError`)
|
* Optional logging (`StandardOutput/StandardError`)
|
||||||
* Supports:
|
* Supports:
|
||||||
|
* `--calendar`: Timer schedule (systemd `OnCalendar`)
|
||||||
* `--calendar`
|
* `--exec`: Command to execute (`ExecStart`)
|
||||||
* `--exec`
|
* `--description`: Description for the unit
|
||||||
* `--after`
|
* `--after`: `After=` dependencies in the service unit
|
||||||
* `--environment`
|
* `--environment`: Arbitrary `Environment=KEY=VALUE` entries
|
||||||
* `--output`
|
* `--output`: Target directory for the generated unit files
|
||||||
* `--dry-run`
|
* `--run-as`: Sets `User=` in the service unit (only for system-level timers)
|
||||||
* Tested and typed with Deno + Cliffy
|
* `--home`: Sets `Environment=HOME=…`
|
||||||
|
* `--cwd`: Working directory for the process (`WorkingDirectory`)
|
||||||
|
* `--dry-run`: Outputs unit content without writing to disk
|
||||||
|
* Tested and fully typed with **Deno** + **Cliffy**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -18,6 +18,18 @@ export const createCommand = new Command()
|
|||||||
})
|
})
|
||||||
.option('--description <desc:string>', 'Beschreibung des Timers')
|
.option('--description <desc:string>', 'Beschreibung des Timers')
|
||||||
.option('--user', 'Erstellt die Unit als User-Timer')
|
.option('--user', 'Erstellt die Unit als User-Timer')
|
||||||
|
.option(
|
||||||
|
'--run-as <user:string>',
|
||||||
|
'Führe den systemweiten Timer als bestimmter Benutzer aus (setzt User= in der Service-Unit)',
|
||||||
|
)
|
||||||
|
.option(
|
||||||
|
'--home <path:string>',
|
||||||
|
'HOME-Variable für den Service setzen',
|
||||||
|
)
|
||||||
|
.option(
|
||||||
|
'--cwd <path:string>',
|
||||||
|
'Arbeitsverzeichnis (WorkingDirectory) für den Service-Prozess',
|
||||||
|
)
|
||||||
.option('--output <dir:string>', 'Zielverzeichnis der Unit-Dateien')
|
.option('--output <dir:string>', 'Zielverzeichnis der Unit-Dateien')
|
||||||
.option(
|
.option(
|
||||||
'--after <target:string>',
|
'--after <target:string>',
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
assert,
|
||||||
assertStringIncludes,
|
assertStringIncludes,
|
||||||
} from 'https://deno.land/std@0.224.0/assert/mod.ts';
|
} from 'https://deno.land/std@0.224.0/assert/mod.ts';
|
||||||
import { TimerOptions } from '../../types/mod.ts';
|
import { TimerOptions } from '../../types/mod.ts';
|
||||||
@@ -53,3 +54,63 @@ Deno.test('generateUnits berücksichtigt environment und logfile', () => {
|
|||||||
assertStringIncludes(serviceUnit, 'StandardOutput=append:/var/log/job.log');
|
assertStringIncludes(serviceUnit, 'StandardOutput=append:/var/log/job.log');
|
||||||
assertStringIncludes(serviceUnit, 'StandardError=append:/var/log/job.log');
|
assertStringIncludes(serviceUnit, 'StandardError=append:/var/log/job.log');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Deno.test('generateUnits berücksichtigt runAs', () => {
|
||||||
|
const opts: TimerOptions = {
|
||||||
|
exec: '/bin/true',
|
||||||
|
calendar: 'daily',
|
||||||
|
runAs: 'myuser',
|
||||||
|
};
|
||||||
|
const { serviceUnit } = generateUnits('job', opts);
|
||||||
|
|
||||||
|
assertStringIncludes(serviceUnit, 'User=myuser');
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('generateUnits berücksichtigt home', () => {
|
||||||
|
const opts: TimerOptions = {
|
||||||
|
exec: '/bin/true',
|
||||||
|
calendar: 'daily',
|
||||||
|
home: '/home/myuser',
|
||||||
|
};
|
||||||
|
const { serviceUnit } = generateUnits('job', opts);
|
||||||
|
|
||||||
|
assertStringIncludes(serviceUnit, 'Environment=HOME=/home/myuser');
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('generateUnits berücksichtigt cwd', () => {
|
||||||
|
const opts: TimerOptions = {
|
||||||
|
exec: '/bin/true',
|
||||||
|
calendar: 'daily',
|
||||||
|
cwd: '/srv/app',
|
||||||
|
};
|
||||||
|
const { serviceUnit } = generateUnits('job', opts);
|
||||||
|
|
||||||
|
assertStringIncludes(serviceUnit, 'WorkingDirectory=/srv/app');
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('generateUnits verwendet default.target bei User-Timern', () => {
|
||||||
|
const opts: TimerOptions = {
|
||||||
|
exec: '/bin/true',
|
||||||
|
calendar: 'daily',
|
||||||
|
user: true,
|
||||||
|
};
|
||||||
|
const { timerUnit } = generateUnits('job', opts);
|
||||||
|
|
||||||
|
assertStringIncludes(timerUnit, 'WantedBy=default.target');
|
||||||
|
});
|
||||||
|
|
||||||
|
Deno.test('generateUnits ignoriert runAs bei --user', () => {
|
||||||
|
const opts = {
|
||||||
|
exec: '/bin/true',
|
||||||
|
calendar: 'daily',
|
||||||
|
user: true,
|
||||||
|
runAs: 'should-not-appear',
|
||||||
|
};
|
||||||
|
|
||||||
|
const { serviceUnit } = generateUnits('job', opts);
|
||||||
|
|
||||||
|
assert(
|
||||||
|
!serviceUnit.includes('User=should-not-appear'),
|
||||||
|
'User= sollte bei --user nicht enthalten sein',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
@@ -51,14 +51,18 @@ export function generateUnits(name: string, options: TimerOptions): {
|
|||||||
`[Service]`,
|
`[Service]`,
|
||||||
`Type=oneshot`,
|
`Type=oneshot`,
|
||||||
`ExecStart=${options.exec}`,
|
`ExecStart=${options.exec}`,
|
||||||
|
...(options.cwd ? [`WorkingDirectory=${options.cwd}`] : []),
|
||||||
...(options.environment?.map((e) => `Environment=${e}`) ?? []),
|
...(options.environment?.map((e) => `Environment=${e}`) ?? []),
|
||||||
|
...(options.home ? [`Environment=HOME=${options.home}`] : []),
|
||||||
|
...(options.logfile
|
||||||
|
? [
|
||||||
|
`StandardOutput=append:${options.logfile}`,
|
||||||
|
`StandardError=append:${options.logfile}`,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(options.runAs && !options.user ? [`User=${options.runAs}`] : []),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (options.logfile) {
|
|
||||||
unitParts.push(`StandardOutput=append:${options.logfile}`);
|
|
||||||
unitParts.push(`StandardError=append:${options.logfile}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const serviceUnit = unitParts.join('\n');
|
const serviceUnit = unitParts.join('\n');
|
||||||
|
|
||||||
const timerParts = [
|
const timerParts = [
|
||||||
@@ -70,7 +74,7 @@ export function generateUnits(name: string, options: TimerOptions): {
|
|||||||
`Persistent=true`,
|
`Persistent=true`,
|
||||||
``,
|
``,
|
||||||
`[Install]`,
|
`[Install]`,
|
||||||
`WantedBy=timers.target`,
|
`WantedBy=${options.user ? 'default.target' : 'timers.target'}`,
|
||||||
];
|
];
|
||||||
|
|
||||||
const timerUnit = timerParts.join('\n');
|
const timerUnit = timerParts.join('\n');
|
||||||
|
@@ -4,6 +4,9 @@ export interface TimerOptions {
|
|||||||
calendar: string;
|
calendar: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
user?: boolean;
|
user?: boolean;
|
||||||
|
runAs?: string;
|
||||||
|
home?: string;
|
||||||
|
cwd?: string;
|
||||||
output?: string;
|
output?: string;
|
||||||
after?: string[];
|
after?: string[];
|
||||||
environment?: string[];
|
environment?: string[];
|
||||||
|
Reference in New Issue
Block a user