Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/wg-easy-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
tags: [ 'v*' ]
paths:
- 'applications/wg-easy/**'
- '!applications/wg-easy/README.md'
- '.github/workflows/wg-easy-image.yml'
pull_request:
paths:
Expand Down
48 changes: 42 additions & 6 deletions .github/workflows/wg-easy-pr-validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ on:
description: 'Run in test mode'
required: false
default: 'true'
workflow_call:
inputs:
channel-name:
description: 'Channel name override (defaults to branch-derived name)'
type: string
default: ''
customer-name:
description: 'Customer name override (defaults to branch-derived name)'
type: string
default: ''
cleanup-cluster:
description: 'Delete test clusters after completion'
type: boolean
default: false
secrets:
WG_EASY_REPLICATED_API_TOKEN:
required: true
outputs:
test-result:
description: 'Result of the test-deployment job'
value: ${{ jobs.test-deployment.result }}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -44,12 +65,19 @@ jobs:
- name: Set branch and channel variables
id: vars
run: |
# Branch name preserves original case for resource naming (clusters, customers)
BRANCH_NAME="${{ github.head_ref || github.ref_name }}"
# Channel name is normalized to lowercase with hyphens for Replicated channels
CHANNEL_NAME=$(echo "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | tr '/' '-')
# Customer name uses normalized branch name for idempotent resource creation
CUSTOMER_NAME="${CHANNEL_NAME}"
# Use input overrides when called via workflow_call (e.g. from the weekly test workflow)
if [ -n "${{ inputs.channel-name }}" ]; then
CHANNEL_NAME="${{ inputs.channel-name }}"
BRANCH_NAME="$CHANNEL_NAME"
CUSTOMER_NAME="${{ inputs.customer-name || inputs.channel-name }}"
else
# Branch name preserves original case for resource naming (clusters, customers)
BRANCH_NAME="${{ github.head_ref || github.ref_name }}"
# Channel name is normalized to lowercase with hyphens for Replicated channels
CHANNEL_NAME=$(echo "$BRANCH_NAME" | tr '[:upper:]' '[:lower:]' | tr '/' '-')
# Customer name uses normalized branch name for idempotent resource creation
CUSTOMER_NAME="${CHANNEL_NAME}"
fi
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
echo "channel-name=$CHANNEL_NAME" >> $GITHUB_OUTPUT
echo "customer-name=$CUSTOMER_NAME" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -756,6 +784,14 @@ jobs:
echo "Started: $(date -u)"
echo "Status: Complete"

- name: Cleanup test cluster
if: always() && inputs.cleanup-cluster
run: |
K8S_VERSION_NORMALIZED=$(echo "${{ matrix.k8s-version }}" | tr '.' '-')
CLUSTER_NAME="${{ needs.setup.outputs.channel-name }}-$K8S_VERSION_NORMALIZED-${{ matrix.distribution }}-${{ github.run_number }}"
echo "Removing cluster: $CLUSTER_NAME"
replicated cluster rm --name "$CLUSTER_NAME" || echo "Cluster cleanup failed or already removed"

- name: Upload debug logs
if: failure()
uses: actions/upload-artifact@v4
Expand Down
212 changes: 212 additions & 0 deletions .github/workflows/wg-easy-weekly-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
---
name: WG-Easy Weekly Test - Verify Chart Installation

on:
schedule:
# Run every Monday at 9:00 AM UTC (1:00 AM PST / 4:00 AM EST)
- cron: '0 9 * * 1'
workflow_dispatch:
inputs:
notify_on_success:
description: 'Send notification even on success'
required: false
default: 'false'
type: boolean

concurrency:
group: wg-easy-weekly-test
cancel-in-progress: false

jobs:
run-tests:
uses: ./.github/workflows/wg-easy-pr-validation.yaml
with:
channel-name: weekly-test
customer-name: weekly-test-customer
cleanup-cluster: true
secrets:
WG_EASY_REPLICATED_API_TOKEN: ${{ secrets.WG_EASY_REPLICATED_API_TOKEN }}

notify-on-failure:
runs-on: ubuntu-24.04
needs: run-tests
if: failure()
permissions:
issues: write
steps:
- name: Create GitHub Issue on Failure
uses: actions/github-script@v7
with:
Comment thread
adamancini marked this conversation as resolved.
script: |
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const issueTitle = `[Weekly Test Failure] WG-Easy chart installation failed - ${new Date().toISOString().split('T')[0]}`;
const issueBody = `## Weekly Test Failure Report

The weekly automated test for the WG-Easy Helm chart has failed.

**Workflow Run:** ${runUrl}
**Date:** ${new Date().toISOString()}
**Trigger:** ${context.eventName === 'schedule' ? 'Scheduled weekly test' : 'Manual workflow dispatch'}

### Failed Jobs
Check the workflow run for detailed logs and failure information.

### Next Steps
1. Review the workflow logs at the link above
2. Investigate the root cause of the failure
3. Fix any issues with the chart or dependencies
4. Re-run the workflow to verify the fix

### Related Files
- Chart: \`applications/wg-easy/charts/wg-easy/\`
- Workflow: \`.github/workflows/wg-easy-weekly-test.yaml\`

---
*This issue was automatically created by the weekly test workflow.*`;

// Check if there's already an open issue for today
const issues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'automated-test,wg-easy',
per_page: 10
});

const existingIssue = issues.data.find(issue =>
issue.title.includes('[Weekly Test Failure]') &&
issue.title.includes(new Date().toISOString().split('T')[0])
);

if (existingIssue) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: `Another test failure occurred in the same day.\n\n**Latest Run:** ${runUrl}`
});
console.log(`Updated existing issue #${existingIssue.number}`);
} else {
const issue = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
labels: ['automated-test', 'wg-easy', 'bug']
});
console.log(`Created issue #${issue.data.number}`);
}

notify-on-success:
runs-on: ubuntu-24.04
needs: run-tests
if: success() && (github.event.inputs.notify_on_success == 'true' || github.event_name == 'schedule')
permissions:
issues: write
steps:
- name: Comment on latest open issue if exists
uses: actions/github-script@v7
with:
script: |
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;

const issues = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'automated-test,wg-easy',
sort: 'created',
direction: 'desc',
per_page: 10
});

// Only comment on issues that are weekly test failure reports
const failureIssue = issues.data.find(issue =>
issue.title.includes('[Weekly Test Failure]')
);

if (failureIssue) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: failureIssue.number,
body: `✅ **Weekly test passed!**\n\nThe WG-Easy chart is now installing and working correctly.\n\n**Successful Run:** ${runUrl}\n\nConsider closing this issue if the problem is resolved.`
});
Comment thread
adamancini marked this conversation as resolved.
console.log(`Added success comment to issue #${failureIssue.number}`);
} else {
console.log('No open weekly test failure issues found - weekly test passed successfully!');
}

update-readme-status:
runs-on: ubuntu-24.04
needs: run-tests
if: always() && github.event_name == 'schedule'
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Update README with test results
run: |
README_PATH="applications/wg-easy/README.md"

if [ "${{ needs.run-tests.outputs.test-result }}" == "success" ]; then
STATUS="✅ Passing"
else
STATUS="❌ Failed"
fi

TEST_DATE=$(date -u +"%Y-%m-%d %H:%M UTC")
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"

# Write only the inner content (the markers remain in place as anchors)
cat > /tmp/status_inner.md <<EOF

## Test Status

| Component | Status | Last Tested | Kubernetes Version | Details |
|-----------|--------|-------------|--------------------|---------|
| Chart Installation | ${STATUS} | ${TEST_DATE} | v1.33 / v1.34 / v1.35 | [View Run](${RUN_URL}) |

*Status automatically updated by [weekly test workflow](${RUN_URL})*

EOF

# Replace content between the marker comments, keeping the markers as anchors
sed -i.bak '/<!-- TEST_STATUS_START -->/,/<!-- TEST_STATUS_END -->/{
/<!-- TEST_STATUS_START -->/{
r /tmp/status_inner.md
}
/<!-- TEST_STATUS_START -->/!{/<!-- TEST_STATUS_END -->/!d}
}' "$README_PATH"
rm -f "${README_PATH}.bak"

echo "Updated README with test status: ${STATUS}"

- name: Check for changes
id: check_changes
run: |
if git diff --quiet applications/wg-easy/README.md; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi

- name: Commit and push changes
if: steps.check_changes.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

git add applications/wg-easy/README.md
git commit -m "chore(wg-easy): update test status in README [skip ci]

Automated test status update from weekly test workflow.

Status: ${{ needs.run-tests.outputs.test-result }}
Run: ${{ github.run_id }}"

git push
Comment thread
adamancini marked this conversation as resolved.
31 changes: 31 additions & 0 deletions applications/wg-easy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ This project demonstrates a **composable multi-chart workflow** for packaging an

The target scenario: multiple teams, multiple product verticals, one Replicated release.

<!-- TEST_STATUS_START -->
## Test Status

| Component | Status | Last Tested | Kubernetes Version | Details |
|-----------|--------|-------------|--------------------|---------|
| Chart Installation | ⏳ Pending | Never | v1.33 / v1.34 / v1.35 | - |

*Status automatically updated by weekly test workflow*
<!-- TEST_STATUS_END -->

## The Problem with Monolithic Releases

In a monolithic Replicated application, all components share a single set of release artifacts:
Expand Down Expand Up @@ -148,6 +158,27 @@ Key components:

> **New to Task or Helmfile?** These tools are convenient wrappers around standard Helm and shell commands -- they are not the point of this example. See the [Tooling Guide](docs/tooling-guide.md) for what each tool does, why it was chosen over Make and plain Helm CLI, and how to translate the workflows to your own tooling.

## Automated Testing

### Weekly Chart Validation

The repository includes an automated weekly test workflow that runs every Monday at 9:00 AM UTC to ensure the chart remains installable and functional:

**Workflow:** `.github/workflows/wg-easy-weekly-test.yaml`

**What it tests:**
- Chart validation and linting
- Chart packaging and release creation
- Deployment to a fresh Kubernetes cluster (latest stable version)
- Application health checks and functionality tests

**Notifications:**
- Creates a GitHub Issue automatically when tests fail
- Comments on existing issues when tests pass again
- Can be triggered manually via workflow_dispatch

This provides continuous validation that the chart is always ready to install, even during periods of low development activity.

## Learn More

- [Composable Multi-Chart Walkthrough](../../patterns/composable-multi-chart-walkthrough/README.md) -- end-to-end guided tour of the data flow from chart structure through release assembly
Expand Down
Loading