Carmel CPAN Artifact Repository Manager

repository·master·Indexed 41 days ago

https://github.com/miyagawa/carmel

A CPAN module manager for reproducible development and production deployment. Carmel manages dependencies by storing build artifacts in a central repository and using a cpanfile.snapshot to pin exact versions. It provides a CLI for installing, updating, and executing commands with pinned dependencies, as well as tools for rolling out dependencies to a local directory or packaging them for vendor caches.

Tokens
2.3K
Snippets
6
Records
12
Agent score
0%

What's inside Carmel

  1. Overview of Carmel CPAN Artifact Repository Manager

    master
    Carmel is a CPAN module manager that differs from traditional installers by keeping dependency builds in a central repository. Instead of installing directly into your system or a local directory, it manages build artifacts and selects the appropriate library paths at runtime. This allows for reproducible development environments via cpanfile.snapshot and easy deployment to production via rollouts or packaging.
  2. How Carmel manages artifacts

    master

    Carmel stores build artifacts in a central repository, typically at $HOME/.carmel/{version}-{archname}/builds.

    When you run carmel install, it computes the best versions satisfying cpanfile, installs them via cpanm into this central repository, and records the mapping in cpanfile.snapshot.

    When running via carmel exec, Carmel dynamically prepends the necessary build directories to the Perl @INC array, allowing you to run applications with pinned dependencies without manually managing PERL5LIB.

  3. Compare Carmel with Carton and cpm

    master

    Carmel is a dependency manager for Perl that uses cpanfile to declare dependencies and cpanfile.snapshot to pin them. It is designed as a drop-in replacement for Carton but with improved state management.

    Key Differences from Carton

    • State Management: Unlike Carton, which relies on the contents of a local directory (which can lead to conflicts), Carmel manages all dependencies in a central repository under $HOME/.carmel. Nothing is installed in your project directory during development.
    • Reliability: Running carmel install after pulling changes to cpanfile.snapshot always installs the correct dependencies. Carton may fail to update if the existing local directory already satisfies the cpanfile requirements, even if it doesn't match the snapshot.
    • Reversibility: Because Carmel resolves dependencies dynamically based on cpanfile.snapshot, you can undo changes by simply reverting the snapshot file. Carton requires deleting the entire local directory to undo changes.

    Comparison with cpm (App::cpm)

    • Installation Target: cpm installs dependencies to a local directory, whereas Carmel uses a build cache. You can use carmel rollout to copy Carmel's managed dependencies into a local directory if needed.
    • Parallelism: cpm installs modules in parallel for speed.
    • Snapshot Management: cpm cannot manage cpanfile.snapshot on its own, but it can read it. A common workflow is using Carmel for development and cpm install to build a perl5 library path from the existing cpanfile and cpanfile.snapshot.
  4. Use carmel rollout to create a local directory

    master

    While Carmel manages dependencies in $HOME/.carmel to avoid polluting your project directory, you can explicitly create a local directory containing your project's dependencies by using the carmel rollout command. This is useful when you need a standard local directory for specific deployment or build tasks.

    # Example command to populate the local directory
    carmel rollout
  5. Update dependencies with carmel update

    master

    Use the update command to modify the versions pinned in your snapshot:

    • carmel update <Module>: Updates a specific module to the latest version from CPAN (and updates its dependencies if necessary).
    • carmel update <Module>@<Version>: Pins a module to a specific version.
    • carmel update: Updates all modules listed in your cpanfile to their latest versions.
    # Update a specific module
    carmel update Plack
    
    # Pin modules to specific versions
    carmel update DBI@1.633 Plack@1.0000
    
    # Update everything in the snapshot
    carmel update
  6. Package dependencies with carmel package

    master

    If you want to vendor your dependencies for use with cpanm on a target machine (e.g., in a CI/CD pipeline or a restricted environment), use carmel package. This creates a directory containing tarballs and CPAN-style package indexes.

    # Create a vendor cache
    carmel package
    
    # On the target machine, use cpanm to install from the vendor cache
    cpanm -L ./local --from $PWD/vendor/cache -nq --installdeps .
  7. Deploy to production using carmel rollout

    master

    To avoid requiring Carmel on production hosts or dealing with large @INC overhead, use carmel rollout. This command extracts all files from the pinned dependencies into a standard Perl library directory structure (defaults to ./local). This directory can then be used like a local::lib path.

    # Roll out dependencies to the ./local directory
    carmel rollout
    
    # Run your application using the rolled-out path
    perl -Ilocal/lib/perl5 local/bin/starman -p 8080 myapp.psgi
  8. Manage dependencies in development with carmel install

    master

    In a development workflow, use carmel install to set up your environment or update it when cpanfile changes. This command updates your build artifacts and saves the specific versions used to cpanfile.snapshot. You should commit both cpanfile and cpanfile.snapshot to your version control system to ensure consistency across machines.

    To run your application using the exact versions pinned in your snapshot, use carmel exec.

    # Setup environment
    carmel install
    
    # Run an application (e.g., Starman) with pinned dependencies
    carmel exec starman -p 8080 myapp.psgi
    
    # Run a perl command directly
    carmel exec perl -e 'use Carmel::Preload;'
  9. Use the carmel CLI

    master

    The carmel executable is used to manage Perl dependencies and environments via cpanfile and cpanfile.snapshot. It provides a suite of commands for loading modules, managing snapshots, and running scripts within a controlled environment.

    Based on the internal CLI logic, the tool operates by interpreting commands passed to Carmel::App. Common usage patterns include running commands within specific directories or executing scripts using the artifacts managed by carmel.

  10. Troubleshooting: Version conflicts and missing artifacts

    master

    Version Conflicts

    Conflicts can occur when a new dependency requires a version of a module that contradicts what is currently pinned in cpanfile.snapshot. Recommendation: Always run carmel install before making changes to your cpanfile. This ensures the build cache is prepared. If a conflict occurs, use carmel update <Module> to force an update of the conflicting module.

    Missing Artifacts

    If you see the error Can't find an artifact for Foo, it means a dependency was missed during the initial carmel install. This is a known issue with certain modules. Check the Carmel issue tracker for known problematic modules.

    Taint Mode

    Carmel does not support Perl's Taint mode (-T). Running with -T will result in an error: Insecure dependency in require while running with -T switch.

  11. Reference: Carmel CLI Commands

    master

    The following commands are available in the carmel CLI:

    CommandDescription
    installInstalls modules from cpanfile and updates cpanfile.snapshot
    listLists all modules to be loaded
    treeLists all modules in a tree structure
    show <Module>Shows the installation location of a module
    update <Module>Updates a specific module to the latest version
    updateUpdates all modules in the snapshot
    update <Mod>@<Ver>Pins modules to specific versions
    diffShows diffs for cpanfile.snapshot in a readable format
    exec <cmd>Runs a command using modules from artifacts
    rolloutRolls out build artifacts into a ./local directory
    packagePackages tarballs and index into ./vendor/cache
    exportPrints environment variables (like PATH) for shell scripting
    find <Module>Finds a module in a repository
    find <Module> "<Query>"Finds a module matching a version query
  12. Execute carmel commands via the API

    master

    For developers integrating carmel into testing frameworks or automation scripts, the xt::CLI module provides a TestCLI class to simulate and capture CLI execution.

    Key methods for programmatic execution include:

    • run(@args): Executes a carmel command and captures stdout, stderr, and the exit_code.
    • cmd(@args): Executes a system command and captures output.
    • run_in_dir($dir, @args): Executes a carmel command within a specific subdirectory.
    • cmd_in_dir($dir, @args): Executes a system command within a specific subdirectory.
    • run_ok(@args): Runs a command and asserts that the exit_code is 0.
    • run_fails(@args): Runs a command and asserts that the exit_code is non-zero.
    use xt::CLI;
    
    my $cli = cli(clean => 1);
    $cli->write_cpanfile("module A", "module B");
    $cli->run_ok("list");