Skip to content

Commit a98ab8e

Browse files
committed
chore: build dynamix.unraid.net with versioning a-la-slackware
1 parent 6bfde19 commit a98ab8e

File tree

15 files changed

+188
-183
lines changed

15 files changed

+188
-183
lines changed

.github/workflows/build-plugin.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,8 @@ jobs:
113113
id: build-plugin
114114
run: |
115115
cd ${{ github.workspace }}/plugin
116-
ls -al
117116
pnpm run build:txz
118-
pnpm run build:plugin --tag="${{ inputs.TAG }}" --base-url="${{ inputs.BASE_URL }}"
117+
pnpm run build:plugin --tag="${{ inputs.TAG }}" --base-url="${{ inputs.BASE_URL }}" --api-version="${{ steps.vars.outputs.API_VERSION }}"
119118
120119
- name: Ensure Plugin Files Exist
121120
run: |

plugin/.nvmrc

Whitespace-only changes.

plugin/builder/build-plugin.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { readFile, writeFile, mkdir, rename } from "fs/promises";
22
import { $ } from "zx";
33
import { escape as escapeHtml } from "html-sloppy-escaper";
44
import { dirname, join } from "node:path";
5-
import { getTxzName, pluginName, startingDir } from "./utils/consts";
5+
import { getTxzName, pluginName, startingDir, defaultArch, defaultBuild } from "./utils/consts";
66
import { getAssetUrl, getPluginUrl } from "./utils/bucket-urls";
77
import { getMainTxzUrl } from "./utils/bucket-urls";
88
import {
@@ -26,7 +26,7 @@ const checkGit = async () => {
2626
}
2727
};
2828

29-
const moveTxzFile = async (txzPath: string, pluginVersion: string) => {
29+
const moveTxzFile = async ({txzPath, pluginVersion}: Pick<PluginEnv, "txzPath" | "pluginVersion">) => {
3030
const txzName = getTxzName(pluginVersion);
3131
await rename(txzPath, join(deployDir, txzName));
3232
};
@@ -50,14 +50,20 @@ const buildPlugin = async ({
5050
tag,
5151
txzSha256,
5252
releaseNotes,
53+
apiVersion,
5354
}: PluginEnv) => {
55+
console.log(`API version: ${apiVersion}`);
56+
5457
// Update plg file
5558
let plgContent = await readFile(getRootPluginPath({ startingDir }), "utf8");
5659

5760
// Update entity values
5861
const entities: Record<string, string> = {
5962
name: pluginName,
6063
version: pluginVersion,
64+
api_version: apiVersion,
65+
arch: defaultArch,
66+
build: defaultBuild,
6167
pluginURL: getPluginUrl({ baseUrl, tag }),
6268
MAIN_TXZ: getMainTxzUrl({ baseUrl, pluginVersion, tag }),
6369
TXZ_SHA256: txzSha256,
@@ -107,7 +113,7 @@ const main = async () => {
107113
await cleanupPluginFiles();
108114

109115
await buildPlugin(validatedEnv);
110-
await moveTxzFile(validatedEnv.txzPath, validatedEnv.pluginVersion);
116+
await moveTxzFile(validatedEnv);
111117
await bundleVendorStore();
112118
} catch (error) {
113119
console.error(error);

plugin/builder/build-txz.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const validateSourceDir = async (validatedEnv: TxzEnv) => {
9191

9292
const buildTxz = async (validatedEnv: TxzEnv) => {
9393
await validateSourceDir(validatedEnv);
94+
console.log(`Package name: ${getTxzName()}`);
9495
const txzPath = join(validatedEnv.txzOutputDir, getTxzName());
9596
await ensureNodeJs();
9697

@@ -99,6 +100,7 @@ const buildTxz = async (validatedEnv: TxzEnv) => {
99100
await cd(join(startingDir, "source", pluginName));
100101
$.verbose = true;
101102

103+
// Create the package using the default package name
102104
await $`${join(startingDir, "scripts/makepkg")} --chown y --compress -${
103105
validatedEnv.compress
104106
} --linkadd y ${txzPath}`;

plugin/builder/cli/setup-plugin-environment.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const safeParseEnvSchema = z.object({
99
ci: z.boolean().optional(),
1010
baseUrl: z.string().url(),
1111
tag: z.string().optional().default(''),
12+
apiVersion: z.string().optional(),
1213

1314
txzPath: z.string().refine((val) => val.endsWith(".txz"), {
1415
message: "TXZ Path must end with .txz",
@@ -24,6 +25,7 @@ const pluginEnvSchema = safeParseEnvSchema.extend({
2425
txzSha256: z.string().refine((val) => val.length === 64, {
2526
message: "TXZ SHA256 must be 64 characters long",
2627
}),
28+
apiVersion: z.string().nonempty("API version is required"),
2729
});
2830

2931
export type PluginEnv = z.infer<typeof pluginEnvSchema>;
@@ -105,6 +107,11 @@ export const setupPluginEnv = async (argv: string[]): Promise<PluginEnv> => {
105107
"Plugin Version in the format YYYY.MM.DD.HHMM",
106108
getPluginVersion()
107109
)
110+
.requiredOption(
111+
"--api-version <version>",
112+
"API Version (e.g. 1.0.0)",
113+
process.env.API_VERSION
114+
)
108115
.option("--tag <tag>", "Tag (used for PR and staging builds)", process.env.TAG)
109116
.option("--release-notes-path <path>", "Path to release notes file")
110117
.option("--ci", "CI mode", process.env.CI === "true")

plugin/builder/utils/bucket-urls.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getTxzName, LOCAL_BUILD_TAG, pluginNameWithExt } from "./consts";
1+
import { getTxzName, LOCAL_BUILD_TAG, pluginNameWithExt, defaultArch, defaultBuild } from "./consts";
22

33
// Define a common interface for URL parameters
44
interface UrlParams {
@@ -44,7 +44,7 @@ export const getPluginUrl = (params: UrlParams): string =>
4444

4545
/**
4646
* Get the URL for the main TXZ file
47-
* ex. returns = BASE_URL/TAG/dynamix.unraid.net-4.1.3.txz
47+
* ex. returns = BASE_URL/TAG/dynamix.unraid.net-4.1.3-x86_64-1.txz
4848
*/
4949
export const getMainTxzUrl = (params: TxzUrlParams): string =>
50-
getAssetUrl(params, getTxzName(params.pluginVersion));
50+
getAssetUrl(params, getTxzName(params.pluginVersion, defaultArch, defaultBuild));

plugin/builder/utils/consts.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
export const pluginName = "dynamix.unraid.net" as const;
22
export const pluginNameWithExt = `${pluginName}.plg` as const;
33

4-
export const getTxzName = (version?: string) =>
5-
version ? `${pluginName}-${version}.txz` : `${pluginName}.txz`;
4+
// Default architecture and build number for Slackware package
5+
export const defaultArch = "x86_64" as const;
6+
export const defaultBuild = "1" as const;
7+
8+
// Get the txz name following Slackware naming convention: name-version-arch-build.txz
9+
export const getTxzName = (version?: string, arch: string = defaultArch, build: string = defaultBuild) =>
10+
version ? `${pluginName}-${version}-${arch}-${build}.txz` : `${pluginName}.txz`;
611
export const startingDir = process.cwd();
712

813
export const BASE_URLS = {

plugin/builder/utils/nodejs-helper.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,21 @@ import { get } from "https";
55
import { $ } from "zx";
66
import { startingDir } from "./consts";
77

8+
const findNvmrc = () => {
9+
const nvmrcPaths = [
10+
join(startingDir, "..", ".nvmrc"),
11+
join(startingDir, ".nvmrc"),
12+
];
13+
for (const nvmrcPath of nvmrcPaths) {
14+
if (existsSync(nvmrcPath)) {
15+
return nvmrcPath;
16+
}
17+
}
18+
throw new Error("NVMRC file not found");
19+
}
820
// Read Node.js version from .nvmrc
9-
const NVMRC_PATH = join(startingDir, "..", ".nvmrc");
21+
const NVMRC_PATH = findNvmrc();
22+
console.log(`NVMRC_PATH: ${NVMRC_PATH}`);
1023
const NODE_VERSION = readFileSync(NVMRC_PATH, "utf8").trim();
1124

1225
const NODE_FILENAME = `node-v${NODE_VERSION}-linux-x64.tar.xz`;

plugin/docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ services:
77
- ./:/app
88
- /app/node_modules
99
- ../.git:/app/.git
10+
- ../.nvmrc:/app/.nvmrc
1011
- ./source:/app/source
1112
- ./scripts:/app/scripts
1213
- ../unraid-ui/dist-wc:/app/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/unraid-components/uui
@@ -19,3 +20,4 @@ services:
1920
- HOST_LAN_IP=${HOST_LAN_IP}
2021
- CI=${CI:-false}
2122
- TAG=${TAG}
23+
- API_VERSION=${API_VERSION}

plugin/docs/migration/progress.md

Lines changed: 28 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,176 +1,43 @@
1-
# Plugin Migration to Slackware Package: Progress Report
2-
3-
## Overview
4-
This document tracks our progress in migrating the Unraid plugin to a native Slackware package.
1+
# Migration Progress: Plugin to Slackware Package
52

63
## Completed Tasks
74

8-
### Package Structure and Slackware Integration
9-
- Created standard Slackware package description file (`slack-desc`) for the dynamix.unraid.net package
10-
- Implemented proper Slackware init system integration:
11-
- Modified `rc.unraid-api` script to include standard start/stop/restart/status functions
12-
- Updated approach to use native Slackware init system rather than System V directories
13-
- Added boot-time node modules dependency restoration to the `start()` function
14-
- Moved environment setup from setup_api.sh to rc.unraid-api to ensure it's available at boot
15-
- The service will now properly start on boot if pre-installed in the OS
16-
17-
### Installation Scripts
18-
- Added `doinst.sh` script to handle post-installation tasks like creating symlinks and starting services
19-
- Implemented support for both install and remove operations in doinst.sh using Slackware's installation mode parameter
20-
- Modularized the installation logic into separate scripts for better maintainability:
21-
- `setup_api.sh`: Handles API setup, symlinks, and service startup
22-
- `file_patches.sh`: Manages file patches and system configurations
23-
- `cleanup.sh`: Performs uninstallation and cleanup operations
24-
- Improved doinst.sh script maintainability:
25-
- Added SCRIPTS_DIR variable to centralize script paths
26-
- Replaced all hardcoded script paths with the variable reference
27-
28-
### Cleanup and Removal Operations
29-
- File restoration scripts have been successfully migrated from the plugin's inline code to the modular cleanup.sh script
30-
- Enhanced cleanup.sh to handle both installation and removal scenarios with a mode parameter ('restore' or 'cleanup')
31-
- Updated doinst.sh to call cleanup.sh with the appropriate mode for both installation and removal operations
32-
- Simplified the plugin XML file by removing all cleanup code, as these operations are now entirely handled by the Slackware package system
33-
- Updated the removal script to rely on the Slackware package system instead of manually running cleanup operations
34-
- Consolidated all cleanup scripts into a single robust shell script:
35-
- Merged functionality from the PHP `cleanup_operations.php` script into the shell-based `cleanup.sh`
36-
- Removed dependency on PHP for cleanup operations, making it more compatible with native Slackware tooling
37-
- Created a unified script that handles both file restoration (during installation) and full cleanup (during removal)
38-
39-
### Node.js and Dependencies Management
40-
- Removed Node.js symlinking from both the doinst.sh script and plugin file as this will be handled by the build-txz script
41-
- Implemented vendor archive handling in the rc.unraid-api script:
42-
- Proper path definitions for the vendor archive
43-
- Comprehensive dependency restoration function that checks file existence and disk space
44-
- Archive creation function for backing up node_modules
45-
- Command-line interface for both restoration and archiving operations
46-
- Automatic restoration during service startup if node_modules are missing
47-
48-
### Script Consolidation
49-
- Eliminated duplicate cleanup scripts by standardizing on the version at usr/local/share/dynamix.unraid.net/install/scripts/cleanup.sh
50-
- Eliminated duplicate setup_api.sh scripts by standardizing on the version at usr/local/share/dynamix.unraid.net/install/scripts/setup_api.sh
5+
### 2024-05-XX
516

52-
### POSIX Compatibility
53-
- Ensured POSIX shell compatibility by replacing Bash-specific array syntax with POSIX-compliant for loops
54-
- Fixed POSIX shell compatibility in verify_install.sh:
55-
- Replaced Bash-specific array syntax with POSIX-compliant string lists
56-
- Maintained identical functionality while ensuring /bin/sh compatibility
57-
- Eliminated SC3030 shellcheck warnings about undefined arrays in POSIX sh
58-
- Removed unused check_file() function to fix SC2317 unreachable command warning
7+
- Modified `setup_api.sh` to only use the Slackware package version
8+
- Removed all fallback logic for bundle detection
9+
- Now exclusively uses version from dynamix.unraid.net Slackware package
10+
- Exit with error if package not found instead of falling back to defaults
11+
- Simplified logic for finding and using the correct bundle archives
12+
- Fixed ShellCheck SC2010 violations by replacing `ls | grep` with proper glob pattern matching
5913

60-
### Verification and TAG Handling
61-
- Created post-installation verification script:
62-
- Checks for existence of critical files and directories
63-
- Verifies executable permissions on important scripts
64-
- Validates startup and shutdown configurations in rc.M, rc.local, rc.0, and rc.6 files
65-
- Provides color-coded output for easy readability
66-
- Integrated with doinst.sh to run automatically after installation
67-
- Added TAG handling from plugin XML file to the Slackware package
14+
## Pending Tasks
6815

69-
### Slackware-Native Init System Changes
70-
- Completely rewrote the startup/shutdown system to use Slackware's native approach:
71-
- Removed all code trying to create or use System V-style rc*.d directories
72-
- Implemented direct modification of rc.M and rc.local for service startup
73-
- Implemented direct modification of rc.0 and rc.6 for service shutdown
74-
- Created a generic `configure_script()` function to handle both startup and shutdown scripts
75-
- Updated verification script to check for the proper Slackware initialization entries
76-
- The setup_api.sh script now properly modifies rc.M, rc.local, rc.0, and rc.6 files
16+
- Update installation process to use native Slackware packaging
17+
- Modify build scripts to create proper Slackware packages
18+
- Update boot scripts to conform with Slackware standards
19+
- Test package installation/upgrade flows
20+
- Implement proper package dependencies
21+
- Ensure all scripts use proper Slackware paths and conventions
7722

78-
## Recent Decisions
79-
- Kept version compatibility check in the plugin file rather than the Slackware package:
80-
- Recognized that doinst.sh runs after files are already installed
81-
- Version checking needs to happen before installation to be effective
82-
- The PHP check in the plugin file is the best place for this validation
83-
- Removed TAG handling from doinst.sh and reverted to plugin file approach:
84-
- Discovered TAG isn't properly set in the Unraid environment within doinst.sh context
85-
- Reverted to using the plugin file for TAG handling to ensure proper functionality
86-
- Identified issue with runlevel directory creation approach:
87-
- Discovered that in Slackware, the rc.0 and rc.6 files are actual files, not directories
88-
- Completely redesigned the approach to use Slackware's native init system
89-
- Now directly modifying rc.M and rc.local for startup, rc.0 and rc.6 for shutdown
23+
## In Progress
9024

91-
## Removed Components
92-
- Removed redundant build-slackware-package.sh script:
93-
- Eliminated duplicate functionality as we now use build-txz.ts for package creation
94-
- Simplified build tooling to use a single TypeScript-based build process
95-
- Removed makepkg-usage.md documentation:
96-
- Determined that direct makepkg usage documentation is unnecessary
97-
- Package creation is now fully handled by the build-txz.ts script
98-
- Removed System V-style init system code:
99-
- Eliminated all code related to rc*.d directories that don't exist in Slackware
100-
- Replaced with native Slackware init system modification approach
25+
1. Refactoring `build-plugin.ts` to better support Slackware package format.
26+
2. Implementing standard Slackware package scripts (doinst.sh, etc.)
10127

10228
## Next Steps
103-
- Document complete migration process with testing results
104-
- Review and ensure all file permissions are set correctly
105-
- Test package installation and removal
106-
- Verify that all services start correctly after installation
107-
108-
## Implementation Notes
109-
- Disk space verification checks are not needed in the native package since it will be pre-installed in Unraid
110-
- Gzip availability checks are unnecessary for the native package
111-
- DNS resolution checks are unnecessary and should be removed from the plugin file
112-
- Plugin staging conflict check is outdated and no longer needed
113-
- Full SlackBuild script is not necessary since we're not compiling code; direct use of `makepkg` is simpler
114-
- Version compatibility checks should remain in the plugin file since they need to run before installation
115-
116-
## Recent Improvements
117-
- Enhanced Firefox configuration in file_patches.sh:
118-
- Replaced hardcoded Firefox profile path with dynamic profile detection
119-
- Added fallback handling when Firefox profile cannot be found
120-
- Improved user feedback with status messages about configuration changes
121-
- Made the script more resilient to Firefox profile directory changes in future Unraid versions
122-
- Improved POSIX and shellcheck compliance in cleanup.sh:
123-
- Fixed SC2046 warning in process termination code by properly handling pidof with no results
124-
- Improved ps/grep/kill pattern to safely handle cases with no matching processes
125-
- Prevented non-zero exit codes during cleanup process to ensure smooth uninstallation
126-
- Enhanced reliability of the script in edge cases like when no processes are running
127-
- Fixed base64 encoding to prevent line wrapping in HTTP POST data by piping through tr -d '\n'
128-
- Enhanced POSIX compatibility in shell scripts:
129-
- Replaced echo statements with escape sequences (\n) with printf commands
130-
- Fixed issue where /bin/sh implementations (like dash) print literal \n instead of interpreting them
131-
- Improved formatting of status messages in cleanup.sh with proper newlines
132-
- Ensured better cross-platform compatibility across different shell implementations
133-
- Created advanced init script configuration:
134-
- Implemented a unified script function that handles both startup and shutdown script modifications
135-
- Added intelligent handling of script placement (end of file for startup, beginning for shutdown)
136-
- Made the verification script more robust to check both potential startup locations (rc.M and rc.local)
137-
- Added conditional checks to only setup flash_backup if it exists
13829

139-
## Bug Fixes
140-
- Fixed malformed sed pattern in cleanup.sh:
141-
- Changed `sed -i '#robots.txt any origin/d'` to use standard slash delimiters
142-
- Replaced with `sed -i '/#robots.txt any origin/d'` to correctly match and delete the pattern
143-
- This ensures the robots.txt origin line is properly removed from rc.nginx during cleanup
144-
- Fixed issue in rc6.d and rc0.d directory creation:
145-
- Previously attempted to create and use rc0.d/rc6.d directories that don't exist in Slackware
146-
- Completely rewrote the approach to directly modify rc.0 and rc.6 files
147-
- Now correctly configures shutdown using Slackware's native approach
30+
1. Create standard Slackware package structure
31+
- Create install directory with doinst.sh script
32+
- Setup proper Slackware package metadata
14833

149-
## Changes Implemented
34+
2. Utilize native Slackware tooling for:
35+
- Package installation
36+
- Service management
37+
- Version tracking
15038

151-
### rc.unraid-api Script
152-
- Added functionality to start flash backup service during API service startup
153-
- This ensures that flash backup is running whenever the API service is started
39+
3. Update vendor storage mechanism to align with Slackware standards
15440

155-
### setup_api.sh Script
156-
- Completely redesigned to use Slackware's native initialization system
157-
- Now properly configures both startup (in rc.M and rc.local) and shutdown (in rc.0 and rc.6)
158-
- Created a unified `configure_script()` function that handles all script modifications
159-
- Made startup/shutdown script handling more intelligent and robust
41+
## References
16042

161-
## API Setup Script Validation
162-
- Identified issue with `setup_api.sh` not executing properly during package installation:
163-
- Despite being called correctly from `doinst.sh`, the script fails to create necessary symlinks
164-
- Manual execution of the script after installation was required to properly set up API
165-
- Key symptoms include missing symlinks that should have been created during installation
166-
- Further troubleshooting needed to determine why the script doesn't function when called by doinst.sh
167-
- Potential issues:
168-
- Path resolution differences when called from doinst.sh vs manual execution
169-
- Permission issues during package installation process
170-
- Environment variable differences between package install context and manual execution
171-
- Action item: Add logging to doinst.sh and setup_api.sh to debug execution flow during installation
172-
173-
## Pending Tasks
174-
- Continue migrating plugin components to follow Slackware package standards
175-
- Review and ensure all necessary init scripts are properly configured
176-
- Test the startup and shutdown sequences for all services
43+
- The setup_api.sh script (at plugin/source/dynamix.unraid.net/usr/local/share/dynamix.unraid.net/install/scripts/) already implements some Slackware-style package detection for getting API version.

0 commit comments

Comments
 (0)