Skip to content

refactor(hr): decouple resume storage from WordPress filesystem#3838

Open
rathorevaibhav wants to merge 2 commits intodevelopfrom
feature/decouple-wordpress-resume-storage
Open

refactor(hr): decouple resume storage from WordPress filesystem#3838
rathorevaibhav wants to merge 2 commits intodevelopfrom
feature/decouple-wordpress-resume-storage

Conversation

@rathorevaibhav
Copy link
Copy Markdown
Member

@rathorevaibhav rathorevaibhav commented May 8, 2026

Summary

  • Removes MoveFilesToWordPress console command and MoveResumeToWebsite event listener that copied portal-uploaded resumes into WordPress's wp-content/uploads/ directory and rewrote the resume URL to a coloredcow.com/wp-content/uploads/... link.
  • Drops the website_upload_dir config entry (was only consumed by the deleted command).
  • The portal already serves uploaded resumes publicly from its own storage symlink — the iframe in details.blade.php:91 and edit.blade.php:558 renders /storage/resume/... same-origin without any auth or framing issues.

Why

Context: coloredcow-admin/coloredcow#1230 — DevOps is moving coloredcow.com (WordPress) onto its own Ubuntu 24.04 EC2 server so it can run modern PHP, leaving the portal on the existing server. While auditing what would break, this MoveFilesToWordPress plumbing turned out to be the only remaining hard coupling between portal and WordPress filesystems.

The flow it implemented:

  1. Admin uploads resume_file via portal UI → Application::saveResumeFile() saves to storage/app/public/resume/YYYY/MM/... and stores /storage/resume/... in DB.
  2. ApplicationCreated event → MoveResumeToWebsite listener → synchronous Artisan::call('hr:move-resume-to-website').
  3. The command does exec("cp ...") to a local WordPress upload path (WEBSITE_UPLOAD_DIR), then rewrites applications.resume to https://coloredcow.com/wp-content/uploads/....

Issues with the existing implementation:

  • Synchronous exec() shell call inside a request-time event listener.
  • Errors swallowed silently (if ($d) continue;).
  • Non-recursive mkdir() — would fail if year directory doesn't exist.
  • Class name MoveFilesToWordPress doesn't match command signature hr:move-resume-to-website.
  • Description literally 'Command description' — placeholder never filled in.
  • WHERE resume LIKE '/storage/resume%' LIMIT 50 processes 50 random old records on every new application — looks like a one-time backlog migration script that someone wired into an event listener as an afterthought.
  • Hard dependency on a shared filesystem between two apps that the org wants to split onto separate servers.

The portal-side serving already works:

$ ls -la public/storage    # on production
lrwxrwxrwx 1 nginx nginx 54 May  8  2022 public/storage -> /var/www/html/portal.coloredcow.com/storage/app/public

Nginx serves these as static files at https://portal.coloredcow.com/storage/resume/.... The blade iframe loads same-origin → no X-Frame-Options issues, no auth issues, browser PDF viewer renders inline. Same access pattern (publicly readable by anyone with the URL) as the WP-hosted variant — no new privacy risk.

What this changes for users

Nothing visible. The HR admin "View Resume" link in the applicant details/edit pages continues to work — only the URL changes for new portal-uploaded resumes (from coloredcow.com/wp-content/uploads/... to portal.coloredcow.com/storage/resume/...).

Existing records are untouched:

  • Resumes already stored as https://coloredcow.com/wp-content/uploads/... (most of the table — these come from the WordPress career form path) keep working as long as the WP wp-content/uploads/ directory remains served from coloredcow.com (which it will, even after the WP server move per the migration plan's rsync step).
  • Resumes still at /storage/resume/... (the backlog this command was supposed to drain) start working immediately because the portal serves them directly.

Test plan

  • Apply on staging
  • Upload a resume via portal admin → confirm it's saved to storage/app/public/resume/YYYY/MM/<filename>.pdf and applications.resume is /storage/resume/YYYY/MM/<filename>.pdf (no longer rewritten to a coloredcow.com URL)
  • Open /hr/recruitment/applicant/details/show/{id} for the new application → confirm iframe renders the PDF inline
  • Open /hr/recruitment/job/{id}/edit → confirm iframe still renders for the new application and for an existing application (whose URL is the legacy WP-hosted form)
  • Submit a career form on coloredcow.com (or simulate via API call) → confirm the resume field is still accepted as a URL and the existing flow is unaffected
  • Run php artisan list and confirm hr:move-resume-to-website is gone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Removed the automated resume file synchronization system that was previously used in the recruitment workflow to transfer resume files to external platforms.
    • Updated system configuration to introduce new URL endpoints for admin dashboard and analytics platform integration, replacing the legacy upload directory configuration approach.

Portal already serves uploaded resumes publicly from its own storage
symlink (storage/app/public via /storage/resume), and the iframe in the
applicant details/edit views renders them same-origin without any auth
or framing issues. The MoveFilesToWordPress command and the
MoveResumeToWebsite listener that called it via Artisan on every
ApplicationCreated event were duplicating the file onto WordPress's
upload directory purely to surface a coloredcow.com URL — a redundant
indirection that also imposes a hard filesystem coupling between portal
and WP. Removing it eliminates that coupling so the WordPress site can
move to its own server without portal-side changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2416e3eb-8922-4dfc-bda7-4e7e0b1610ed

📥 Commits

Reviewing files that changed from the base of the PR and between 1936836 and 98cac95.

📒 Files selected for processing (5)
  • Modules/HR/Console/Recruitment/MoveFilesToWordPress.php
  • Modules/HR/Listeners/Recruitment/MoveResumeToWebsite.php
  • Modules/HR/Providers/EventServiceProvider.php
  • Modules/HR/Providers/HRServiceProvider.php
  • config/constants.php
💤 Files with no reviewable changes (5)
  • Modules/HR/Providers/HRServiceProvider.php
  • Modules/HR/Listeners/Recruitment/MoveResumeToWebsite.php
  • Modules/HR/Console/Recruitment/MoveFilesToWordPress.php
  • config/constants.php
  • Modules/HR/Providers/EventServiceProvider.php

Walkthrough

This pull request removes the resume file migration feature by deleting the Artisan command and event listener, deregistering them from service providers, and updating configuration to remove the now-unused upload directory setting while introducing new URL-based configuration entries for admin, analytics, and CubeJS services.

Changes

Resume Migration Feature Removal

Layer / File(s) Summary
Command & Listener Deletion
Modules/HR/Console/Recruitment/MoveFilesToWordPress.php, Modules/HR/Listeners/Recruitment/MoveResumeToWebsite.php
The MoveFilesToWordPress command and MoveResumeToWebsite listener classes are deleted entirely, removing the resume copying logic and event trigger.
Provider Deregistration
Modules/HR/Providers/EventServiceProvider.php, Modules/HR/Providers/HRServiceProvider.php
Listener import and ApplicationCreated event mapping are removed from EventServiceProvider; command registration is removed from HRServiceProvider::registerCommands().
Configuration Updates
config/constants.php
The website_upload_dir setting is removed; new configuration entries for website_admin_url, analytics_dashboard_url, and cube_js_url are added with environment variable support.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🗑️ Resume migrations fade to dust,
The WordPress uploads, no longer a must.
Listeners removed, commands gone bye,
Config now points to analytics in the sky. 📊

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: removing WordPress filesystem coupling from the HR resume storage workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/decouple-wordpress-resume-storage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cypress
Copy link
Copy Markdown

cypress Bot commented May 8, 2026

Employee portal    Run #9050

Run Properties:  status check passed Passed #9050  •  git commit a153113a91 ℹ️: Merge c15678d09f3ae8c2622a669a8c5501e86c1c16a8 into 4c91a3da0ce6249ea711536d6c77...
Project Employee portal
Branch Review refs/pull/3838/merge
Run status status check passed Passed #9050
Run duration 00m 23s
Commit git commit a153113a91 ℹ️: Merge c15678d09f3ae8c2622a669a8c5501e86c1c16a8 into 4c91a3da0ce6249ea711536d6c77...
Committer Vaibhav Rathore
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 4
View all changes introduced in this branch ↗︎

@rathorevaibhav rathorevaibhav self-assigned this May 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

Coverage report for commit: c15678d
File: coverage.xml

Cover ┌─────────────────────────┐ Freq.
   0% │ ███████████████████████ │ 73.0%
  10% │ █░░░░░░░░░░░░░░░░░░░░░░ │  1.6%
  20% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.6%
  30% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.3%
  40% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.6%
  50% │ ██░░░░░░░░░░░░░░░░░░░░░ │  4.7%
  60% │ █░░░░░░░░░░░░░░░░░░░░░░ │  1.2%
  70% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.9%
  80% │ █░░░░░░░░░░░░░░░░░░░░░░ │  0.9%
  90% │ █░░░░░░░░░░░░░░░░░░░░░░ │  3.1%
 100% │ █████░░░░░░░░░░░░░░░░░░ │ 13.0%
      └─────────────────────────┘
 *Legend:* █ = Current Distribution 
Summary - Lines: 10.49% | Methods: 11.17%
FilesLinesMethodsBranches
Modules/HR/Console
   JobExpiredEmailToHr.php--100.00%
   QuarterlyReviewSystemForEmployee.php--100.00%
Modules/HR/Console/Recruitment
   ApplicationNoShow.php--100.00%
   DailyMessage.php--100.00%
   MappingOfJobsAndHrRounds.php--100.00%
   MarkApplicationForFollowUp.php--100.00%
   ResetIsLatestApplicationRound.php45.45%66.67%100.00%
   SendFollowUpThresholdMail.php--100.00%
   SendInterviewReminders.php--100.00%
Modules/HR/Contracts
   ApplicationServiceContract.php100.00%100.00%100.00%
   EvaluationServiceContract.php100.00%100.00%100.00%
   UniversityServiceContract.php100.00%100.00%100.00%
Modules/HR/Database/Factories
   HrApplicantsFactory.php100.00%100.00%100.00%
   HrApplicationEvaluationFactory.php--100.00%
   HrApplicationMetaFactory.php--100.00%
   HrApplicationRejectionFactory.php--100.00%
   HrApplicationRoundReviewFactory.php--100.00%
   HrApplicationSegmentFactory.php--100.00%
   HrApplicationsFactory.php--100.00%
   HrEmployeeFactory.php--100.00%
   HrFollowUpFactory.php--100.00%
   HrJobsFactory.php100.00%100.00%100.00%
   HrResourcesCategoriesFactory.php--100.00%
   HrResourcesFactory.php--100.00%
   HrUniversitiesContactsFactory.php100.00%100.00%100.00%
   HrUniversitiesFactory.php100.00%100.00%100.00%
   HrUniversityAliasesFactory.php100.00%100.00%100.00%
Modules/HR/Database/Migrations
   2020_07_15_110611_create_hr_application_segments_table.php91.67%50.00%100.00%
   2020_07_15_142215_rename_next_interview_comments_column.php50.00%50.00%100.00%
   2020_07_25_202622_update_segment_table_with_segment_parent.php61.54%50.00%100.00%
   2020_09_04_234639_update_application_round_with_calendar_meeting_id.php66.67%50.00%100.00%
   2020_09_06_234443_update_hr_application_round_table_with_is_latest.php50.00%50.00%100.00%
   2020_09_07_171154_create_hr_follow_ups_table.php92.31%50.00%100.00%
   2020_09_08_073438_create_hr_universities_table.php87.50%50.00%100.00%
   2020_09_08_073538_create_hr_universities_contacts_table.php90.00%50.00%100.00%
   2020_09_08_073651_add_hr_university_id_to_hr_applicants_table.php42.86%50.00%100.00%
   2020_11_24_141131_create_hr_university_aliases_table.php85.71%50.00%100.00%
   2020_12_31_112259_alter_posted_by_in_hr_jobs_table.php50.00%50.00%100.00%
   2021_01_01_113149_add_status_to_hr_jobs_table.php50.00%50.00%100.00%
   2021_01_01_123714_add_soft_deletes_to_hr_jobs_table.php50.00%50.00%100.00%
   2022_03_08_064931_update_hr_jobs_table.php50.00%50.00%100.00%
   2022_06_15_141424_add_parameter_slug_column_in_evaluation_parameter_table.php50.00%50.00%100.00%
   2022_07_04_165601_add_verification_status_to_application.php50.00%50.00%100.00%
   2022_07_07_075310_create_hr_job_domains_table.php85.71%50.00%100.00%
   2022_07_15_115016_create_hr_channels_table.php85.71%50.00%100.00%
   2022_07_15_115134_update_hr_applications_with_hr_channels_table.php50.00%50.00%100.00%
   2022_09_01_230847_create_job_requisition_table.php57.14%50.00%100.00%
   2022_09_06_232653_add_status_to_job_requisition.php50.00%50.00%100.00%
   2022_09_12_140344_create_hr_applicant_meta_table.php76.92%50.00%100.00%
   2022_09_19_160414_create_hr_job_designation_table.php85.71%50.00%100.00%
   2022_09_21_145858_create_batch_members_table.php57.14%50.00%100.00%
   2022_09_21_151304_create_batches_table.php83.33%50.00%100.00%
   2022_09_26_134702_alter_column_for_application_meta_value.php50.00%50.00%100.00%
   2024_03_20_161855_add_commencement_date_column_to_employee_salary_table.php50.00%50.00%100.00%
Modules/HR/Database/Seeders
   AddPreparatoryRoundsSeeder.php--100.00%
   ApplicationEvaluationTableSeeder.php--100.00%
   DomainTableSeeder.php--100.00%
   HRDatabaseSeeder.php--100.00%
   HRJobsSeederTableSeeder.php--100.00%
   HRPermissionsTableSeeder.php--100.00%
   HRRoundsTableSeeder.php--100.00%
   HrApplicantsTableSeeder.php--100.00%
   HrApplicationEvaluationSegmentTableSeeder.php--100.00%
   HrApplicationMetaTableSeeder.php--100.00%
   HrApplicationRejectionReasonTableSeeder.php--100.00%
   HrApplicationRoundReviewTableSeeder.php--100.00%
   HrApplicationRoundTableSeeder.php--100.00%
   HrApplicationSegmentTableSeeder.php--100.00%
   HrApplicationsTableSeeder.php--100.00%
   HrChannelsTableSeeder.php--100.00%
   HrDesignationTableSeeder.php100.00%100.00%100.00%
   HrDomainTableSeeder.php100.00%100.00%100.00%
   HrFollowUpTableSeeder.php--100.00%
   HrResourcesCategoriesTableSeeder.php--100.00%
   HrResourcesTableSeeder.php--100.00%
   HrUniversitiesContactsTableSeeder.php--100.00%
   HrUniversitiesTableSeeder.php--100.00%
   HrUniversityAliasesTableSeeder.php--100.00%
   ResumeScreeningEvaluationSeeder.php--100.00%
   SettingsTableSeeder.php--100.00%
   TagTableSeeder.php--100.00%
Modules/HR/Emails
   AppointmentSlotSelectionMail.php--100.00%
   SendHiringMail.php--100.00%
   SendJobExpiredMail.php--100.00%
   SendPayrollListMail.php--100.00%
   SendThreshholdFollowUp.php--100.00%
Modules/HR/Emails/Recruitment/Applicant
   ApplicantCreateAutoResponder.php--100.00%
   NoShow.php--100.00%
   OnHold.php--100.00%
   RoundReviewed.php--100.00%
   ScheduledInterviewReminder.php--100.00%
Modules/HR/Emails/Recruitment/Application
   ApplicationHandover.php--100.00%
   CustomApplicationMail.php--100.00%
   JobChanged.php--100.00%
   RoundNotConducted.php--100.00%
Modules/HR/Emails/Recruitment
   InterviewerScheduledRoundsReminder.php--100.00%
   SendForApproval.php--100.00%
   SendOfferLetter.php--100.00%
Modules/HR/Entities
   Applicant.php1.69%10.00%100.00%
   ApplicantMeta.php--100.00%
   Application.php13.52%10.42%100.00%
   ApplicationEvaluationSegment.php--100.00%
   ApplicationMeta.php--100.00%
   ApplicationRound.php0.36%4.00%100.00%
   ApplicationRoundReview.php--100.00%
   Assessment.php--100.00%
   Employee.php1.39%4.35%100.00%
   FollowUp.php--100.00%
   HRJobsRounds.php100.00%100.00%100.00%
   HRRejectionReason.php--100.00%
   HRRequisitionHiredBatch.php--100.00%
   HRRequisitionHiredBatchMembers.php--100.00%
   HrChannel.php100.00%100.00%100.00%
   HrJobDesignation.php--100.00%
   HrJobDomain.php--100.00%
   IndividualAssessment.php--100.00%
   Job.php50.00%38.89%100.00%
   JobRequisition.php--100.00%
   Round.php--100.00%
   University.php33.33%33.33%100.00%
   UniversityAlias.php100.00%100.00%100.00%
   UniversityContact.php100.00%100.00%100.00%
Modules/HR/Entities/Evaluation
   ApplicationEvaluation.php--100.00%
   Parameter.php--100.00%
   ParameterOption.php--100.00%
   Segment.php--100.00%
Modules/HR/Events
   ApplicationMovedToNewRound.php--100.00%
   CustomMailTriggeredForApplication.php--100.00%
   FollowUpEvent.php--100.00%
   InterviewCommunicationEmailSent.php--100.00%
Modules/HR/Events/Recruitment
   ApplicantEmailVerified.php--100.00%
   ApplicationCreated.php--100.00%
   JobUpdated.php66.67%50.00%100.00%
Modules/HR/Exports
   ContractorFeeExport.php--100.00%
   EmployeePayrollExport.php--100.00%
Modules/HR/Helpers
   TemplateHelper.php--100.00%
Modules/HR/Http/Controllers
   EmployeeController.php--100.00%
   EvaluationController.php--100.00%
   HiringController.php--100.00%
   HrChannelController.php--100.00%
   HrJobDesignationController.php--100.00%
   RequisitionController.php--100.00%
   ResourcesController.php--100.00%
   TagsController.php--100.00%
Modules/HR/Http/Controllers/Recruitment
   ApplicantController.php--100.00%
   ApplicationController.php38.22%7.14%100.00%
   ApplicationRoundController.php--100.00%
   CampaignsController.php--100.00%
   InternshipApplicationController.php--100.00%
   JobApplicationController.php100.00%100.00%100.00%
   JobController.php13.13%25.00%100.00%
   RecruitmentOpportunityController.php--100.00%
Table truncated to fit comment

🤖 comment via lucassabreu/comment-coverage-clover

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant