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:

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:


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:**

**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:**

**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:**

**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:**

**Returns:** A Promise resolving to a SHA-1 hash string.

**Algorithm/Implementation Details:**

  1. Initialize a SHA-1 hash instance.

  2. Hash the root-level "unchained" files: package.json, lerna.json, yarn.lock, and Dockerfile.node.

  3. Hash all relevant packages under node/packages, excluding unwanted folders like dist, node_modules, and pulumi.

  4. Hash the common API folder under node/coinstacks/common/api.

  5. If the coinstack is 'proxy', hash node/proxy/api; otherwise hash node/coinstacks/{coinstack}/api.

  6. Update the hash with the SHA-1 of the serialized buildArgs.

  7. 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:**

**Returns:** A Promise resolving to a SHA-1 hash string.

**Algorithm/Implementation Details:**

  1. Initialize a SHA-1 hash instance.

  2. Hash the Go module files go.mod and go.sum at the root of the Go directory.

  3. Hash build-related files under go/build directory.

  4. Hash static assets under go/static.

  5. Hash internal Go source files under go/internal.

  6. Hash command source files and .env samples in go/cmd/{coinstack}.

  7. Hash Go package sources under go/pkg.

  8. Hash coinstack root Go files under go/coinstacks/{coinstack}.

  9. Hash coinstack API files under go/coinstacks/{coinstack}/api.

  10. Update the hash with SHA-1 of the serialized buildArgs.

  11. 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


Interactions with Other Parts of the System


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.