Skip to content

Merge pull request #35 from ReneHeim/logistic-regression #75

Merge pull request #35 from ReneHeim/logistic-regression

Merge pull request #35 from ReneHeim/logistic-regression #75

Workflow file for this run

name: Build Package
on:
push:
branches: [main, dev]
pull_request:
types: [opened, synchronize, closed]
branches: [main, dev]
env:
PYTHON_VERSION: "3.12"
jobs:
build:
name: Build Package
runs-on: ubuntu-latest
if: |
github.event_name == 'push' ||
(github.event_name == 'pull_request' && github.event.action != 'closed') ||
(github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true)
outputs:
version: ${{ steps.get_version.outputs.version }}
has_artifacts: ${{ steps.check_artifacts.outputs.has_artifacts }}
is_merge_commit: ${{ steps.check_merge.outputs.is_merge_commit }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
# NEW: Detect if this is a merge commit
- name: Check if merge commit
id: check_merge
run: |
# Check if commit message indicates a PR merge
COMMIT_MSG=$(git log -1 --pretty=%s)
echo "Commit message: $COMMIT_MSG"
if [[ "$COMMIT_MSG" =~ ^Merge\ pull\ request\ #[0-9]+\ from\ .+ ]]; then
echo "is_merge_commit=true" >> $GITHUB_OUTPUT
echo "This is a PR merge commit"
else
echo "is_merge_commit=false" >> $GITHUB_OUTPUT
echo "This is not a PR merge commit"
fi
# ... (all your existing build steps remain the same) ...
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build==1.0.3 twine==4.0.2 setuptools>=65.0
- name: Build package
run: |
echo "Building package..."
python -m build --wheel --sdist
- name: Check package integrity
run: |
echo "Checking package integrity..."
if [ ! -d "dist" ] || [ -z "$(ls -A dist)" ]; then
echo "Error: No distribution files found"
exit 1
fi
echo "Distribution files found:"
ls -la dist/
if ! twine check dist/*; then
echo "Warning: twine check failed, performing basic validation..."
for file in dist/*; do
if [[ $file == *.whl ]]; then
echo "Checking wheel file: $file"
python -m zipfile -l "$file" > /dev/null || {
echo "Error: Invalid wheel file $file"
exit 1
}
elif [[ $file == *.tar.gz ]]; then
echo "Checking source distribution: $file"
tar -tzf "$file" > /dev/null || {
echo "Error: Invalid source distribution $file"
exit 1
}
fi
done
echo "Basic package validation completed"
else
echo "Package integrity check passed"
fi
- name: Test package installation
run: |
echo "Testing package installation..."
WHEEL_FILE=$(find dist -name "*.whl" | head -1)
if [ -z "$WHEEL_FILE" ]; then
echo "Error: No wheel file found for testing"
exit 1
fi
echo "Installing wheel: $WHEEL_FILE"
pip install "$WHEEL_FILE"
python -c "
import sys
print('Package installed successfully')
print('Python version:', sys.version)
try:
print('Package import test: SKIPPED (no package specified)')
except ImportError as e:
print('Package import test: FAILED -', e)
except Exception as e:
print('Package import test: ERROR -', e)
"
- name: Get package version
id: get_version
run: |
VERSION=""
if [ -f "pyproject.toml" ]; then
VERSION=$(grep -E '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/' | head -1)
elif [ -f "setup.py" ]; then
VERSION=$(python setup.py --version 2>/dev/null || echo "")
fi
if [ -z "$VERSION" ]; then
VERSION=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo "")
fi
if [ -z "$VERSION" ] && [ -f ".bumpversion.cfg" ]; then
VERSION=$(grep "current_version" .bumpversion.cfg | cut -d'=' -f2 | tr -d ' ')
fi
if [ -z "$VERSION" ]; then
VERSION="$(date +%Y.%m.%d)-$(git rev-parse --short HEAD)"
fi
echo "Detected version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Check artifacts
id: check_artifacts
run: |
if [ -d "dist" ] && [ -n "$(ls -A dist)" ]; then
echo "has_artifacts=true" >> $GITHUB_OUTPUT
else
echo "has_artifacts=false" >> $GITHUB_OUTPUT
fi
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ env.PYTHON_VERSION }}-${{ github.sha }}
path: dist/
retention-days: 30
- name: Build summary
if: always()
run: |
echo "Build Summary"
echo "============="
if [ -d "dist" ] && [ -n "$(ls -A dist)" ]; then
echo "Build Status: SUCCESS"
echo "Files created:"
for file in dist/*; do
if [ -f "$file" ]; then
SIZE=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo "unknown")
echo " - $(basename "$file") (${SIZE} bytes)"
fi
done
else
echo "Build Status: FAILED - No distribution files created"
fi
echo "Build completed at: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
# UPDATED: Release job that handles both PR merges and push events
release:
name: Create Release
runs-on: ubuntu-latest
needs: build
if: |
needs.build.outputs.has_artifacts == 'true' && (
(github.event_name == 'pull_request' &&
github.event.action == 'closed' &&
github.event.pull_request.merged == true &&
github.event.pull_request.base.ref == 'main') ||
(github.event_name == 'push' &&
github.ref == 'refs/heads/main' &&
needs.build.outputs.is_merge_commit == 'true')
)
permissions:
contents: write
pull-requests: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: dist-${{ env.PYTHON_VERSION }}-${{ github.sha }}
path: dist/
# NEW: Get PR information for push events
- name: Get PR information from merge commit
id: pr_info
if: github.event_name == 'push'
uses: actions/github-script@v7
with:
script: |
const commitMessage = `${{ github.event.head_commit.message }}`;
console.log('Commit message:', commitMessage);
// Extract PR number from merge commit message
const prMatch = commitMessage.match(/Merge pull request #(\d+) from/);
if (prMatch) {
const prNumber = parseInt(prMatch[1]);
console.log('Found PR number:', prNumber);
try {
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_request_number: prNumber
});
core.setOutput('pr_number', prNumber);
core.setOutput('pr_title', pr.title);
core.setOutput('pr_body', pr.body || '');
core.setOutput('pr_author', pr.user.login);
core.setOutput('pr_merged_at', pr.merged_at);
core.setOutput('pr_additions', pr.additions);
core.setOutput('pr_deletions', pr.deletions);
core.setOutput('pr_changed_files', pr.changed_files);
return { found: true, number: prNumber };
} catch (error) {
console.log('Error fetching PR:', error);
return { found: false };
}
}
return { found: false };
- name: Generate release notes
id: release_notes
uses: actions/github-script@v7
with:
script: |
let releaseNotes = '';
if (context.eventName === 'pull_request') {
// Original PR event logic
const pr = context.payload.pull_request;
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number
});
const reviews = await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number
});
releaseNotes = `## ${pr.title} (#${pr.number})\n\n`;
if (pr.body) {
releaseNotes += `### Description\n${pr.body}\n\n`;
}
releaseNotes += `### Pull Request Details\n`;
releaseNotes += `- **Author**: @${pr.user.login}\n`;
releaseNotes += `- **Merged**: ${pr.merged_at}\n`;
releaseNotes += `- **Files changed**: ${pr.changed_files}\n`;
releaseNotes += `- **Additions**: +${pr.additions}\n`;
releaseNotes += `- **Deletions**: -${pr.deletions}\n\n`;
const approvedReviews = reviews.filter(review => review.state === 'APPROVED');
if (approvedReviews.length > 0) {
releaseNotes += `### Reviewers\n`;
approvedReviews.forEach(review => {
releaseNotes += `- @${review.user.login}\n`;
});
releaseNotes += `\n`;
}
if (comments.length > 0) {
releaseNotes += `### Discussion Summary\n`;
releaseNotes += `This PR had ${comments.length} comment(s) during review.\n\n`;
}
} else {
// Push event logic - use PR info from previous step
const prNumber = '${{ steps.pr_info.outputs.pr_number }}';
const prTitle = '${{ steps.pr_info.outputs.pr_title }}';
const prBody = '${{ steps.pr_info.outputs.pr_body }}';
const prAuthor = '${{ steps.pr_info.outputs.pr_author }}';
const prMergedAt = '${{ steps.pr_info.outputs.pr_merged_at }}';
const prAdditions = '${{ steps.pr_info.outputs.pr_additions }}';
const prDeletions = '${{ steps.pr_info.outputs.pr_deletions }}';
const prChangedFiles = '${{ steps.pr_info.outputs.pr_changed_files }}';
if (prNumber) {
releaseNotes = `## ${prTitle} (#${prNumber})\n\n`;
if (prBody) {
releaseNotes += `### Description\n${prBody}\n\n`;
}
releaseNotes += `### Pull Request Details\n`;
releaseNotes += `- **Author**: @${prAuthor}\n`;
releaseNotes += `- **Merged**: ${prMergedAt}\n`;
releaseNotes += `- **Files changed**: ${prChangedFiles}\n`;
releaseNotes += `- **Additions**: +${prAdditions}\n`;
releaseNotes += `- **Deletions**: -${prDeletions}\n\n`;
} else {
releaseNotes = `## Release from commit ${context.sha.substring(0, 7)}\n\n`;
releaseNotes += `### Commit Details\n`;
releaseNotes += `- **Message**: ${{ github.event.head_commit.message }}\n`;
releaseNotes += `- **Author**: @${{ github.event.head_commit.author.username }}\n`;
releaseNotes += `- **Timestamp**: ${{ github.event.head_commit.timestamp }}\n\n`;
}
}
releaseNotes += `### Build Information\n`;
releaseNotes += `- **Python Version**: ${{ env.PYTHON_VERSION }}\n`;
releaseNotes += `- **Built on**: ${new Date().toISOString()}\n`;
releaseNotes += `- **Commit**: ${context.sha}\n`;
releaseNotes += `- **Triggered by**: ${context.eventName}\n`;
core.setOutput('notes', releaseNotes);
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ needs.build.outputs.version }}"
TAG_NAME="v$VERSION"
if ! git tag -l | grep -q "^$TAG_NAME$"; then
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git tag "$TAG_NAME"
git push origin "$TAG_NAME"
fi
cat << 'EOF' > release_notes.md
${{ steps.release_notes.outputs.notes }}
EOF
gh release create "$TAG_NAME" \
--title "Release $VERSION" \
--notes-file release_notes.md \
--latest \
dist/*
- name: Release summary
run: |
echo "Release Created Successfully!"
echo "================================"
echo "Version: ${{ needs.build.outputs.version }}"
echo "Tag: v${{ needs.build.outputs.version }}"
echo "Triggered by: ${{ github.event_name }}"
if [ "${{ github.event_name }}" = "push" ]; then
echo "PR: #${{ steps.pr_info.outputs.pr_number }}"
echo "Author: @${{ steps.pr_info.outputs.pr_author }}"
else
echo "PR: #${{ github.event.pull_request.number }}"
echo "Author: @${{ github.event.pull_request.user.login }}"
fi
echo "Files included:"
ls -la dist/