diff --git a/.github/workflows/check_dependency_updates.yaml b/.github/workflows/check_dependency_updates.yaml index 557293e30..478c5e102 100644 --- a/.github/workflows/check_dependency_updates.yaml +++ b/.github/workflows/check_dependency_updates.yaml @@ -1,5 +1,4 @@ name: check_dependency_updates - on: schedule: - cron: '0 0 15 */2 *' @@ -9,8 +8,6 @@ jobs: update_dependencies: runs-on: ubuntu-latest steps: - # MARK: Environments - - name: Checkout Repository uses: actions/checkout@v2 @@ -19,89 +16,168 @@ jobs: with: node-version: 20 - - name: Install Yarn - working-directory: ./frontend - run: install - - # MARK: Dependency Updates + - name: Initialize Report + run: | + echo "# Dependency Update Report $(date '+%B %d, %Y') 🤖📝" > reports.md + echo "## Available Update ⚙️" >> reports.md - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.11' - - name: Update Backend Dependencies - working-directory: backend + - name: Setup Yarn + working-directory: frontend + continue-on-error: true run: | - python -m pip install --upgrade uv - uv venv - uv pip install -r requirements-dev.txt - pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U - pip freeze > requirements-dev.txt + corepack enable + corepack prepare yarn@4.6.0 --activate - - name: Install npm-check-updates - run: npm install -g npm-check-updates + - name: Install Frontend Dependencies + id: install-frontend + working-directory: frontend + continue-on-error: true + run: | + rm -rf .yarn .pnp.* yarn.lock node_modules + yarn set version 4.6.0 + yarn install --no-immutable - name: Update Frontend Dependencies + id: frontend-updates working-directory: frontend + continue-on-error: true run: | + cp package.json package.old.json + npm install -g npm-check-updates + cat > compare_versions.js << 'EOF' + #!/usr/bin/env node + const oldPkg = require('./package.old.json'); + const newPkg = require('./package.json'); + + const allDeps = new Set([ + ...Object.keys(oldPkg.dependencies || {}), + ...Object.keys(oldPkg.devDependencies || {}), + ...Object.keys(newPkg.dependencies || {}), + ...Object.keys(newPkg.devDependencies || {}) + ]); + + const getVersion = (pkg, name) => { + return (pkg.dependencies && pkg.dependencies[name]) + || (pkg.devDependencies && pkg.devDependencies[name]) + || 'not present'; + }; + + for (const dep of Array.from(allDeps).sort()) { + const oldVersion = getVersion(oldPkg, dep); + const newVersion = getVersion(newPkg, dep); + + if (oldVersion !== newVersion) { + console.log(`- ${dep}: ${oldVersion} → ${newVersion}`); + } + } + EOF + + chmod +x compare_versions.js ncu -u - # MARK: Backend Tests - - - name: Activate Virtual Environment - run: | - . .venv/bin/activate - echo PATH=$PATH >> $GITHUB_ENV - - - name: Run Ruff Format - Formatting and Linting Check - run: ruff check ./backend || echo "Ruff check failed" >> error_log.txt - - - name: Run mypy - Static Type Checking - if: always() - run: mypy ./backend --config-file ./backend/pyproject.toml || echo "mypy check failed" >> error_log.txt - - - name: Run pytest - Unit Tests - if: always() - run: pytest ./backend -vv || echo "Backend tests failed." >> error_log.txt - - # MARK: Frontend Tests + echo -e "\n### Dependencies" >> ../reports.md + echo -e "| Package Name | Old Version | New Available Version | Type |" >> ../reports.md + echo -e "|--------------|-------------|-----------------------|------|" >> ../reports.md + node compare_versions.js | sed 's/- \(.*\): \(.*\) → \(.*\)/| \1 | \2 | \3 | Frontend |/' >> ../reports.md || echo "No frontend changes found" >> ../reports.md - - name: Install Prettier - run: yarn add prettier + - name: Create Python Virtual Environment + id: setup-venv + working-directory: backend + continue-on-error: true + run: python -m venv .venv - - name: Run Prettier - Formatting Check - working-directory: ./frontend + - name: Install Backend Dependencies + id: install-backend + working-directory: backend + continue-on-error: true run: | - yarn prettier . --check --config ../.prettierrc --ignore-path ../.prettierignore || echo "Prettier check failed." >> error_log.txt - - - name: Run Nuxt Type Check - if: always() - working-directory: ./frontend - run: nuxi typecheck || echo "Type check failed." >> error_log.txt + source .venv/bin/activate + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + python -m pip install mypy - - name: Run ESLint - Linting - if: always() - working-directory: ./frontend - run: eslint . || echo "ESLint check failed." >> error_log.txt - - # MARK: Errors and Issue - - - name: Log Errors - if: failure() + - name: Update Backend Dependencies + id: backend-updates + working-directory: backend + continue-on-error: true + run: | + source .venv/bin/activate + echo PATH=$PATH >> $GITHUB_ENV + cp requirements.txt requirements.old.txt + pip install -U pip-tools + pip-compile --upgrade requirements.in + + cat > compare_versions.py << 'EOF' + import re + def parse_req_file(filename): + deps = {} + with open(filename, "r") as f: + for line in f: + line = line.strip() + if line and not line.startswith("#") and "==" in line: + parts = re.split("==|>=|<=", line, 1) + if len(parts) == 2: + name = parts[0].strip() + version = parts[1].strip() + deps[name] = version + return deps + old_deps = parse_req_file("requirements.old.txt") + new_deps = parse_req_file("requirements.txt") + all_deps = set(list(old_deps.keys()) + list(new_deps.keys())) + for dep in sorted(all_deps): + old_ver = old_deps.get(dep, "not present") + new_ver = new_deps.get(dep, "not present") + if old_ver != new_ver: + print(f"| {dep} | {old_ver} | {new_ver} | Backend |") + EOF + + python compare_versions.py >> ../reports.md || echo "No backend changes found" >> ../reports.md + + - name: Run Backend Tests + id: backend-tests + working-directory: backend + continue-on-error: true run: | - if [[ -f error_log.txt ]]; then - cat error_log.txt - else - echo "No errors found during dependency update." - fi + source .venv/bin/activate + echo -e "\n## Test Results" >> ../reports.md + echo -e "\n### Mypy Results" >> ../reports.md + echo "\`\`\`" >> ../reports.md + mypy . --config-file mypy.ini 2>&1 | tee -a ../reports.md || true + echo "\`\`\`" >> ../reports.md + + echo -e "\n### Django Tests" >> ../reports.md + echo "\`\`\`" >> ../reports.md + DJANGO_SETTINGS_MODULE=app.settings.test python manage.py test 2>&1 | tee -a ../reports.md || true + echo "\`\`\`" >> ../reports.md + + - name: Run Frontend Tests + id: frontend-tests + working-directory: frontend + continue-on-error: true + run: | + echo "compare_versions.js" >> ../.prettierignore + echo -e "\n### Prettier Results" >> ../reports.md + echo "\`\`\`" >> ../reports.md + yarn prettier . --check --config ../.prettierrc --ignore-path ../.prettierignore 2>&1 | tee -a ../reports.md || true + echo "\`\`\`" >> ../reports.md + + echo -e "\n### Type Check Results" >> ../reports.md + echo "\`\`\`" >> ../reports.md + yarn nuxi typecheck 2>&1 | sed 's/\[.*\]/\n&\n/g' | tee -a ../reports.md || true + echo "\`\`\`" >> ../reports.md - name: Create GitHub Issue - if: failure() + if: always() uses: peter-evans/create-issue-from-file@v4 with: - title: $(date +%Y-%m-%d) Dependency Update Errors - content-filepath: error_log.txt + title: "Dependency Update Report - $(date '+%B %d, %Y') 🤖" + content-filepath: reports.md labels: | dependencies help wanted + good first issue