| name | apollo-upgrade-migration |
| description | Plan and execute Apollo.io SDK upgrades.
Use when upgrading Apollo API versions, migrating to new endpoints,
or updating deprecated API usage.
Trigger with phrases like "apollo upgrade", "apollo migration",
"update apollo api", "apollo breaking changes", "apollo deprecation".
|
| allowed-tools | Read, Grep, Bash(curl:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Apollo Upgrade Migration
Overview
Plan and execute safe upgrades for Apollo.io API integrations, handling breaking changes and deprecated endpoints.
Pre-Upgrade Assessment
Check Current API Usage
grep -r "api.apollo.io" --include="*.ts" --include="*.js" -l
grep -roh "api.apollo.io/v[0-9]*/[a-z_/]*" --include="*.ts" --include="*.js" | sort -u
grep -rn "deprecated\|legacy" --include="*.ts" src/lib/apollo/
Audit Script
import { readFileSync, readdirSync } from 'fs';
import { join } from 'path';
interface AuditResult {
file: string;
line: number;
pattern: string;
severity: 'warning' | 'error';
message: string;
}
const DEPRECATED_PATTERNS = [
{
pattern: /\/v1\/contacts\//,
message: 'Use /v1/people/ instead of /v1/contacts/',
severity: 'error' as const,
},
{
pattern: /organization_name/,
message: 'Use q_organization_domains instead of organization_name',
severity: 'warning' as const,
},
{
pattern: /\.then\s*\(/,
message: 'Consider using async/await for cleaner code',
severity: 'warning' as const,
},
];
function auditFile(filePath: string): AuditResult[] {
content = (filePath, );
lines = content.();
: [] = [];
lines.( {
( { pattern, message, severity } ) {
(pattern.(line)) {
results.({
: filePath,
: index + ,
: pattern.,
severity,
message,
});
}
}
});
results;
}
(): [] {
: [] = [];
() {
files = (currentDir, { : });
( file files) {
path = (currentDir, file.);
(file.() && !file..()) {
(path);
} (file..() || file..()) {
results.(...(path));
}
}
}
(dir);
results;
}
results = ();
.();
( result results) {
icon = result. === ? : ;
.();
.();
}
.();
Migration Steps
Step 1: Create Compatibility Layer
import { apollo } from './client';
export const apolloCompat = {
async searchContacts(params: any) {
console.warn('searchContacts is deprecated, use searchPeople');
return apollo.searchPeople(params);
},
async searchByCompanyName(companyName: string) {
console.warn('searchByCompanyName is deprecated');
const orgSearch = await apollo.searchOrganizations({
q_organization_name: companyName,
per_page: 1,
});
if (orgSearch.organizations.length === 0) {
throw new Error(`Company not found: ${companyName}`);
}
const domain = orgSearch.[].;
apollo.({
: [domain],
});
},
};
Step 2: Update Imports Gradually
import { searchContacts } from '../lib/apollo/legacy';
import { apolloCompat } from '../lib/apollo/compat';
const results = await apolloCompat.searchContacts(params);
import { apollo } from '../lib/apollo/client';
const results = await apollo.searchPeople(params);
Step 3: Feature Flag for New API
export const USE_NEW_APOLLO_API = process.env.APOLLO_USE_NEW_API === 'true';
import { apollo } from '../lib/apollo/client';
import { apolloCompat } from '../lib/apollo/compat';
import { USE_NEW_APOLLO_API } from '../lib/apollo/feature-flags';
export async function searchLeads(criteria: SearchCriteria) {
if (USE_NEW_APOLLO_API) {
return apollo.searchPeople({
q_organization_domains: criteria.domains,
person_titles: criteria.titles,
});
} else {
return apolloCompat.searchContacts({
organization_domains: criteria.domains,
titles: criteria.titles,
});
}
}
Step 4: Parallel Testing
import { apollo } from '../src/lib/apollo/client';
import { apolloCompat } from '../src/lib/apollo/compat';
async function compareResults() {
const testCases = [
{ domains: ['stripe.com'], titles: ['Engineer'] },
{ domains: ['apollo.io'], titles: ['Sales'] },
];
for (const testCase of testCases) {
console.log(`\nTesting: ${JSON.stringify(testCase)}`);
const newResult = await apollo.searchPeople({
q_organization_domains: testCase.domains,
person_titles: testCase.titles,
per_page: 10,
});
const legacyResult = await apolloCompat.searchContacts({
organization_domains: testCase.domains,
titles: testCase.titles,
per_page: 10,
});
newCount = newResult..;
legacyCount = legacyResult..;
.();
.();
.();
}
}
().(.);
Rollout Strategy
Phase 1: Canary (1%)
apiVersion: v1
kind: ConfigMap
metadata:
name: apollo-config-canary
data:
APOLLO_USE_NEW_API: "true"
---
Phase 2: Gradual Rollout
function shouldUseNewApi(userId: string): boolean {
const rolloutPercentage = parseInt(process.env.APOLLO_NEW_API_ROLLOUT || '0');
const hash = hashCode(userId) % 100;
return hash < rolloutPercentage;
}
function hashCode(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash);
}
Phase 3: Full Migration
export APOLLO_USE_NEW_API=true
rm src/lib/apollo/compat.ts
find src -name "*.ts" -exec sed -i 's/apolloCompat/apollo/g' {} \;
Post-Migration Cleanup
grep -rl "deprecated" --include="*.ts" src/lib/apollo/ | xargs rm -v
npm run audit:apollo
Rollback Procedure
export APOLLO_USE_NEW_API=false
kubectl rollout undo deployment/api-server
Output
- Pre-upgrade audit results
- Compatibility layer for gradual migration
- Feature flag controlled rollout
- Parallel testing verification
- Cleanup procedures
Error Handling
| Issue | Resolution |
|---|
| Audit finds errors | Fix before proceeding |
| Compat layer fails | Check mapping logic |
| Results differ | Investigate API changes |
| Canary issues | Immediate rollback |
Resources
Next Steps
Proceed to apollo-ci-integration for CI/CD setup.