Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
350bd00
Script: "Add Django EOL checker script (fail if <180 days to EOL)"
CarolineDenis May 11, 2026
a1a215f
Github: Add github CI for EOL dependencies
CarolineDenis May 11, 2026
4578d8c
Fix: Improve run time out handling
CarolineDenis May 11, 2026
e986b74
Test: Create pr comments when warning triggered
CarolineDenis May 11, 2026
1da6a28
Fix: Fix installation
CarolineDenis May 11, 2026
7900e9a
Fix: Add timeout
CarolineDenis May 11, 2026
b4cdadb
Fix: Add timeout to CI
CarolineDenis May 11, 2026
6202252
Fix: Alignement
CarolineDenis May 11, 2026
2988b3d
Fix: Handle backticks
CarolineDenis May 11, 2026
19e8703
Comment
CarolineDenis May 11, 2026
28c95c8
Clean
CarolineDenis May 11, 2026
4107146
Fix: test new install for dependecies
CarolineDenis May 11, 2026
bcb6164
Fix: Typo
CarolineDenis May 11, 2026
a61cb47
Fix: Create or Update github action comment
CarolineDenis May 11, 2026
e3737d4
Test
CarolineDenis May 11, 2026
db19719
Feat: Generalize EOL script
CarolineDenis May 12, 2026
3e7f524
Fix: fix python version
CarolineDenis May 12, 2026
eac393f
Feat: Combine github comments
CarolineDenis May 12, 2026
846ed30
Fix: Indentation
CarolineDenis May 12, 2026
af092af
Refactor: Allow expension of EOL tracking
CarolineDenis May 12, 2026
fc387f1
Fix: remove install
CarolineDenis May 12, 2026
c4e53cc
Fix: fix path
CarolineDenis May 12, 2026
755dd58
Fix: Update imports
CarolineDenis May 12, 2026
fa88ada
Fix: Add init
CarolineDenis May 12, 2026
863cdf0
Update .github/workflows/test.yml
CarolineDenis May 13, 2026
d83c2b5
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] May 13, 2026
3247410
Fix: Handle None dates
CarolineDenis May 13, 2026
c9a8ae5
Fix: Handle string and integer cycle
CarolineDenis May 13, 2026
a9cd34e
Fix: handle failed request
CarolineDenis May 13, 2026
c4165f8
Fix: Improve regex
CarolineDenis May 13, 2026
d3078d1
Merge branch 'main' into issue-8063
grantfitzsimmons Jul 6, 2026
4c28212
Potential fix for pull request finding 'CodeQL / Empty except'
CarolineDenis Jul 7, 2026
c1290a7
Potential fix for pull request finding 'CodeQL / Empty except'
CarolineDenis Jul 7, 2026
b3ea1d5
Potential fix for pull request finding 'CodeQL / Empty except'
CarolineDenis Jul 7, 2026
603ba88
Potential fix for pull request finding 'CodeQL / Empty except'
CarolineDenis Jul 7, 2026
0a590c8
Merge branch 'main' into issue-8063
CarolineDenis Jul 7, 2026
817d766
Merge branch 'main' into issue-8063
grantfitzsimmons Jul 8, 2026
26e652d
fix: use pass instead of continue in scanner
grantfitzsimmons Jul 8, 2026
fa0f315
Merge branch 'issue-8063' of https://github.com/specify/specify7 into…
grantfitzsimmons Jul 8, 2026
36a8657
chore: minor style adjustment
grantfitzsimmons Jul 8, 2026
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
91 changes: 73 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,14 @@ jobs:
MIGRATOR_NAME: MasterUser
MIGRATOR_PASSWORD: MasterPassword
APP_USER_NAME: MasterUser
APP_USER_PASSWORD: MasterPassword
options:
--health-cmd="mariadb-admin ping" --health-interval=5s
APP_USER_PASSWORD: MasterPassword
options: --health-cmd="mariadb-admin ping" --health-interval=5s
--health-timeout=2s --health-retries=3
redis:
image: redis:latest
ports:
- 6379


steps:
- uses: actions/checkout@v4

Expand All @@ -98,8 +96,7 @@ jobs:
- name:
Patch Specify datamodel (Sam, you made the Attachment.origFilename too
long)
run:
sed -i 's/name="origFilename"
run: sed -i 's/name="origFilename"
type="java.lang.String"/name="origFilename" type="text"/'
./Specify6/config/specify_datamodel.xml

Expand Down Expand Up @@ -135,10 +132,9 @@ jobs:
echo "APP_USER_PASSWORD = 'MasterPassword'" >> specifyweb/settings/local_specify_settings.py
echo "REDIS_HOST = '127.0.0.1'" >> specifyweb/settings/local_specify_settings.py
echo "REDIS_PORT = ${{ job.services.redis.ports[6379] }}" >> specifyweb/settings/local_specify_settings.py

- name: Need these files to be present
run:
make specifyweb/settings/build_version.py
run: make specifyweb/settings/build_version.py
specifyweb/settings/secret_key.py

- name: Verify MariaDB connection
Expand All @@ -148,7 +144,7 @@ jobs:
while ! mysqladmin ping -h"127.0.0.1" -P"$PORT" --silent; do
sleep 1
done

- name: Run Mypy type checker
run: VIRTUAL_ENV=./ve make typecheck

Expand Down Expand Up @@ -180,7 +176,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: specifyweb/frontend/js_src/package.json
cache: 'npm'
cache: "npm"
cache-dependency-path: specifyweb/frontend/js_src/package-lock.json

- name: Build frontend
Expand All @@ -199,8 +195,7 @@ jobs:

- name: Clone branch that stores localization strings
# Listen for changes to production branch
if:
github.ref == format('refs/heads/{0}',
if: github.ref == format('refs/heads/{0}',
github.event.repository.default_branch)
id: weblate
uses: actions/checkout@v3
Expand All @@ -215,8 +210,7 @@ jobs:
npm run localizationTests -- --emit ../../../weblate-localization/strings

- name: Sync localization strings with Weblate (only on production branch)
if:
github.ref == format('refs/heads/{0}',
if: github.ref == format('refs/heads/{0}',
github.event.repository.default_branch)
working-directory: weblate-localization
run: |
Expand Down Expand Up @@ -282,8 +276,7 @@ jobs:
# - This would have already run on the feature branch by the time code
# is pushed into production.
# - There shouldn't be many direct pushes to production anyway
if:
github.ref != format('refs/heads/{0}',
if: github.ref != format('refs/heads/{0}',
github.event.repository.default_branch)
working-directory: specifyweb/frontend/js_src
run: |
Expand Down Expand Up @@ -322,4 +315,66 @@ jobs:
-m 'Lint code with ESLint and Prettier' \
-m "Triggered by ${{ github.sha }} on branch ${{ github.ref }}"
git push
fi
fi

eol-check:
name: Check dependency EOL (Django)
runs-on: ubuntu-latest
continue-on-error: true

permissions:
pull-requests: write
contents: read

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
pip install requests django
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

- name: Run EOL check
id: eol
run: |
output=$(python scripts/check_django_eol.py || true)

echo "$output"

echo "output<<EOF" >> $GITHUB_OUTPUT
echo "$output" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Parse EOL status
id: parse
run: |
STATUS=$(echo "${{ steps.eol.outputs.output }}" | grep STATUS= | cut -d= -f2)
echo "status=$STATUS" >> $GITHUB_OUTPUT

- name: Comment on PR if EOL warning
if: github.event_name == 'pull_request' && steps.parse.outputs.status == 'WARNING'
uses: actions/github-script@v7
with:
script: |
const output = `${{ steps.eol.outputs.output }}`;

const body = `

\`\`\`
${output}
\`\`\`

This dependency is approaching or past End-of-Life.
Please plan an upgrade.
`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
92 changes: 92 additions & 0 deletions scripts/check_django_eol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import requests
import datetime
import sys
import subprocess
import re
from requests import RequestException

THRESHOLD_DAYS = 180


def get_django_version():
result = subprocess.run(
[sys.executable, "-m", "django", "--version"],
capture_output=True,
text=True
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

if result.returncode != 0:
print("ERROR: Unable to determine Django version")
sys.exit(1)

full_version = result.stdout.strip()

# Example:
# 4.2.16 -> 4.2
m = re.match(r"^(\d+)\.(\d+)", full_version)
if not m:
print(f"ERROR: Unexpected Django version format: {full_version}")
sys.exit(1)

cycle = f"{m.group(1)}.{m.group(2)}"

return full_version, cycle


def get_django_eol(cycle):
url = "https://endoflife.date/api/django.json"

try:
response = requests.get(url, timeout=10)
response.raise_for_status()
except RequestException as exc:
print(f"ERROR: Failed to fetch EOL data: {exc}")
sys.exit(1)

data = response.json()

for release in data:
if release["cycle"] == cycle:
return release["eol"]

print(f"ERROR: No EOL data found for Django {cycle}")
sys.exit(1)


def calculate_days_remaining(eol_date):
today = datetime.date.today()
eol = datetime.datetime.strptime(eol_date, "%Y-%m-%d").date()
return (eol - today).days


def main():
full_version, cycle = get_django_version()

eol_date = get_django_eol(cycle)
days_remaining = calculate_days_remaining(eol_date)

status = "OK"
if days_remaining < THRESHOLD_DAYS:
status = "WARNING"

# ---- structured output for GitHub Actions ----
print(f"STATUS={status}")
print(f"DJANGO_VERSION={full_version}")
print(f"DJANGO_CYCLE={cycle}")
print(f"EOL_DATE={eol_date}")
print(f"DAYS_REMAINING={days_remaining}")

# ---- human-readable log ----
print("\n--- Django EOL Report ---")
print(f"Version: {full_version}")
print(f"Cycle: {cycle}")
print(f"EOL date: {eol_date}")
print(f"Days remaining: {days_remaining}")
print(f"Status: {status}")

# keep non-blocking behavior (CI should NOT fail)
sys.exit(0)


if __name__ == "__main__":
main()
Loading