feature/pp-58-runtime-image-contract (#68)
## Summary This PR tightens repository quality enforcement around markdown and documentation. It adds `markdownlint` to the `cicd-checks` workflow, expands pre-commit coverage so markdown files are checked repo-wide, and cleans up the PP-58 documentation set to keep it aligned with the new policy. ## What changed - Added a `Markdownlint Check` entry to `.gitea/workflows/cicd-checks.yaml` - Added `markdownlint` to pre-commit and widened prettier coverage to include markdown files across the repo - Updated `README.md` to satisfy markdownlint line-length rules - Normalized the PP-58 documentation set: - `docs/DEPLOYABLE_RUNTIME_CONTRACT.md` - `docs/adr/ADR003-deployable_runtime_image_contract.md` - `docs/DEVELOPMENT.md` - `docs/CICD_MULTI_STAGE_BUILD.md` - `docs/CICD_TROUBLESHOOTING_GUIDE.md` - `docs/SECURE_DOCKER_CICD.md` ## Validation - `pre-commit run markdownlint --files README.md docs/DEPLOYABLE_RUNTIME_CONTRACT.md` - `pre-commit run prettier --files README.md docs/DEPLOYABLE_RUNTIME_CONTRACT.md` - Workflow YAML validation returned no errors ## Notes This change does not alter application runtime behavior. It only strengthens CI and documentation quality enforcement. Co-authored-by: copilotcoder <copilotcoder@darkhelm.org> Reviewed-on: #68
This commit was merged in pull request #68.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* End-to-end tests using Playwright
|
||||
*/
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
// Helper function for network-resilient page navigation
|
||||
async function navigateWithRetry(page: any, url: string, maxRetries = 3): Promise<void> {
|
||||
@@ -10,54 +10,54 @@ async function navigateWithRetry(page: any, url: string, maxRetries = 3): Promis
|
||||
try {
|
||||
await page.goto(url, {
|
||||
waitUntil: 'networkidle',
|
||||
timeout: process.env.CI ? 45000 : 30000
|
||||
})
|
||||
return // Success
|
||||
timeout: process.env.CI ? 45000 : 30000,
|
||||
});
|
||||
return; // Success
|
||||
} catch (error) {
|
||||
if (i === maxRetries - 1) throw error // Last attempt failed
|
||||
console.log(`Navigation attempt ${i + 1} failed, retrying...`)
|
||||
await page.waitForTimeout(2000) // Wait before retry
|
||||
if (i === maxRetries - 1) throw error; // Last attempt failed
|
||||
console.log(`Navigation attempt ${i + 1} failed, retrying...`);
|
||||
await page.waitForTimeout(2000); // Wait before retry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test.describe('Plex Playlist App', () => {
|
||||
test('should display app title', async ({ page }) => {
|
||||
await navigateWithRetry(page, '/')
|
||||
await navigateWithRetry(page, '/');
|
||||
|
||||
// Wait for the app to fully load with network resilience
|
||||
await page.waitForSelector('h1', { timeout: 15000 })
|
||||
await expect(page.locator('h1')).toContainText('Plex Playlist')
|
||||
})
|
||||
await page.waitForSelector('h1', { timeout: 15000 });
|
||||
await expect(page.locator('h1')).toContainText('Plex Playlist');
|
||||
});
|
||||
|
||||
test('should have welcome message', async ({ page }) => {
|
||||
await navigateWithRetry(page, '/')
|
||||
await navigateWithRetry(page, '/');
|
||||
|
||||
// Wait for the welcome message to appear with network resilience
|
||||
await page.waitForSelector('p', { timeout: 15000 })
|
||||
await expect(page.locator('p')).toContainText('Welcome to the Plex Playlist Manager')
|
||||
})
|
||||
await page.waitForSelector('p', { timeout: 15000 });
|
||||
await expect(page.locator('p')).toContainText('Welcome to the Plex Playlist Manager');
|
||||
});
|
||||
|
||||
test('should load without errors', async ({ page }) => {
|
||||
const errors: string[] = []
|
||||
const errors: string[] = [];
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
// Filter out network-related errors that are acceptable in CI
|
||||
const errorText = msg.text()
|
||||
const errorText = msg.text();
|
||||
if (!errorText.includes('net::') && !errorText.includes('Failed to fetch')) {
|
||||
errors.push(errorText)
|
||||
errors.push(errorText);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
await navigateWithRetry(page, '/')
|
||||
await navigateWithRetry(page, '/');
|
||||
|
||||
// Wait for app to fully load with extra time for network instability
|
||||
await page.waitForLoadState('networkidle')
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Give extra time for any async operations in unstable networks
|
||||
await page.waitForTimeout(process.env.CI ? 3000 : 1000)
|
||||
await page.waitForTimeout(process.env.CI ? 3000 : 1000);
|
||||
|
||||
expect(errors).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
expect(errors).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import App from '@/App.vue'
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import App from '@/App.vue';
|
||||
|
||||
describe('App.vue', () => {
|
||||
it('renders properly', () => {
|
||||
const wrapper = mount(App)
|
||||
expect(wrapper.text()).toContain('Plex Playlist')
|
||||
})
|
||||
})
|
||||
const wrapper = mount(App);
|
||||
expect(wrapper.text()).toContain('Plex Playlist');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user