Skip to main content

Release v1.0.1: CI/CD Simplification

· 7 min read
Eduardez
MoLOS Lead Developer

We're excited to announce MoLOS v1.0.1, a maintenance release focused on simplifying our CI/CD workflows, improving manual release processes, and enhancing production Docker builds. This release makes it easier to maintain and deploy MoLOS while maintaining all the stability of v1.0.0.

What's New in v1.0.1​

CI/CD Simplification​

We've simplified our CI/CD workflows by removing unnecessary pipelines:

# .github/workflows/ci.yml
name: CI

on:
push:
branches: [develop, main]
pull_request:
branches: [develop, main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'

- name: Install dependencies
run: pnpm install

- name: Build
run: pnpm build

- name: Type check
run: pnpm typecheck

Removed Workflows​

The following workflows have been removed to simplify operations:

  • .github/workflows/release.yml - Automated releases
  • .github/workflows/test.yml - Separate test pipeline

These have been consolidated into the main CI workflow and manual release process.

Manual Release Workflow​

We've moved to a manual release workflow for better control:

# Create a release
npm run release

# This will:
# 1. Run all tests
# 2. Update version numbers
# 3. Generate changelog
# 4. Create git tag
# 5. Push to GitHub
# 6. Create GitHub release

Release Script​

The release script automates the manual process:

// scripts/release.ts
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

async function release() {
console.log('Starting release process...');

// Run tests
console.log('Running tests...');
await execAsync('pnpm test');

// Build project
console.log('Building project...');
await execAsync('pnpm build');

// Type check
console.log('Type checking...');
await execAsync('pnpm typecheck');

// Get current version
const { version } = JSON.parse(
await fs.readFile('package.json', 'utf-8')
);

// Create git tag
console.log(`Creating tag v${version}...`);
await execAsync(`git tag -a v${version} -m "Release v${version}"`);

// Push tag
console.log('Pushing tag...');
await execAsync('git push origin v${version}');

// Create GitHub release
console.log('Creating GitHub release...');
await execAsync(`gh release create v${version} --notes "Release v${version}"`);

console.log(`✓ Release v${version} complete!`);
}

release().catch(console.error);

Production Docker Build Improvements​

Multi-Stage Build Optimization​

We've optimized the production Docker build with better layer caching:

FROM node:20-alpine AS base

# Install build dependencies
RUN apk add --no-cache \
ca-certificates \
dumb-init \
gosu

WORKDIR /app

# Copy dependency files
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && \
pnpm install --frozen-lockfile

FROM base AS build

# Copy source code
COPY . .

# Build application
RUN pnpm build

FROM node:20-alpine AS production

# Install runtime dependencies only
RUN apk add --no-cache \
ca-certificates \
dumb-init \
gosu

# Create non-root user
RUN addgroup -g 1001 -S molos && \
adduser -S -u 1001 -G molos molos

WORKDIR /app

# Copy built application
COPY --from=build --chown=molos:molos /app/dist ./dist
COPY --from=build --chown=molos:molos /app/node_modules ./node_modules
COPY --from=build --chown=molos:molos /app/package.json ./package.json

# Copy entrypoint
COPY --chown=molos:molos docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

# Switch to non-root user
USER molos

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"

# Expose port
EXPOSE 3000

# Set environment
ENV NODE_ENV=production

# Use dumb-init for proper signal handling
ENTRYPOINT ["dumb-init", "--"]
CMD ["docker-entrypoint.sh", "node", "dist/index.js"]

Docker Compose Configuration​

Enhanced Docker Compose for production:

version: '3.8'

services:
molos:
image: molos-app:v1.0.1
container_name: molos
restart: unless-stopped
ports:
- "3000:3000"
env_file:
- ~/.molos/secrets/.env
environment:
- NODE_ENV=production
- ORIGIN=${ORIGIN:-https://molos.example.com}
- DATABASE_URL=/data/molos.db
volumes:
- ~/.molos/data:/data
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

volumes:
molos-data:
driver: local

Module Improvements​

Module Version Bump​

We've bumped active module versions:

// modules.config.ts
export const modulesConfig = {
production: {
modules: [
{
id: 'molos-tasks',
repository: 'https://github.com/MoLOS-App/Modules/MoLOS-Tasks',
tag: 'v1.0.3', // Updated from v1.0.2
enabled: true
},
{
id: 'molos-notes',
repository: 'https://github.com/MoLOS-App/Modules/MoLOS-Notes',
tag: 'v1.0.1', // Updated from v1.0.0
enabled: true
}
]
}
};

Module Loading Refinements​

Improved module loading and scoping logic:

// server/modules/loader.ts
export async function loadModule(moduleConfig: ModuleConfig) {
// Validate module configuration
const validation = await validateModule(moduleConfig);
if (!validation.valid) {
throw new ModuleLoadError(
`Module ${moduleConfig.id} is invalid: ${validation.errors.join(', ')}`
);
}

// Load module metadata
const metadata = await getModuleMetadata(moduleConfig);

// Initialize module
const module = await initializeModule(metadata);

// Apply module scoping
await applyModuleScoping(module);

console.log(`✓ Loaded module: ${metadata.name} v${metadata.version}`);

return module;
}

MCP Refinements​

Auth Key Renaming​

We renamed API keys to auth keys for clarity:

// Renamed from apiKey to authKey
export interface MCPAuthKey {
id: string;
name: string;
authKeyHash: string; // Previously apiKeyHash
scopes: string[];
expiresAt: Date | null;
createdAt: Date;
}

MCP Configuration UI​

Enhanced MCP configuration in admin settings:

<!-- src/routes/admin/mcp/+page.svelte -->
<script lang="ts">
import MCPSettings from './MCPSettings.svelte';
import AuthKeys from './AuthKeys.svelte'; // Previously APIKeys

let activeTab = 'settings';
</script>

<div class="mcp-admin">
<nav class="tabs">
<button
class="tab {activeTab === 'settings' ? 'active' : ''}"
onclick={() => activeTab = 'settings'}
>
Settings
</button>
<button
class="tab {activeTab === 'keys' ? 'active' : ''}"
onclick={() => activeTab = 'keys'}
>
Auth Keys
</button>
</nav>

{#if activeTab === 'settings'}
<MCPSettings />
{:else if activeTab === 'keys'}
<AuthKeys />
{/if}
</div>

Admin Settings Refactoring​

We extracted admin settings into modular components:

<!-- src/routes/admin/+page.svelte -->
<script lang="ts">
import GeneralSettings from './components/GeneralSettings.svelte';
import AuthSettings from './components/AuthSettings.svelte';
import ModuleSettings from './components/ModuleSettings.svelte';
import MCPSettings from './components/MCPSettings.svelte';

let activeSection = 'general';

const sections = [
{ id: 'general', label: 'General', component: GeneralSettings },
{ id: 'auth', label: 'Authentication', component: AuthSettings },
{ id: 'modules', label: 'Modules', component: ModuleSettings },
{ id: 'mcp', label: 'MCP', component: MCPSettings }
];
</script>

<div class="admin-page">
<aside class="sidebar">
<nav>
{#each sections as section}
<button
class="nav-item {activeSection === section.id ? 'active' : ''}"
onclick={() => activeSection = section.id}
>
{section.label}
</button>
{/each}
</nav>
</aside>

<main class="content">
{#each sections as section}
{#if activeSection === section.id}
<svelte:component this={section.component} />
{/if}
{/each}
</main>
</div>

Documentation Updates​

Release Notes​

We've added comprehensive release notes for v1.0.0:

# Release v1.0.0

## What's New

- First stable production release
- Production-ready Docker images with security hardening
- All core modules verified and tested
- Comprehensive API documentation

## Migration Guide

See [Migration Guide](/docs/migration-v1-0-0) for upgrading from previous versions.

## Breaking Changes

None from v0.5.0-alpha.

## Known Issues

See [Known Issues](https://github.com/MoLOS-App/MoLOS/issues) for current issues.

Changelog Updates​

Updated changelog to reflect all changes:

# Changelog

## [1.0.1] - 2026-03-18

### Added
- Manual release workflow script
- Enhanced production Docker builds
- Modular admin settings components

### Changed
- Renamed API keys to auth keys (MCP)
- Bumped module versions
- Simplified CI/CD workflows

### Removed
- Automated release workflow
- Separate test pipeline

## [1.0.0] - 2026-03-13

### Added
- First stable production release
- Production Docker images
- All core modules

See full changelog for details.

What's Changed Since v1.0.0​

Bug Fixes​

  • Fixed authentication issues for HTTP deployments
  • Improved module loading and scoping

Improvements​

  • Simplified CI/CD workflows
  • Enhanced production Docker builds
  • Improved admin settings UI
  • Better module version management

Documentation​

  • Added v1.0.0 release notes
  • Added migration guide
  • Updated changelog

Upgrading from v1.0.0​

Quick Upgrade​

# Pull latest changes
git fetch origin
git checkout v1.0.1

# Update dependencies
pnpm install

# Restart application
docker-compose down
docker-compose pull
docker-compose up -d

Manual Upgrade​

# Update dependencies
pnpm install

# No migrations needed

# Build
pnpm build

# Restart
pnpm start

Key Commits​

What's Next​

The v1.0.1 release improves operational simplicity. Our focus for v1.1.0 includes:

  • PostgreSQL support
  • Performance optimizations
  • Enhanced mobile experience
  • Advanced analytics
  • Real-time collaboration features

The v1.0.1 release simplifies operations while maintaining all the stability and features of v1.0.0.