77 # Run automatically every Sunday at 2:00 AM UTC
88 schedule :
99 - cron : ' 0 2 * * 0'
10-
11- # Run on push to main (optional, remove if not needed)
12- # push :
13- # branches: [main]
10+
11+ # IMPORTANT: This permission is required to push changes
12+ permissions :
13+ contents : write
1414
1515jobs :
1616 update-publications :
@@ -30,24 +30,44 @@ jobs:
3030 SCOPUS_API_KEY : ${{ secrets.SCOPUS_API_KEY }}
3131 SCOPUS_AUTHOR_ID : ${{ secrets.SCOPUS_AUTHOR_ID }}
3232 run : |
33- # Fetch author metrics
33+ # Fetch author metrics and save to file
3434 echo "Fetching author metrics..."
35- AUTHOR_DATA=$( curl -s -H "Accept: application/json" \
35+ curl -s -H "Accept: application/json" \
3636 -H "X-ELS-APIKey: ${SCOPUS_API_KEY}" \
37- "https://api.elsevier.com/content/author/author_id/${SCOPUS_AUTHOR_ID}?view=METRICS")
37+ "https://api.elsevier.com/content/author/author_id/${SCOPUS_AUTHOR_ID}?view=METRICS" \
38+ -o author_data.json
3839
39- # Fetch publications
40+ # Check if author data was fetched successfully
41+ if [ ! -s author_data.json ]; then
42+ echo "Error: Failed to fetch author data"
43+ exit 1
44+ fi
45+
46+ # Fetch publications and save to file
4047 echo "Fetching publications..."
41- PUBS_DATA=$( curl -s -H "Accept: application/json" \
48+ curl -s -H "Accept: application/json" \
4249 -H "X-ELS-APIKey: ${SCOPUS_API_KEY}" \
43- "https://api.elsevier.com/content/search/scopus?query=AU-ID(${SCOPUS_AUTHOR_ID})&sort=-citedby-count&count=50")
50+ "https://api.elsevier.com/content/search/scopus?query=AU-ID(${SCOPUS_AUTHOR_ID})&sort=-citedby-count&count=100" \
51+ -o pubs_data.json
52+
53+ # Check if publications data was fetched successfully
54+ if [ ! -s pubs_data.json ]; then
55+ echo "Error: Failed to fetch publications data"
56+ exit 1
57+ fi
58+
59+ # Debug: show first part of response to verify data
60+ echo "Author data preview:"
61+ head -c 500 author_data.json
62+ echo ""
4463
4564 # Create Node.js script to process data
4665 cat > process_scopus.js << 'SCRIPT'
4766 const fs = require('fs');
4867
49- const authorData = JSON.parse(process.env.AUTHOR_DATA || '{}');
50- const pubsData = JSON.parse(process.env.PUBS_DATA || '{}');
68+ // Read data from files
69+ const authorData = JSON.parse(fs.readFileSync('author_data.json', 'utf8'));
70+ const pubsData = JSON.parse(fs.readFileSync('pubs_data.json', 'utf8'));
5171
5272 // Extract author info
5373 const authorProfile = authorData['author-retrieval-response']?.[0] || {};
5979 hIndex = parseInt(authorProfile['h-index']) || 0;
6080 } else if (coredata?.['h-index']) {
6181 hIndex = parseInt(coredata['h-index']) || 0;
82+ } else if (authorProfile?.['author-profile']?.['h-index']) {
83+ hIndex = parseInt(authorProfile['author-profile']['h-index']) || 0;
84+ }
85+
86+ // Debug: log structure if h-index is 0
87+ if (hIndex === 0) {
88+ console.log('Debug - Author profile keys:', Object.keys(authorProfile));
89+ console.log('Debug - Coredata keys:', Object.keys(coredata));
90+ if (authorProfile?.['author-profile']) {
91+ console.log('Debug - author-profile keys:', Object.keys(authorProfile['author-profile']));
92+ }
6293 }
6394
6495 // Get preferred name
@@ -73,6 +104,12 @@ jobs:
73104
74105 // Process publications
75106 const entries = pubsData['search-results']?.entry || [];
107+
108+ // Check for error in search results
109+ if (pubsData['search-results']?.['opensearch:totalResults'] === '0') {
110+ console.log('Warning: No publications found in search results');
111+ }
112+
76113 const publications = entries.map(entry => ({
77114 title: entry['dc:title'] || 'Untitled',
78115 authors: entry['dc:creator'] || '',
@@ -90,6 +127,13 @@ jobs:
90127 // Calculate i10-index
91128 const i10Index = publications.filter(p => p.citations >= 10).length;
92129
130+ // Get total citations from coredata
131+ const totalCitations = parseInt(coredata['citation-count']) ||
132+ publications.reduce((sum, p) => sum + p.citations, 0);
133+
134+ // Get document count
135+ const worksCount = parseInt(coredata['document-count']) || publications.length;
136+
93137 // Create final JSON
94138 const result = {
95139 _generatedAt: new Date().toISOString(),
@@ -102,8 +146,8 @@ jobs:
102146 metrics: {
103147 hIndex: hIndex,
104148 i10Index: i10Index,
105- totalCitations: parseInt(coredata['citation-count']) || 0 ,
106- worksCount: parseInt(coredata['document-count']) || publications.length ,
149+ totalCitations: totalCitations ,
150+ worksCount: worksCount ,
107151 lastUpdated: new Date().toISOString().split('T')[0],
108152 source: 'Scopus'
109153 },
@@ -113,19 +157,25 @@ jobs:
113157
114158 fs.writeFileSync('content/publications.json', JSON.stringify(result, null, 2));
115159 console.log(`✓ Saved ${publications.length} publications`);
116- console.log(`✓ h-index: ${hIndex}, citations: ${result.metrics. totalCitations}`);
160+ console.log(`✓ h-index: ${hIndex}, citations: ${totalCitations}`);
117161 SCRIPT
118162
119163 # Run the processing script
120- AUTHOR_DATA="$AUTHOR_DATA" PUBS_DATA="$PUBS_DATA" SCOPUS_AUTHOR_ID="$SCOPUS_AUTHOR_ID" node process_scopus.js
164+ node process_scopus.js
121165
122- # Cleanup
123- rm process_scopus.js
166+ # Cleanup temp files
167+ rm -f author_data.json pubs_data.json process_scopus.js
124168
125169 - name : Commit and Push
126170 run : |
127171 git config --local user.email "github-actions[bot]@users.noreply.github.com"
128172 git config --local user.name "github-actions[bot]"
129173 git add content/publications.json
130- git diff --staged --quiet || git commit -m "📚 Update publications from Scopus [$(date +'%Y-%m-%d')]"
131- git push
174+
175+ # Only commit if there are changes
176+ if git diff --staged --quiet; then
177+ echo "No changes to commit"
178+ else
179+ git commit -m "📚 Update publications from Scopus [$(date +'%Y-%m-%d')]"
180+ git push
181+ fi
0 commit comments