Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/wasm-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ jobs:
override: true

- name: Build wasm
run: cargo build --target wasm32-unknown-unknown --release --manifest-path contracts/token-factory/Cargo.toml
run: cargo build --locked --target wasm32-unknown-unknown --release --manifest-path contracts/token-factory/Cargo.toml
1 change: 1 addition & 0 deletions .kiro/specs/cargo-lock-version-control/.config.kiro
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specId": "695ef77b-6e75-4bf1-905a-d174b32fbfc1", "workflowType": "requirements-first", "specType": "feature"}
148 changes: 148 additions & 0 deletions .kiro/specs/cargo-lock-version-control/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Design Document: Cargo.lock Version Control

## Overview

This feature ensures `Cargo.lock` is committed to the repository and that CI builds use the exact locked dependency versions. The token-factory contract is a deployable binary artifact (`cdylib`), so Rust best practices require committing `Cargo.lock` for reproducible builds.

The change set is minimal and surgical:
1. Remove any `.gitignore` rules that suppress `Cargo.lock` within `contracts/`
2. Commit `contracts/Cargo.lock` to the repository
3. Add `--locked` to the `cargo build` invocation in `.github/workflows/wasm-build.yml`

## Architecture

The feature touches three files:

```
.gitignore # ensure no Cargo.lock ignore rule exists
contracts/Cargo.lock # add to version control (generate if absent)
.github/workflows/wasm-build.yml # add --locked flag to cargo build step
```

No new components, services, or abstractions are introduced. This is a repository hygiene change.

```mermaid
flowchart LR
A[Developer clones repo] --> B[contracts/Cargo.lock present]
B --> C[cargo build --locked --target wasm32-unknown-unknown --release]
C -->|Cargo.lock matches Cargo.toml| D[Build succeeds]
C -->|Cargo.lock absent or inconsistent| E[Build fails with non-zero exit]
```

## Components and Interfaces

### .gitignore

Current state: no rule suppresses `Cargo.lock` (confirmed — the file only ignores `node_modules/`, `dist/`, `.env`, `.env.local`, `*.local`).

Required state: same — no action needed on `.gitignore` unless a rule is added in the future.

### contracts/Cargo.lock

Generated by running `cargo generate-lockfile` (or any `cargo build`/`cargo check`) inside the `contracts/` workspace. Once generated, the file is committed and tracked by Git.

The lock file records the exact resolved version of every dependency in the workspace, including transitive ones. For the token-factory crate this includes `soroban-sdk`, `soroban-token-sdk`, `proptest`, and all their transitive dependencies.

### .github/workflows/wasm-build.yml

The `Build wasm` step currently runs:
```
cargo build --target wasm32-unknown-unknown --release --manifest-path contracts/token-factory/Cargo.toml
```

It must be updated to:
```
cargo build --locked --target wasm32-unknown-unknown --release --manifest-path contracts/token-factory/Cargo.toml
```

The `--locked` flag instructs Cargo to use only the versions recorded in `Cargo.lock` and to fail if the lock file is absent or inconsistent with `Cargo.toml`.

## Data Models

### Cargo.lock structure (informational)

`Cargo.lock` is a TOML file managed entirely by Cargo. Its schema is:

```toml
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "token-factory"
version = "0.1.0"
dependencies = [
"soroban-sdk 21.x.x ...",
...
]

[[package]]
name = "soroban-sdk"
version = "21.x.x"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "<sha256>"
dependencies = [...]
```

No application-level data model changes are required. The lock file is an opaque artifact from Cargo's perspective.

## Correctness Properties

*A property is a characteristic or behavior that should hold true across all valid executions of a system — essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*

### Property 1: Cargo.lock is present and tracked

*For any* fresh clone of the repository, the file `contracts/Cargo.lock` SHALL exist on disk and SHALL be tracked by Git (i.e., `git ls-files contracts/Cargo.lock` returns a non-empty result).

**Validates: Requirements 1.2, 1.3**

### Property 2: .gitignore does not suppress Cargo.lock

*For any* state of the `.gitignore` file, no pattern in it SHALL cause Git to ignore `Cargo.lock` files under the `contracts/` directory.

**Validates: Requirements 1.1**

### Property 3: CI build uses --locked flag

*For any* invocation of the WASM build CI job, the `cargo build` command SHALL include the `--locked` flag, ensuring dependency resolution is constrained to the versions in `Cargo.lock`.

**Validates: Requirements 2.1**

### Property 4: CI fails on missing or inconsistent Cargo.lock

*For any* CI run where `Cargo.lock` is absent or where `Cargo.toml` specifies dependencies inconsistent with `Cargo.lock`, the build step SHALL exit with a non-zero status code.

**Validates: Requirements 2.2**

## Error Handling

| Scenario | Behavior |
|---|---|
| `Cargo.lock` absent in CI | `cargo build --locked` exits non-zero; CI job fails and reports the error |
| `Cargo.lock` inconsistent with `Cargo.toml` | `cargo build --locked` exits non-zero with message "Cargo.lock needs to be updated" |
| `.gitignore` accidentally re-adds a Cargo.lock rule | `git status` will show `contracts/Cargo.lock` as untracked; developer must remove the rule |

No runtime error handling is needed — all failure modes surface at build/CI time.

## Testing Strategy

This feature is a repository configuration change, not application logic. Testing is therefore structural and CI-based rather than unit/property-based in the traditional sense.

### Unit / Example Tests (shell-level checks)

These can be run locally or in a separate CI lint job:

1. **Gitignore check**: Assert that `git check-ignore -v contracts/Cargo.lock` returns a non-zero exit code (meaning the file is NOT ignored).
2. **Lock file presence**: Assert that `git ls-files --error-unmatch contracts/Cargo.lock` succeeds (file is tracked).
3. **CI flag check**: Assert that `wasm-build.yml` contains the string `--locked`.

### Property-Based Tests

The properties in this feature are structural/configuration properties rather than algorithmic ones. They are best validated by the CI pipeline itself:

- **Property 1 & 2**: Validated by the presence of `contracts/Cargo.lock` in the Git tree and the absence of a suppressing `.gitignore` rule. These are checked on every CI run via `git ls-files`.
- **Property 3 & 4**: Validated by the CI job itself — if `--locked` is present and `Cargo.lock` is committed and consistent, the build passes; otherwise it fails.

**Property-Based Testing Library**: Not applicable for this feature. The correctness properties are configuration invariants verified by Cargo's own `--locked` enforcement and Git's tracking mechanism, not algorithmic properties requiring randomized input generation.

**CI as the test harness**: Every push to `main` or PR targeting `main` exercises Properties 3 and 4 automatically via the updated `wasm-build.yml`.
37 changes: 37 additions & 0 deletions .kiro/specs/cargo-lock-version-control/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Requirements Document

## Introduction

The token-factory contract is a deployable Soroban smart contract (binary/application crate). Per Rust best practices, `Cargo.lock` should be committed to version control for such crates to ensure reproducible builds across all environments. Currently, `Cargo.lock` is absent from the repository. This feature tracks it, removes any ignore rules that would suppress it, and updates CI to respect the locked dependency versions.

## Glossary

- **Cargo.lock**: The file generated by Cargo that records the exact versions of all resolved dependencies for a Rust workspace or crate.
- **Token_Factory_Contract**: The Soroban smart contract located at `contracts/token-factory/`, built as a `cdylib` deployable artifact.
- **CI**: The GitHub Actions continuous integration pipeline defined in `.github/workflows/wasm-build.yml`.
- **Gitignore**: The `.gitignore` file at the repository root that controls which files Git tracks.
- **Locked_Build**: A `cargo build` invocation that uses the exact dependency versions recorded in `Cargo.lock` rather than resolving the latest compatible versions.

## Requirements

### Requirement 1: Cargo.lock Is Tracked by Version Control

**User Story:** As a developer, I want `Cargo.lock` committed to the repository, so that every checkout of the codebase produces a build with identical dependency versions.

#### Acceptance Criteria

1. THE Gitignore SHALL NOT contain any rule that causes Git to ignore `Cargo.lock` files within the `contracts/` directory.
2. WHEN a developer clones the repository, THE Token_Factory_Contract workspace SHALL include a `Cargo.lock` file at `contracts/Cargo.lock`.
3. THE `contracts/Cargo.lock` file SHALL be present and tracked in the Git repository.

---

### Requirement 2: CI Builds Use Locked Dependency Versions

**User Story:** As a developer, I want CI to build the contract using the exact versions in `Cargo.lock`, so that CI results are reproducible and consistent with local builds.

#### Acceptance Criteria

1. WHEN the CI pipeline runs the WASM build job, THE CI SHALL invoke `cargo build` with the `--locked` flag so that dependency resolution is constrained to the versions recorded in `Cargo.lock`.
2. IF `Cargo.lock` is absent or inconsistent with `Cargo.toml` during a CI run, THEN THE CI SHALL fail the build with a non-zero exit code.
3. THE CI WASM build step SHALL target `wasm32-unknown-unknown` and build in `--release` mode, consistent with the existing build configuration.
53 changes: 53 additions & 0 deletions .kiro/specs/cargo-lock-version-control/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Implementation Plan: Cargo.lock Version Control

## Overview

Three surgical changes: verify `.gitignore` has no suppressing rule, generate and commit `contracts/Cargo.lock`, and add `--locked` to the CI `cargo build` step.

## Tasks

- [x] 1. Verify .gitignore does not suppress Cargo.lock
- Inspect `.gitignore` and confirm no pattern matches `Cargo.lock` files under `contracts/`
- If a suppressing rule exists, remove it
- _Requirements: 1.1_

- [ ]* 1.1 Write shell-level check for gitignore property
- **Property 2: .gitignore does not suppress Cargo.lock**
- Assert `git check-ignore -v contracts/Cargo.lock` exits non-zero (file is NOT ignored)
- **Validates: Requirements 1.1**

- [x] 2. Generate and commit contracts/Cargo.lock
- Run `cargo generate-lockfile --manifest-path contracts/Cargo.toml` (or `cargo check`) inside the `contracts/` workspace to produce `contracts/Cargo.lock`
- Ensure the file is staged and committed to the repository
- _Requirements: 1.2, 1.3_

- [ ]* 2.1 Write shell-level check for lock file presence property
- **Property 1: Cargo.lock is present and tracked**
- Assert `git ls-files --error-unmatch contracts/Cargo.lock` succeeds
- **Validates: Requirements 1.2, 1.3**

- [x] 3. Add --locked flag to CI WASM build step
- In `.github/workflows/wasm-build.yml`, update the `Build wasm` step from:
`cargo build --target wasm32-unknown-unknown --release --manifest-path contracts/token-factory/Cargo.toml`
to:
`cargo build --locked --target wasm32-unknown-unknown --release --manifest-path contracts/token-factory/Cargo.toml`
- _Requirements: 2.1, 2.2, 2.3_

- [ ]* 3.1 Write shell-level check for --locked flag property
- **Property 3: CI build uses --locked flag**
- Assert that `.github/workflows/wasm-build.yml` contains the string `--locked`
- **Validates: Requirements 2.1**

- [ ]* 3.2 Write shell-level check for CI failure on missing/inconsistent Cargo.lock
- **Property 4: CI fails on missing or inconsistent Cargo.lock**
- Assert that removing `contracts/Cargo.lock` and running `cargo build --locked ...` exits non-zero
- **Validates: Requirements 2.2**

- [x] 4. Final checkpoint
- Ensure all checks pass, ask the user if questions arise.

## Notes

- Tasks marked with `*` are optional and can be skipped for faster MVP
- Properties 1–4 are configuration invariants enforced by Git and Cargo's `--locked` mechanism, not algorithmic properties requiring a PBT library
- Every push to `main` or PR targeting `main` will exercise Properties 3 and 4 automatically via the updated `wasm-build.yml`
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
{
"kiroAgent.configureMCP": "Disabled"
}
Loading
Loading