v1.1.1 #19
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Update Zenodo Metadata | |
| on: | |
| push: | |
| tags: | |
| - 'v*' # Only standard releases (v1.0.0, v1.1.0, etc.) | |
| - '!v*-*' # Exclude pre-releases like v1.0.0-beta | |
| - '!python-v*' # Exclude Python library tags | |
| release: | |
| types: [published] | |
| permissions: | |
| contents: write | |
| jobs: | |
| update-zenodo: | |
| name: Update Zenodo Metadata | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Extract release information | |
| id: release_info | |
| run: | | |
| echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT | |
| echo "release_date=$(date -u +%Y-%m-%d)" >> $GITHUB_OUTPUT | |
| - name: Update CITATION.cff with new version | |
| run: | | |
| VERSION="${{ steps.release_info.outputs.version }}" | |
| DATE="${{ steps.release_info.outputs.release_date }}" | |
| # Update version in CITATION.cff | |
| sed -i "s/^version: .*/version: ${VERSION}/" CITATION.cff | |
| sed -i "s/^date-released: .*/date-released: ${DATE}/" CITATION.cff | |
| - name: Update README.md version and last updated date | |
| run: | | |
| VERSION="${{ steps.release_info.outputs.version }}" | |
| DATE="${{ steps.release_info.outputs.release_date }}" | |
| # Remove 'v' prefix if present | |
| CLEAN_VERSION="${VERSION#v}" | |
| # Format date as "Month Day, Year" | |
| FORMATTED_DATE=$(date -d "$DATE" "+%B %d, %Y") | |
| # Update version in README.md | |
| sed -i "s/^\*\*Version:\*\* .*/**Version:** ${CLEAN_VERSION}/" README.md | |
| # Update last updated date in README.md | |
| sed -i "s/^\*\*Last Updated:\*\* .*/**Last Updated:** ${FORMATTED_DATE}/" README.md | |
| - name: Update CHANGELOG.md with release notes | |
| run: | | |
| VERSION="${{ steps.release_info.outputs.version }}" | |
| RELEASE_DATE="${{ steps.release_info.outputs.release_date }}" | |
| RELEASE_BODY="${{ github.event.release.body }}" | |
| # Remove 'v' prefix if present | |
| CLEAN_VERSION="${VERSION#v}" | |
| # Create new changelog entry | |
| cat > changelog_entry.tmp << EOF | |
| ## [${CLEAN_VERSION}] - ${RELEASE_DATE} | |
| ### Release Notes | |
| ${RELEASE_BODY} | |
| EOF | |
| # Insert the new entry after the Unreleased section | |
| awk -v entry="$(cat changelog_entry.tmp)" ' | |
| /^## \[Unreleased\]/ { | |
| getline | |
| print entry | |
| next | |
| } | |
| {print} | |
| ' CHANGELOG.md > CHANGELOG.md.tmp | |
| # Add comparison link at the end if not already present | |
| if ! grep -q "\[${CLEAN_VERSION}\]:" CHANGELOG.md.tmp; then | |
| echo "" >> CHANGELOG.md.tmp | |
| echo "[${CLEAN_VERSION}]: https://github.com/upss-standard/universal-prompt-security-standard/releases/tag/${VERSION}" >> CHANGELOG.md.tmp | |
| fi | |
| # Replace original file | |
| mv CHANGELOG.md.tmp CHANGELOG.md | |
| rm -f changelog_entry.tmp | |
| - name: Commit version updates | |
| run: | | |
| VERSION="${{ steps.release_info.outputs.version }}" | |
| # Configure git user | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| # Stage modified files | |
| git add README.md | |
| git add CITATION.cff | |
| git add CHANGELOG.md | |
| # Check if there are changes to commit | |
| if git diff --staged --quiet; then | |
| echo "::notice::No version changes to commit" | |
| else | |
| git commit -m "chore(release): update version to ${VERSION} [skip ci]" | |
| # Create a release branch and push to it | |
| # Remove 'v' prefix if present to avoid double 'v' in branch name | |
| CLEAN_VERSION="${VERSION#v}" | |
| RELEASE_BRANCH="release/zenodo-v${CLEAN_VERSION}" | |
| git checkout -b "${RELEASE_BRANCH}" | |
| if git push origin "${RELEASE_BRANCH}"; then | |
| echo "✅ Created release branch: ${RELEASE_BRANCH}" | |
| echo "::warning::Please create a pull request to merge ${RELEASE_BRANCH} into main" | |
| echo "::warning::The workflow will continue assuming version files will be merged" | |
| else | |
| echo "::error::Failed to create release branch" | |
| exit 1 | |
| fi | |
| fi | |
| - name: Prepare Zenodo metadata | |
| id: zenodo_metadata | |
| run: | | |
| VERSION="${{ steps.release_info.outputs.version }}" | |
| RELEASE_DATE="${{ steps.release_info.outputs.release_date }}" | |
| RELEASE_NAME="${{ github.event.release.name }}" | |
| RELEASE_BODY="${{ github.event.release.body }}" | |
| # Load metadata from config file and replace placeholders | |
| if [ ! -f "config/zenodo/metadata.json" ]; then | |
| echo "❌ Error: config/zenodo/metadata.json not found" | |
| exit 1 | |
| fi | |
| # Use jq to replace placeholders with proper JSON escaping | |
| jq --arg version "$VERSION" \ | |
| --arg publication_date "$RELEASE_DATE" \ | |
| --arg release_body "$RELEASE_BODY" \ | |
| ' | |
| walk(if type == "string" then | |
| gsub("{{VERSION}}"; $version) | | |
| gsub("{{PUBLICATION_DATE}}"; $publication_date) | | |
| gsub("{{RELEASE_BODY}}"; $release_body) | |
| else | |
| . | |
| end) | |
| ' config/zenodo/metadata.json > zenodo_metadata.json | |
| echo "Generated metadata:" | |
| cat zenodo_metadata.json | |
| - name: Update Zenodo deposition | |
| env: | |
| ZENODO_ACCESS_TOKEN: ${{ secrets.ZENODO_ACCESS_TOKEN }} | |
| ZENODO_DEPOSITION_ID: ${{ secrets.ZENODO_DEPOSITION_ID }} | |
| run: | | |
| if [ -z "$ZENODO_ACCESS_TOKEN" ]; then | |
| echo "Warning: ZENODO_ACCESS_TOKEN not set. Skipping Zenodo update." | |
| echo "Please add ZENODO_ACCESS_TOKEN to repository secrets to enable automatic Zenodo updates." | |
| exit 0 | |
| fi | |
| if [ -z "$ZENODO_DEPOSITION_ID" ]; then | |
| echo "Warning: ZENODO_DEPOSITION_ID not set. Skipping Zenodo update." | |
| echo "Please add ZENODO_DEPOSITION_ID to repository secrets to enable automatic Zenodo updates." | |
| exit 0 | |
| fi | |
| # Function to create a new version, handling existing drafts | |
| create_new_version() { | |
| echo "Creating new version on Zenodo..." | |
| NEW_VERSION_RESPONSE=$(curl -sS -X POST \ | |
| "https://zenodo.org/api/deposit/depositions/${ZENODO_DEPOSITION_ID}/actions/newversion" \ | |
| -H "Authorization: Bearer ${ZENODO_ACCESS_TOKEN}") | |
| echo "New version response: ${NEW_VERSION_RESPONSE}" | |
| # Check if the response contains an error about existing files | |
| ERROR_MESSAGE=$(echo "$NEW_VERSION_RESPONSE" | jq -r '.message // empty') | |
| STATUS=$(echo "$NEW_VERSION_RESPONSE" | jq -r '.status // empty') | |
| if [ "$STATUS" = "400" ] && echo "$ERROR_MESSAGE" | grep -q "Please remove all files first"; then | |
| echo "⚠️ Detected existing unpublished draft version" | |
| # Check if there's a latest_draft link in the error response | |
| LATEST_DRAFT_URL=$(echo "$NEW_VERSION_RESPONSE" | jq -r '.links.latest_draft // empty') | |
| if [ -n "$LATEST_DRAFT_URL" ] && [ "$LATEST_DRAFT_URL" != "null" ]; then | |
| EXISTING_DRAFT_ID=$(echo "$LATEST_DRAFT_URL" | grep -oP '/depositions/\K[0-9]+') | |
| if [ -n "$EXISTING_DRAFT_ID" ]; then | |
| echo "🗑️ Deleting existing unpublished draft: ${EXISTING_DRAFT_ID}" | |
| DELETE_DRAFT_RESPONSE=$(curl -sS -X DELETE \ | |
| "https://zenodo.org/api/deposit/depositions/${EXISTING_DRAFT_ID}" \ | |
| -H "Authorization: Bearer ${ZENODO_ACCESS_TOKEN}") | |
| DELETE_STATUS=$(echo "$DELETE_DRAFT_RESPONSE" | jq -r '.status // empty') | |
| if [ "$DELETE_STATUS" = "400" ] || [ "$DELETE_STATUS" = "500" ]; then | |
| echo "❌ Error: Failed to delete existing draft" | |
| echo "Response: $DELETE_DRAFT_RESPONSE" | |
| exit 1 | |
| fi | |
| echo "✅ Successfully deleted existing draft" | |
| echo "🔄 Retrying new version creation..." | |
| # Retry creating new version | |
| NEW_VERSION_RESPONSE=$(curl -sS -X POST \ | |
| "https://zenodo.org/api/deposit/depositions/${ZENODO_DEPOSITION_ID}/actions/newversion" \ | |
| -H "Authorization: Bearer ${ZENODO_ACCESS_TOKEN}") | |
| echo "Retry response: ${NEW_VERSION_RESPONSE}" | |
| fi | |
| fi | |
| fi | |
| # Extract the new draft deposition ID | |
| NEW_DRAFT_URL=$(echo "$NEW_VERSION_RESPONSE" | jq -r '.links.latest_draft') | |
| NEW_DRAFT_ID=$(echo "$NEW_DRAFT_URL" | grep -oP '/depositions/\K[0-9]+') | |
| if [ -z "$NEW_DRAFT_ID" ]; then | |
| echo "❌ Error: Failed to create new version. Response:" | |
| echo "$NEW_VERSION_RESPONSE" | |
| exit 1 | |
| fi | |
| echo "✅ New draft deposition ID: ${NEW_DRAFT_ID}" | |
| } | |
| # Call the function to create new version | |
| create_new_version | |
| # Keep existing files from the previous version instead of deleting them | |
| # This ensures Zenodo has at least one file for publishing | |
| # Update the metadata for the new draft | |
| echo "Updating metadata for new version..." | |
| UPDATE_RESPONSE=$(curl -sS -X PUT \ | |
| "https://zenodo.org/api/deposit/depositions/${NEW_DRAFT_ID}" \ | |
| -H "Content-Type: application/json" \ | |
| -H "Authorization: Bearer ${ZENODO_ACCESS_TOKEN}" \ | |
| -d @zenodo_metadata.json) | |
| echo "Update response: ${UPDATE_RESPONSE}" | |
| # Check for errors in update response | |
| UPDATE_STATUS=$(echo "$UPDATE_RESPONSE" | jq -r '.status // empty') | |
| if [ "$UPDATE_STATUS" = "400" ] || [ "$UPDATE_STATUS" = "500" ]; then | |
| echo "❌ Error: Failed to update metadata" | |
| echo "Status: $UPDATE_STATUS" | |
| echo "Message: $(echo "$UPDATE_RESPONSE" | jq -r '.message // empty')" | |
| echo "Errors: $(echo "$UPDATE_RESPONSE" | jq -r '.errors // empty')" | |
| exit 1 | |
| fi | |
| # Publish the new version | |
| echo "Publishing new version..." | |
| PUBLISH_RESPONSE=$(curl -sS -X POST \ | |
| "https://zenodo.org/api/deposit/depositions/${NEW_DRAFT_ID}/actions/publish" \ | |
| -H "Authorization: Bearer ${ZENODO_ACCESS_TOKEN}") | |
| echo "Publish response: ${PUBLISH_RESPONSE}" | |
| # Check for errors in publish response | |
| PUBLISH_STATUS=$(echo "$PUBLISH_RESPONSE" | jq -r '.status // empty') | |
| if [ "$PUBLISH_STATUS" = "400" ] || [ "$PUBLISH_STATUS" = "500" ]; then | |
| echo "❌ Error: Failed to publish new version" | |
| echo "Status: $PUBLISH_STATUS" | |
| echo "Response: $PUBLISH_RESPONSE" | |
| exit 1 | |
| fi | |
| # Extract and display the new DOI | |
| NEW_DOI=$(echo "$PUBLISH_RESPONSE" | jq -r '.doi // empty') | |
| if [ -z "$NEW_DOI" ] || [ "$NEW_DOI" = "null" ]; then | |
| echo "❌ Error: Failed to extract DOI from publish response" | |
| echo "Response: $PUBLISH_RESPONSE" | |
| exit 1 | |
| fi | |
| echo "✅ Successfully published new version to Zenodo!" | |
| echo "New DOI: ${NEW_DOI}" | |
| echo "Zenodo URL: https://doi.org/${NEW_DOI}" | |
| - name: Summary | |
| run: | | |
| echo "## Zenodo Metadata Update Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Version**: ${{ steps.release_info.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Release Date**: ${{ steps.release_info.outputs.release_date }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Status**: ✅ Workflow completed" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Next Steps" >> $GITHUB_STEP_SUMMARY | |
| echo "If Zenodo secrets are configured, check the Zenodo record for the updated metadata." >> $GITHUB_STEP_SUMMARY |