diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml deleted file mode 100644 index 7db53b6..0000000 --- a/.gitea/workflows/ci.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: CI - -# Same checks deploy-to-s3.yml gates on, run before a change reaches main. -# main itself is excluded because the deploy workflow already runs them there; -# without branches-ignore every merge would run the suite twice. -on: - push: - branches-ignore: - - main - pull_request: - -jobs: - checks: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install Python dependencies - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" - pip install -r backend/requirements.txt - - - name: Run checks - run: bash scripts/ci-checks.sh diff --git a/.gitea/workflows/deploy-to-s3.yml b/.gitea/workflows/deploy-to-s3.yml index c5883f0..5e2b169 100644 --- a/.gitea/workflows/deploy-to-s3.yml +++ b/.gitea/workflows/deploy-to-s3.yml @@ -1,64 +1,25 @@ name: Deploy to S3 -# main only. Everything else is covered by ci.yml, which runs the same checks -# without deploying. on: push: - branches: + branches: - main jobs: - # Nothing was verified before this existed: a frontend that failed to compile - # would zip and ship exactly like a working one. `deploy` now needs this job, - # so a red main does not reach the bucket. - checks: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # 22 to match frontend/Dockerfile, so CI resolves the same tree the - # production image builds from. - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: '22' - - # 3.11 is the floor in pyproject.toml and the version the project's conda - # env runs. - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Install Python dependencies - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" - pip install -r backend/requirements.txt - - - name: Run checks - run: bash scripts/ci-checks.sh - deploy: - needs: checks runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - # frontend/node_modules is excluded, and that is safe because of what - # happens to this object downstream. CodeDeploy pulls it, extracts to - # /opt/codedeploy-extracted-5, copies the tree to - # /home/ec2-user/utopia-ai-hr-ats-portal-deployment-group and runs - # `docker compose --env-file ./backend/.env up -d --build`. The only Node - # service is the frontend, whose image does `npm ci` from the lockfile, - # and frontend/.dockerignore excludes node_modules/ from the build context - # outright. So the committed tree was carried into every artifact and then - # thrown away unread. It was 90 MB of a 33 MB compressed upload. - # - # node_modules is still tracked in git, which is the reason it was here at - # all. Untracking it is a separate change and affects other branches. + - name: Configure AWS credentials + env: + AWS_ACCESS_KEY_ID: ${{ secrets.DEVOPS_USER_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.DEVOPS_USER_AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-east-1 + run: | + echo "AWS credentials configured" + - name: Archive project run: | apt-get update -y @@ -66,9 +27,8 @@ jobs: zip -r utopia-ai-hr-ats-portal.zip . \ -x ".git/*" \ -x ".gitea/*" \ - -x ".gitignore" \ - -x "frontend/node_modules/*" \ - -x "*.DS_Store" + -x ".gitignore/*" \ + -x "*.DS_Store" - name: Install AWS CLI run: | @@ -77,18 +37,19 @@ jobs: curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip -q awscliv2.zip ./aws/install - aws --version + aws --version - # The credentials live only on this step. There used to be a separate - # "Configure AWS credentials" step above that set the same three variables - # and then only echoed a message — env: is scoped to its own step, so - # those values were discarded before anything could use them. It was doing - # nothing, and it read as though credentials were set up globally. - name: Upload files to S3 env: AWS_ACCESS_KEY_ID: ${{ secrets.DEVOPS_USER_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.DEVOPS_USER_AWS_SECRET_ACCESS_KEY }} AWS_DEFAULT_REGION: us-east-1 run: | - echo "Uploading repo contents to S3..." - aws s3 cp utopia-ai-hr-ats-portal.zip s3://utopia-ai-s3-repo-bucket/utopia-ai-hr-ats-portal.zip + echo "Uploading repo contents to S3..." + aws s3 cp utopia-ai-hr-ats-portal.zip s3://utopia-ai-s3-repo-bucket/utopia-ai-hr-ats-portal.zip + + + + + + diff --git a/backend/job/candidate/views.py b/backend/job/candidate/views.py index 390b001..d2ff7dd 100644 --- a/backend/job/candidate/views.py +++ b/backend/job/candidate/views.py @@ -1713,26 +1713,9 @@ class CandidateView: email=_norm_email(row.get("email")) if email not in packed: continue - packed[email]["applications"].append(row) + # ATS scores are job-assignment history, not applications. if "candidates" not in packed[email]["present_in"]: packed[email]["present_in"].append("candidates") - pipeline_jobs={} - for email,pack in packed.items(): - jobs=set() - for row in pack["applications"]: - if row.get("source") in ("inbox","manual") and row.get("job_post_id"): - jobs.add(row["job_post_id"]) - pipeline_jobs[email]=jobs - for email,pack in packed.items(): - jobs=pipeline_jobs.get(email) or set() - if not jobs: - continue - # ATS scores for a job the person already applied to are not a - # separate application — they duplicate the pipeline row. - pack["applications"]=[ - row for row in pack["applications"] - if not (row.get("source")=="ats" and row.get("job_post_id") in jobs) - ] for pack in packed.values(): pack["applications"].sort(key=lambda r: r.get("applied_at") or "",reverse=True) present=pack["present_in"] diff --git a/frontend/src/components/ReapplicantHistory.jsx b/frontend/src/components/ReapplicantHistory.jsx index a37d583..22a41fa 100644 --- a/frontend/src/components/ReapplicantHistory.jsx +++ b/frontend/src/components/ReapplicantHistory.jsx @@ -64,12 +64,7 @@ export function candidateApplicationsOf(row) { const self = syntheticCurrentApplication(row) if (self) items.push(self) } - items.sort((a, b) => { - const ac = isSameApplication(a, current) ? 1 : 0 - const bc = isSameApplication(b, current) ? 1 : 0 - if (ac !== bc) return bc - ac - return (appliedAtMs(b?.applied_at) ?? 0) - (appliedAtMs(a?.applied_at) ?? 0) - }) + items.sort((a, b) => (appliedAtMs(b?.applied_at) ?? 0) - (appliedAtMs(a?.applied_at) ?? 0)) return items } diff --git a/frontend/src/screens/CandidateProfile.jsx b/frontend/src/screens/CandidateProfile.jsx index 6c8357d..56dd373 100644 --- a/frontend/src/screens/CandidateProfile.jsx +++ b/frontend/src/screens/CandidateProfile.jsx @@ -19,7 +19,7 @@ import * as formsApi from '../api/forms' import * as pipelineApi from '../api/pipeline' import * as s3Api from '../api/s3' import CandidateFormsTab from './CandidateForms' -import { PreviousApplications, ReappliedBadge } from '../components/ReapplicantHistory' +import { PreviousApplications, ReappliedBadge, candidateApplicationsOf } from '../components/ReapplicantHistory' import { fmtDate, fmtTime, toDate } from '../lib/format' import { companies, moneyK, pick } from '../data/seed' @@ -361,7 +361,7 @@ export default function CandidateProfile({ {rating ? `${rating.toFixed(1)} / 5.0` : 'Not rated'} - + {(live.match_summary || live.match_reasoning) && (