hash.ts
Overview
The `hash.ts` file provides utility functions for generating cryptographic hashes of codebase segments related to different "coinstack" implementations, specifically Node.js and Go-based stacks. It is primarily designed to create reproducible and accurate hash values reflecting the current state of source files and build arguments that make up the final build images of these coinstacks. These hashes can be used to detect changes, trigger rebuilds, or manage Kubernetes secret environment variables.
Key functionalities include:
Generating Kubernetes environment variable specifications sourced from secrets.
Computing content hashes for Node.js and Go coinstacks based on selective files and folders.
Supporting different coinstack types (
'node'and'go') via a unified interface.
This file interacts with the Kubernetes infrastructure layer (via `@pulumi/kubernetes` types), environment configuration (via `dotenv`), cryptographic hashing (`crypto`), and folder hashing utilities (`folder-hash`).
Exports and Types
CoinstackType
export type CoinstackType = 'go' | 'node'
**Description:** A string union type specifying the supported coinstack implementations for hash generation:
'go'— Go language coinstack'node'— Node.js coinstack
secretEnvs
export const secretEnvs = (
assetName: string,
sampleEnv: Buffer
): Array<k8s.types.input.core.v1.EnvVar>
**Description:** Generates an array of Kubernetes `EnvVar` definitions that map environment variables from a Kubernetes Secret named `assetName`. This allows pods to consume secret data as environment variables.
**Parameters:**
assetName(string): The name of the Kubernetes Secret containing the environment variables.sampleEnv(Buffer): A buffer containing the contents of a.env-style file to parse keys from.
**Returns:** An array of Kubernetes environment variable input objects (`k8s.types.input.core.v1.EnvVar`), each configured to source its value from the specified Secret.
**Important behavior:**
Parses keys from the provided
sampleEnv.Ignores keys
INDEXER_API_KEYandRPC_API_KEYif their corresponding environment variable values are empty strings. This is intended to handle fallback deployments.
**Example usage:**
const secretEnvVars = secretEnvs('my-secret', fs.readFileSync('./sample.env'))
// secretEnvVars can be passed into Kubernetes pod specs for environment variable configuration.
getCoinstackHash
export const getCoinstackHash = async (
coinstack: string,
buildArgs: Record<string, string>,
coinstackType: CoinstackType
): Promise<string>
**Description:** Generates a SHA-1 hash string representing the current content state of a coinstack's source code and build arguments. The hashing strategy depends on the `coinstackType`.
**Parameters:**
coinstack(string): The name of the coinstack to hash (e.g.,'proxy','bitcoin', etc.).buildArgs(Record<string,string>): Key-value pairs representing build arguments that influence the build image.coinstackType('go'|'node'): The type of coinstack.
**Returns:** A Promise resolving to a hexadecimal SHA-1 hash string.
**Throws:** An error if an invalid `coinstackType` is provided.
**Example usage:**
const hash = await getCoinstackHash('proxy', { NODE_ENV: 'production' }, 'node')
console.log(`Hash for proxy node coinstack: ${hash}`)
**Implementation detail:** Dispatches to either `getNodeCoinstackApiHash` or `getGoCoinstackApiHash` internally.
Internal Functions
getNodeCoinstackApiHash
const getNodeCoinstackApiHash = async (
coinstack: string,
buildArgs: Record<string, string>
): Promise<string>
**Description:** Generates a SHA-1 hash representing the Node.js coinstack build image contents, including selective project files, package sources, and build arguments.
**Parameters:**
coinstack(string): The name of the Node.js coinstack.buildArgs(Record<string,string>): Build arguments influencing the image.
**Returns:** A Promise resolving to a SHA-1 hash string.
**Algorithm/Implementation Details:**
Initialize a SHA-1 hash instance.
Hash the root-level "unchained" files:
package.json,lerna.json,yarn.lock, andDockerfile.node.Hash all relevant packages under
node/packages, excluding unwanted folders likedist,node_modules, andpulumi.Hash the common API folder under
node/coinstacks/common/api.If the coinstack is
'proxy', hashnode/proxy/api; otherwise hashnode/coinstacks/{coinstack}/api.Update the hash with the SHA-1 of the serialized
buildArgs.Return the final digest as a hex string.
**Important:** Uses `folder-hash` to calculate content hashes, filtering files and folders carefully to avoid transient or irrelevant files.
getGoCoinstackApiHash
const getGoCoinstackApiHash = async (
coinstack: string,
buildArgs: Record<string, string>
): Promise<string>
**Description:** Generates a SHA-1 hash representing the Go coinstack build image contents, including module files, build files, source code, and build arguments.
**Parameters:**
coinstack(string): The Go coinstack name.buildArgs(Record<string,string>): Build arguments.
**Returns:** A Promise resolving to a SHA-1 hash string.
**Algorithm/Implementation Details:**
Initialize a SHA-1 hash instance.
Hash the Go module files
go.modandgo.sumat the root of the Go directory.Hash build-related files under
go/builddirectory.Hash static assets under
go/static.Hash internal Go source files under
go/internal.Hash command source files and
.envsamples ingo/cmd/{coinstack}.Hash Go package sources under
go/pkg.Hash coinstack root Go files under
go/coinstacks/{coinstack}.Hash coinstack API files under
go/coinstacks/{coinstack}/api.Update the hash with SHA-1 of the serialized
buildArgs.Return the final hash digest as a hex string.
**Note:** Folders and files are carefully included/excluded to minimize noise and only hash relevant source code.
Implementation Details and Algorithms
Uses
folder-hashto recursively calculate deterministic hashes of selected files and folders with inclusion and exclusion filters tailored to each coinstack type and directory structure.Uses Node.js
cryptomodule to create a SHA-1 hash instance and update it progressively with folder hashes and build arguments.Serializes
buildArgsusingobject-hash's SHA-1 hash function to ensure changes in build arguments also affect the final hash.The hashing approach ensures that any modification to relevant source files or build parameters results in a new hash, useful for cache invalidation, CI/CD triggers, or build versioning.
The environment variable secret mapping function facilitates Kubernetes integration by translating
.envkeys to secrets-based environment variables.
Interactions with Other Parts of the System
Kubernetes:
ThesecretEnvsfunction returns Kubernetes environment variable references (EnvVar) that are used when deploying pods via Pulumi Kubernetes provider (@pulumi/kubernetes). This ties the secret management in deployment manifests with the environment configuration.Build System / CI/CD:
The hash functions provide a mechanism to detect changes in the codebase or build parameters. These hashes can be used in build pipelines to decide whether to rebuild Docker images or redeploy services.Configuration Management:
Uses.envparsing viadotenvto understand environment variables that need to be mapped to Kubernetes secrets.File System Structure:
Relies on a fixed directory layout withnodeandgosubdirectories under a root directory (rootDir), reflecting project structure conventions.
Visual Diagram
classDiagram
class hash {
<<utility>>
}
class secretEnvs {
+secretEnvs(assetName: string, sampleEnv: Buffer): EnvVar[]
}
class getCoinstackHash {
+getCoinstackHash(coinstack: string, buildArgs: Record<string,string>, coinstackType: CoinstackType): Promise<string>
}
class getNodeCoinstackApiHash {
-getNodeCoinstackApiHash(coinstack: string, buildArgs: Record<string,string>): Promise<string>
}
class getGoCoinstackApiHash {
-getGoCoinstackApiHash(coinstack: string, buildArgs: Record<string,string>): Promise<string>
}
getCoinstackHash --> getNodeCoinstackApiHash : calls for 'node'
getCoinstackHash --> getGoCoinstackApiHash : calls for 'go'
Summary
The `hash.ts` file is a critical utility module providing hashing capabilities for coinstack source code and build arguments, supporting both Node.js and Go implementations. It also facilitates Kubernetes secret environment variable configuration. The hash generation employs a consistent, filtered folder hashing strategy combined with cryptographic hash functions to produce concise fingerprints of code and configuration, enabling reliable build and deployment automation.