Skip to content

Commit 455133e

Browse files
committed
override versions for specific samples
1 parent 1ff5e0a commit 455133e

File tree

4 files changed

+160
-4
lines changed

4 files changed

+160
-4
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ npm install && npm run dev
2727
- Navigation is JSON in `/src/config/sidebar.ts`
2828
- SEO metadata implementation: See [SEO Metadata Guide](SEO_METADATA_GUIDE.md) for technical writers
2929

30+
### Version Overrides for Solidity Samples
31+
32+
To use different package versions for specific sample files (e.g., for tutorials requiring specific versions), edit `version-overrides.json`:
33+
34+
```json
35+
{
36+
"overrides": [
37+
{
38+
"file": "samples/CCIP/example.sol",
39+
"reason": "Tutorial requires specific version",
40+
"versions": {
41+
"@chainlink/contracts": "1.5.0"
42+
}
43+
}
44+
]
45+
}
46+
```
47+
48+
See TypeScript types in `src/scripts/helper/pin-solver-dist.ts` for structure.
49+
3050
## Deploy Preview
3151

3252
This repo is configured to automatically create a preview environment on Vercel when a PR is opened. After the deployment is approved, the Vercel bot will leave a comment with a link to the preview on your PR.

public/samples/CCIP/cct/TokenDependencies.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ import {
99
RegistryModuleOwnerCustom
1010
} from "@chainlink/contracts-ccip/contracts/tokenAdminRegistry/RegistryModuleOwnerCustom.sol";
1111
import {TokenAdminRegistry} from "@chainlink/contracts-ccip/contracts/tokenAdminRegistry/TokenAdminRegistry.sol";
12-
import {BurnMintERC20} from "@chainlink/contracts@1.4.0/src/v0.8/shared/token/ERC20/BurnMintERC20.sol";
12+
import {BurnMintERC20} from "@chainlink/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol";

src/scripts/helper/pin-solver-dist.ts

Lines changed: 126 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
import fs from "fs"
22
import { glob } from "glob"
33
import crypto from "crypto"
4+
import path from "path"
5+
6+
/**
7+
* Type definitions for version override configuration.
8+
* Config file: version-overrides.json in project root
9+
*
10+
* Example:
11+
* {
12+
* "description": "Optional description",
13+
* "overrides": [
14+
* {
15+
* "file": "samples/CCIP/example.sol",
16+
* "reason": "Why this override is needed",
17+
* "versions": {
18+
* "@chainlink/contracts": "1.5.0",
19+
* "@chainlink/contracts-ccip": "1.6.3"
20+
* }
21+
* }
22+
* ]
23+
* }
24+
*/
425

526
interface Dependencies {
627
[key: string]: string
@@ -10,6 +31,18 @@ interface PinningStats {
1031
totalFiles: number
1132
packagesUpdated: { [key: string]: number }
1233
filesProcessed: string[]
34+
overridesApplied: { [file: string]: string[] }
35+
}
36+
37+
interface FileOverride {
38+
file: string
39+
reason?: string
40+
versions: Dependencies
41+
}
42+
43+
interface VersionOverridesConfig {
44+
description?: string
45+
overrides: FileOverride[]
1346
}
1447

1548
/**
@@ -42,13 +75,75 @@ const getFileHash = (content: string): string => {
4275
return crypto.createHash("sha256").update(content).digest("hex")
4376
}
4477

78+
/**
79+
* Loads version override configuration from file.
80+
* @returns The version overrides configuration, or null if file doesn't exist.
81+
*/
82+
const loadVersionOverrides = (): Map<string, Dependencies> => {
83+
const overridesPath = path.join(process.cwd(), "version-overrides.json")
84+
85+
if (!fs.existsSync(overridesPath)) {
86+
console.log("ℹ️ No version-overrides.json found. Using default versions for all files.")
87+
return new Map()
88+
}
89+
90+
try {
91+
const config: VersionOverridesConfig = JSON.parse(fs.readFileSync(overridesPath, "utf8"))
92+
const overridesMap = new Map<string, Dependencies>()
93+
94+
config.overrides.forEach((override) => {
95+
// Normalize path separators for cross-platform compatibility
96+
const normalizedPath = override.file.replace(/\\/g, "/")
97+
overridesMap.set(normalizedPath, override.versions)
98+
99+
console.log(`📌 Loaded override for ${override.file}:`)
100+
if (override.reason) {
101+
console.log(` Reason: ${override.reason}`)
102+
}
103+
Object.entries(override.versions).forEach(([pkg, version]) => {
104+
console.log(` - ${pkg}@${version}`)
105+
})
106+
})
107+
108+
return overridesMap
109+
} catch (error) {
110+
console.error("⚠️ Failed to load version-overrides.json:", error)
111+
return new Map()
112+
}
113+
}
114+
115+
/**
116+
* Determines which versions to use for a given file.
117+
* @param filePath - The path to the file being processed.
118+
* @param defaultVersions - The default versions from package.json.
119+
* @param overridesMap - Map of file paths to their version overrides.
120+
* @returns The versions to use for this file.
121+
*/
122+
const getVersionsForFile = (
123+
filePath: string,
124+
defaultVersions: Dependencies,
125+
overridesMap: Map<string, Dependencies>
126+
): Dependencies => {
127+
// Normalize the file path to match config format (relative to dist, remove dist prefix)
128+
const normalizedPath = filePath.replace(/\\/g, "/").replace(/^.*?\/(samples\/.+\.sol)$/, "$1")
129+
130+
const override = overridesMap.get(normalizedPath)
131+
132+
if (override) {
133+
// Merge override versions with defaults (override takes precedence)
134+
return { ...defaultVersions, ...override }
135+
}
136+
137+
return defaultVersions
138+
}
139+
45140
/**
46141
* Pins the versions of dependencies in Solidity files based on the provided glob patterns.
47142
* @param globPatterns - Array of glob patterns used to find Solidity files.
48-
* @param versions - The object containing the dependencies and their corresponding versions.
143+
* @param defaultVersions - The default object containing the dependencies and their corresponding versions.
49144
* @throws {Error} - If there are errors during the version pinning process.
50145
*/
51-
const pinVersionsInSolidityFiles = async (globPatterns: string[], versions: Dependencies) => {
146+
const pinVersionsInSolidityFiles = async (globPatterns: string[], defaultVersions: Dependencies) => {
52147
try {
53148
const fileArrays = await Promise.all(globPatterns.map((pattern) => glob(pattern)))
54149
const allFiles = fileArrays.flat()
@@ -57,14 +152,24 @@ const pinVersionsInSolidityFiles = async (globPatterns: string[], versions: Depe
57152
totalFiles: allFiles.length,
58153
packagesUpdated: {},
59154
filesProcessed: [],
155+
overridesApplied: {},
60156
}
61157

158+
// Load version overrides configuration
159+
const overridesMap = loadVersionOverrides()
160+
62161
allFiles.forEach((file) => {
63162
try {
64163
const originalContent = fs.readFileSync(file, "utf8")
65164
let content = originalContent
66165

67-
Object.entries(versions).forEach(([packageName, version]) => {
166+
// Get the appropriate versions for this file (either default or overridden)
167+
const versionsToUse = getVersionsForFile(file, defaultVersions, overridesMap)
168+
169+
// Track if this file uses overrides
170+
const usesOverrides = overridesMap.has(file.replace(/\\/g, "/").replace(/^.*?\/(samples\/.+\.sol)$/, "$1"))
171+
172+
Object.entries(versionsToUse).forEach(([packageName, version]) => {
68173
const regex = new RegExp(`(import.*${packageName})(/)(?!@${version.replace(".", "\\.")})(.*?\\.sol)`, "g")
69174
const newContent = content.replace(regex, `$1@${version}/$3`)
70175

@@ -73,6 +178,14 @@ const pinVersionsInSolidityFiles = async (globPatterns: string[], versions: Depe
73178
stats.packagesUpdated[packageName] = 0
74179
}
75180
stats.packagesUpdated[packageName]++
181+
182+
// Track which packages were overridden for this file
183+
if (usesOverrides && versionsToUse[packageName] !== defaultVersions[packageName]) {
184+
if (!stats.overridesApplied[file]) {
185+
stats.overridesApplied[file] = []
186+
}
187+
stats.overridesApplied[file].push(`${packageName}@${version}`)
188+
}
76189
}
77190
content = newContent
78191
})
@@ -102,6 +215,16 @@ const pinVersionsInSolidityFiles = async (globPatterns: string[], versions: Depe
102215
Object.entries(stats.packagesUpdated).forEach(([pkg, count]) => {
103216
console.log(`- ${pkg}: ${count} imports updated`)
104217
})
218+
219+
// Show files with overrides applied
220+
if (Object.keys(stats.overridesApplied).length > 0) {
221+
console.log("\n🎯 Files with custom version overrides:")
222+
Object.entries(stats.overridesApplied).forEach(([file, packages]) => {
223+
console.log(`- ${file}`)
224+
packages.forEach((pkg) => console.log(` └─ ${pkg}`))
225+
})
226+
}
227+
105228
if (stats.filesProcessed.length > 0) {
106229
console.log("\nUpdated files:")
107230
stats.filesProcessed.forEach((file) => {

version-overrides.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"description": "Per-file package version overrides for Solidity samples. This allows specific files to use different versions than the global defaults defined in package.json.",
3+
"overrides": [
4+
{
5+
"file": "samples/CCIP/cct/TokenDependencies.sol",
6+
"reason": "Requires specific CCIP and contracts versions for CCT tutorial compatibility",
7+
"versions": {
8+
"@chainlink/contracts-ccip": "1.6.3",
9+
"@chainlink/contracts": "1.5.0"
10+
}
11+
}
12+
]
13+
}

0 commit comments

Comments
 (0)