Skip to content

Commit f426b88

Browse files
committed
feat: Complete implementation of all YAML configurations (v0.0.5)
- Implemented complete parsing and validation of all YAML configuration options - Added support for nested configuration values (agents.behavior.*) - Added configuration validation (types, ranges, valid values) - Fixed all GitHub URLs to use correct repository name (CodeReviewGuardian) - Added AGENTS_CONFIG.md to Composer package files - Updated README with Current Status section - Enhanced script output to show all configuration values - Updated CHANGELOG and UPGRADING documentation - All configurations now parsed, validated, displayed and applied correctly
1 parent 4561412 commit f426b88

10 files changed

Lines changed: 982 additions & 57 deletions

File tree

.github/workflows/release.yml

Lines changed: 205 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ name: Create Release
33
on:
44
push:
55
tags:
6-
- 'v*' # Se dispara cuando se sube un tag que empieza con 'v'
6+
- 'v*' # Triggers when a tag starting with 'v' is pushed
77

88
jobs:
99
release:
1010
name: Create GitHub Release
1111
runs-on: ubuntu-latest
1212
permissions:
13-
contents: write # Necesario para crear releases
13+
contents: write # Required to create releases
1414

1515
steps:
1616
- name: Checkout code
1717
uses: actions/checkout@v6
1818
with:
19-
fetch-depth: 0 # Necesario para obtener el historial completo y el mensaje del tag
19+
fetch-depth: 0 # Required to get full history and tag message
2020

2121
- name: Get tag name
2222
id: tag
@@ -26,12 +26,12 @@ jobs:
2626
id: tag_message
2727
run: |
2828
TAG_NAME=${GITHUB_REF#refs/tags/}
29-
# Obtener el mensaje del tag anotado, o usar el nombre del tag si no hay mensaje
29+
# Get annotated tag message, or use tag name if no message
3030
TAG_MESSAGE=$(git tag -l --format='%(contents)' "$TAG_NAME" 2>/dev/null || echo "")
3131
if [ -z "$TAG_MESSAGE" ]; then
3232
TAG_MESSAGE="Release $TAG_NAME"
3333
fi
34-
# Preservar saltos de línea usando heredoc (no se necesita escape)
34+
# Preserve newlines using heredoc (no escaping needed)
3535
{
3636
echo "MESSAGE<<EOF"
3737
echo "$TAG_MESSAGE"
@@ -42,23 +42,64 @@ jobs:
4242
id: version
4343
run: |
4444
TAG_NAME=${GITHUB_REF#refs/tags/}
45-
# Remover el prefijo 'v' si existe
45+
# Remove 'v' prefix if exists
4646
VERSION=${TAG_NAME#v}
4747
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
4848
49+
- name: Get previous tag
50+
id: previous_tag
51+
run: |
52+
TAG_NAME=${GITHUB_REF#refs/tags/}
53+
# Get the previous tag (excluding the current one)
54+
PREVIOUS_TAG=$(git tag -l 'v*' | sort -V | grep -B1 "^$TAG_NAME$" | grep -v "^$TAG_NAME$" | tail -1 || echo "")
55+
if [ -z "$PREVIOUS_TAG" ]; then
56+
# If no previous tag found, use the first commit
57+
PREVIOUS_TAG=$(git rev-list --max-parents=0 HEAD 2>/dev/null || echo "")
58+
fi
59+
echo "PREVIOUS_TAG=$PREVIOUS_TAG" >> $GITHUB_OUTPUT
60+
echo "Previous tag: $PREVIOUS_TAG"
61+
62+
- name: Get commits between tags
63+
id: commits
64+
run: |
65+
TAG_NAME=${GITHUB_REF#refs/tags/}
66+
PREVIOUS_TAG="${{ steps.previous_tag.outputs.PREVIOUS_TAG }}"
67+
68+
if [ -n "$PREVIOUS_TAG" ]; then
69+
# Get commits between previous tag and current tag
70+
COMMITS=$(git log --pretty=format:"- %s (%h)" "$PREVIOUS_TAG..$TAG_NAME" 2>/dev/null || echo "")
71+
if [ -n "$COMMITS" ]; then
72+
echo "HAS_COMMITS=true" >> $GITHUB_OUTPUT
73+
{
74+
echo "COMMITS<<EOF"
75+
echo "$COMMITS"
76+
echo "EOF"
77+
} >> $GITHUB_OUTPUT
78+
echo "Found $(echo "$COMMITS" | wc -l) commits between $PREVIOUS_TAG and $TAG_NAME"
79+
else
80+
echo "HAS_COMMITS=false" >> $GITHUB_OUTPUT
81+
echo "No commits found between $PREVIOUS_TAG and $TAG_NAME"
82+
fi
83+
else
84+
echo "HAS_COMMITS=false" >> $GITHUB_OUTPUT
85+
echo "No previous tag found, skipping commits"
86+
fi
87+
4988
- name: Get changelog entry
5089
id: changelog
5190
run: |
5291
VERSION="${{ steps.version.outputs.VERSION }}"
5392
CHANGELOG_FILE="docs/CHANGELOG.md"
54-
93+
5594
if [ -f "$CHANGELOG_FILE" ]; then
56-
# Buscar la sección del changelog para esta versión
57-
# Busca líneas que empiecen con ## seguido de la versión (con o sin v)
58-
CHANGELOG_ENTRY=$(awk "/^## \[?$VERSION\]?/ {flag=1; next} /^## \[?[0-9]/ {flag=0} flag" "$CHANGELOG_FILE" 2>/dev/null || echo "")
59-
95+
# Search changelog section for this version
96+
# Match patterns like: ## [0.0.4] or ## 0.0.4
97+
# Escape dots in version for regex
98+
VERSION_ESCAPED=$(echo "$VERSION" | sed 's/\./\\./g')
99+
CHANGELOG_ENTRY=$(awk "/^## \[$VERSION_ESCAPED\]/ {flag=1; next} /^## \[?[0-9]/ {flag=0} flag" "$CHANGELOG_FILE" 2>/dev/null || echo "")
100+
60101
if [ -n "$CHANGELOG_ENTRY" ]; then
61-
# Preservar saltos de línea usando heredoc (no se necesita escape)
102+
# Preserve newlines using heredoc (no escaping needed)
62103
echo "HAS_CHANGELOG=true" >> $GITHUB_OUTPUT
63104
{
64105
echo "ENTRY<<EOF"
@@ -67,26 +108,165 @@ jobs:
67108
} >> $GITHUB_OUTPUT
68109
else
69110
echo "HAS_CHANGELOG=false" >> $GITHUB_OUTPUT
111+
echo "Warning: No changelog entry found for version $VERSION" >&2
70112
fi
71113
else
72114
echo "HAS_CHANGELOG=false" >> $GITHUB_OUTPUT
115+
echo "Warning: CHANGELOG file not found at $CHANGELOG_FILE" >&2
73116
fi
74117
118+
- name: Check if release exists and update if needed
119+
id: check-existing
120+
uses: actions/github-script@v7
121+
with:
122+
script: |
123+
const tagName = '${{ steps.tag.outputs.TAG_NAME }}';
124+
125+
try {
126+
const { data: releases } = await github.rest.repos.listReleases({
127+
owner: context.repo.owner,
128+
repo: context.repo.repo,
129+
per_page: 100
130+
});
131+
132+
const existingRelease = releases.find(r => r.tag_name === tagName);
133+
134+
if (existingRelease) {
135+
const hasChangelog = (existingRelease.body || '').includes('## Changelog');
136+
core.setOutput('exists', 'true');
137+
core.setOutput('release_id', existingRelease.id.toString());
138+
core.setOutput('has_changelog', hasChangelog ? 'true' : 'false');
139+
console.log('Release ' + tagName + ' already exists (ID: ' + existingRelease.id + '), has changelog: ' + hasChangelog);
140+
} else {
141+
core.setOutput('exists', 'false');
142+
console.log('Release ' + tagName + ' does not exist, will create new one');
143+
}
144+
} catch (error) {
145+
console.log('Error checking existing releases:', error.message);
146+
core.setOutput('exists', 'false');
147+
}
148+
149+
- name: Update existing release
150+
if: steps.check-existing.outputs.exists == 'true'
151+
uses: actions/github-script@v7
152+
env:
153+
TAG_NAME: ${{ steps.tag.outputs.TAG_NAME }}
154+
TAG_MESSAGE: ${{ steps.tag_message.outputs.MESSAGE }}
155+
CHANGELOG_ENTRY: ${{ steps.changelog.outputs.ENTRY }}
156+
COMMITS: ${{ steps.commits.outputs.COMMITS }}
157+
HAS_CHANGELOG: ${{ steps.changelog.outputs.HAS_CHANGELOG }}
158+
HAS_COMMITS: ${{ steps.commits.outputs.HAS_COMMITS }}
159+
RELEASE_ID: ${{ steps.check-existing.outputs.release_id }}
160+
with:
161+
script: |
162+
const releaseId = parseInt(process.env.RELEASE_ID);
163+
const tagName = process.env.TAG_NAME;
164+
const tagMessage = process.env.TAG_MESSAGE || '';
165+
const changelogEntry = process.env.CHANGELOG_ENTRY || '';
166+
const commits = process.env.COMMITS || '';
167+
const hasChangelog = process.env.HAS_CHANGELOG === 'true';
168+
const hasCommits = process.env.HAS_COMMITS === 'true';
169+
const isPrerelease = tagName.includes('-alpha') || tagName.includes('-beta') || tagName.includes('-rc');
170+
171+
// Build release body - include tag message, changelog, and commits
172+
let releaseBody = tagMessage;
173+
174+
if (hasChangelog && changelogEntry) {
175+
releaseBody += '\n\n## Changelog\n\n' + changelogEntry;
176+
console.log('📝 Changelog entry found (' + changelogEntry.split('\n').length + ' lines)');
177+
} else {
178+
console.log('⚠️ No changelog entry found for version ' + tagName);
179+
}
180+
181+
if (hasCommits && commits) {
182+
releaseBody += '\n\n## Commits\n\n' + commits;
183+
console.log('📝 Commits found (' + commits.split('\n').length + ' commits)');
184+
} else {
185+
console.log('ℹ️ No commits found between tags');
186+
}
187+
188+
try {
189+
await github.rest.repos.updateRelease({
190+
owner: context.repo.owner,
191+
repo: context.repo.repo,
192+
release_id: releaseId,
193+
body: releaseBody,
194+
prerelease: isPrerelease,
195+
make_latest: !isPrerelease // Mark as latest if not prerelease
196+
});
197+
if (hasChangelog && changelogEntry) {
198+
console.log('✅ Updated release ' + tagName + ' with complete changelog');
199+
} else {
200+
console.log('✅ Updated release ' + tagName + ' (no changelog available)');
201+
}
202+
203+
// Verify latest status
204+
if (!isPrerelease) {
205+
console.log('✅ Release ' + tagName + ' marked as latest (make_latest: true)');
206+
}
207+
} catch (error) {
208+
console.error('❌ Error updating release ' + tagName + ':', error.message);
209+
throw error;
210+
}
211+
75212
- name: Create Release
76-
uses: softprops/action-gh-release@v2
213+
if: steps.check-existing.outputs.exists != 'true'
214+
uses: actions/github-script@v7
215+
env:
216+
TAG_NAME: ${{ steps.tag.outputs.TAG_NAME }}
217+
TAG_MESSAGE: ${{ steps.tag_message.outputs.MESSAGE }}
218+
CHANGELOG_ENTRY: ${{ steps.changelog.outputs.ENTRY }}
219+
COMMITS: ${{ steps.commits.outputs.COMMITS }}
220+
HAS_CHANGELOG: ${{ steps.changelog.outputs.HAS_CHANGELOG }}
221+
HAS_COMMITS: ${{ steps.commits.outputs.HAS_COMMITS }}
77222
with:
78-
tag_name: ${{ steps.tag.outputs.TAG_NAME }}
79-
name: Release ${{ steps.tag.outputs.TAG_NAME }}
80-
body: |
81-
${{ steps.tag_message.outputs.MESSAGE }}
82-
${{ steps.changelog.outputs.HAS_CHANGELOG == 'true' && format('
83-
84-
## Changelog
85-
86-
{0}', steps.changelog.outputs.ENTRY) || '' }}
87-
draft: false
88-
prerelease: ${{ contains(steps.tag.outputs.TAG_NAME, '-alpha') || contains(steps.tag.outputs.TAG_NAME, '-beta') || contains(steps.tag.outputs.TAG_NAME, '-rc') }}
89-
generate_release_notes: true # GitHub generará notas automáticas basadas en los commits
223+
script: |
224+
const tagName = process.env.TAG_NAME;
225+
const tagMessage = process.env.TAG_MESSAGE || '';
226+
const changelogEntry = process.env.CHANGELOG_ENTRY || '';
227+
const commits = process.env.COMMITS || '';
228+
const hasChangelog = process.env.HAS_CHANGELOG === 'true';
229+
const hasCommits = process.env.HAS_COMMITS === 'true';
230+
const isPrerelease = tagName.includes('-alpha') || tagName.includes('-beta') || tagName.includes('-rc');
231+
232+
// Build release body - include tag message, changelog, and commits
233+
let releaseBody = tagMessage;
234+
235+
if (hasChangelog && changelogEntry) {
236+
releaseBody += '\n\n## Changelog\n\n' + changelogEntry;
237+
console.log('📝 Changelog entry found (' + changelogEntry.split('\n').length + ' lines), will include in release body');
238+
} else {
239+
console.log('⚠️ No changelog entry found for version ' + tagName);
240+
}
241+
242+
if (hasCommits && commits) {
243+
releaseBody += '\n\n## Commits\n\n' + commits;
244+
console.log('📝 Commits found (' + commits.split('\n').length + ' commits), will include in release body');
245+
} else {
246+
console.log('ℹ️ No commits found between tags');
247+
}
248+
249+
try {
250+
const { data: release } = await github.rest.repos.createRelease({
251+
owner: context.repo.owner,
252+
repo: context.repo.repo,
253+
tag_name: tagName,
254+
name: 'Release ' + tagName,
255+
body: releaseBody,
256+
draft: false,
257+
prerelease: isPrerelease,
258+
make_latest: !isPrerelease, // Explicitly mark as latest if not prerelease
259+
generate_release_notes: false // Don't generate auto notes, we have our own changelog
260+
});
261+
if (hasChangelog && changelogEntry) {
262+
console.log('✅ Created release ' + tagName + ' with complete changelog' + (!isPrerelease ? ' (marked as latest)' : ''));
263+
} else {
264+
console.log('✅ Created release ' + tagName + ' (no changelog available)' + (!isPrerelease ? ' (marked as latest)' : ''));
265+
}
266+
} catch (error) {
267+
console.error('❌ Error creating release ' + tagName + ':', error.message);
268+
throw error;
269+
}
90270
91271
# Maintainer: Héctor Franco Aceituno (@HecFranco)
92272
# Organization: nowo-tech (https://github.com/nowo-tech)

0 commit comments

Comments
 (0)