Showing posts with label CLI. Show all posts
Showing posts with label CLI. Show all posts

Creating 18 Engine descriptions

Mike's Notes

18 working engines are currently being imported into Pipi Core, configured, and tested.

Alex has sent me a DeepSeek chat that generated descriptions of those engines and how they worked together by analysing the existing web page "20 Engines". DeepSeek also produced a Mermaid Diagram from Markdown code based on those descriptions. DeepSeek was partially correct in some descriptions.

The Mermaid diagram was wrong, but what a great tool for Pipi to self-document with CL and accurate Markdown descriptions. It will be widely used in future as a plugin.

Feedback and suggestions are very welcome as always.

Update 23/05/2026

Java and CGI Engines added for interoperability by Pipi.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

23/05/2026

Creating 18 20 Engine descriptions

By: Mike Peters
On a Sandy Beach: 06/05/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

Most Pipi engines have historically been poorly described. This is an attempt to write better descriptions for the 18 20 engines currently being imported.  I had a go, then used Gemini to come up with better wording, then Mrs Grammarly did her bit. 😎

Much later, once the workspace UI are working, a one-page summary about each engine can be written for the pipiWiki. The Wiki Engine (wik) in the resources above has an example of such a summary.

Note: These are listed in the order they are being imported.

Descriptions

Each engine has;

  • Unique Name (Unique 3-letter code)
  • S: Short description suitable for tooltips under 100 characters.
  • D: Description under 255 characters.

System Engine (sys)

  • S: System identity and lifecycle controller.
  • D: Manages the vital signs and lifecycle of Pipi’s dynamic engine ecosystem, fostering complex emergent behaviours through seamless interaction.

Nest Engine (nst)

  • S: Host and environment interface bridge.
  • D: Serves as the foundational gateway between the host OS, JVM, the application server, CGI, and the internal Pipi environment.

JVM Engine (jvm)

  • S: JVM interoperability.
  • D: Provides Pipi with a way to work directly with an external JVM.

CGI Engine (cgi)

  • S: CGI interoperability.
  • D: Provides Pipi with a way to work directly with external CGI.

Namespace Engine (nsp)

  • S: Global identification and addressing.
  • D: Enforces a conflict-free global naming convention, ensuring every system element is uniquely addressable across the entire platform.

Render Engine (rnd)

  • S: Static file and asset rendering.
  • D: Processes and renders static resources, including HTML, CSS, source code, and databases.

Template Engine (tem)

  • S: Reusable pattern templates.
  • D: Manages reusable structural pattern templates used by the CMS to generate database-driven pages and components.

Variables Engine (var)

  • S: Centralised variables library.
  • D: Provides a centralised repository for managing variables used across templates, system configurations, and executable logic.

Log Engine (log)

  • S: Universal logging and telemetry controller.
  • D: Aggregates and configures logging parameters across all active engines to provide system-wide transparency and diagnostics.

Data Engine (dta)

  • S: Database lifecycle and CRUD operations.
  • D: Generates SQL to command the creation, evolution, and deletion of databases and their underlying data objects with full administrative control.

Configuration Engine (cnf)

  • S: Engine blueprint and manufacturing settings.
  • D: Supplies the precise DNA and configuration parameters required for the automated fabrication of individual Pipi engines.

Versioning Engine (ver)

  • S: Semantic versioning and update tracker.
  • D: Maintains system integrity by aggregating incremental updates from all engines into a unified semantic versioning timeline.

Code Engine (cde)

  • S: Internal code generation.
  • D: Facilitates automated code generation, including class libraries and logic synthesis directly within the Pipi platform.

Conductor Engine (cnd)

  • S: Internal process regulator.
  • D: Operates as the high-level orchestrator for major internal system processes and synchronisation.

Directory Engine (dir)

  • S: CMS file system and path manager.
  • D: Manages the logical and physical file system directories generated and utilised by the CMS.

Node Engine (nde)

  • S: Hierarchical template tree architect.
  • D: Maintains the addressable tree structure of templates to define content hierarchy within the CMS.

CMS Engine (cms)

  • S: Digital content management.
  • D: Powers the end-to-end lifecycle of digital content, from initial creation and editing to final publishing.

Core Engine (cor)

  • S: Primary system driver and logic hub.
  • D: The central engine that powers fundamental system behaviours and executes the primary logic that keeps Pipi running.

Factory Engine (fac)

  • S: Automated engine fabrication.
  • D: Assembles and deploys engines based on stored configuration files and real-time updates.

Page Engine (pge)

  • S: Semantic relationship and metadata mapper.
  • D: Maps external relationships for pages, managing keywords, references, and "See Also" semantic connections.

Pipi autonomous Read-Eval-Print-Loop (REPL)

Mike's Notes

Deployment roadmap

Later in the year, Pipi will be able to deploy infrastructure on any platform using Infrastructure as Code (IaC).

Options on how to do this include;

  • CL (Command Line)
  • REPL (Read-Eval-Print-Loop)
  • API

Implementing a REPL (Read-Eval-Print-Loop) programmatically in CFML

I asked Google Search AI Mode (powered by Google Gemini) how to use CFML to write and read REPL.

The Google output has been reformatted but not edited, and the code needs to be tested. The questions were turned into headings. There is a lot of duplication.

I find that carefully using Gemini to write CFML code and then checking everything is making me more productive.

There is now enough here to set up REPL.

Once this automation is complete, productivity will increase by at least x10.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

04/04/2026

Pipi autonomous Read-Eval-Print-Loop (REPL)

By: Mike Peters and Gemini
On a Sandy Beach: 04/04/2026

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

Gemini is still cool.

A Read-Eval-Print-Loop (REPL) is an interactive computer programming environment that accepts single-user input, executes it, and returns the result immediately. It is also known as an interactive toplevel or language shell. [1, 2, 3] 

The Four Steps of the Loop

The name describes the precise cycle the environment follows: [4, 5] 

  • Read: The system accepts a line of input (usually a single expression or command) from the user.
  • Eval: It parses and evaluates the input code to determine its value or effect.
  • Print: The resulting value or output is displayed back to the user on the screen.
  • Loop: The process repeats, returning to the prompt to wait for the next input. [1, 5, 6, 7, 8, 9, 10] 

Why Developers Use REPLs

REPLs are highly valued for their tight feedback loop, which allows for: [6, 7, 11] 

  • Interactive Prototyping: Quickly testing small snippets of code without creating and saving files.
  • Debugging: Investigating the state of a program and testing potential fixes in real-time.
  • Learning: Experimenting with new language features or libraries with instant results.
  • Calculations: Using the environment as a high-powered calculator for mathematical expressions. [1, 12, 13, 14, 15, 16, 17] 

Common Examples

Most modern programming languages provide a built-in REPL or have popular third-party versions: [1, 18] 

References

Implementing REPL programmatically in CFML

Implementing a REPL (Read-Eval-Print-Loop) programmatically in CFML involves creating a loop that captures user input, evaluates it as live code, and returns the result. [1, 2, 3] 

While Adobe ColdFusion (2018+) and CommandBox include built-in REPLs for terminal use, you can build your own programmatic version using the following core functions: [2, 4]

1. The Evaluation Engine

The most critical part of a REPL is the Eval step. CFML provides two primary ways to execute strings as code:

  • Evaluate(): Best for executing single expressions and returning a value.
  • Render(): (Lucee specific) Similar to Evaluate, but specifically designed to execute CFML tag or script code and return the generated output as a string. [5, 6] 

2. Building a Basic Web-Based REPL

A programmatic REPL usually consists of a simple loop (often via a form submission) that maintains state.

// 1. READ: Get input from a form or API
inputCode = form.myScript ?: "";
if (len(trim(inputCode))) {
    try {
        // 2. EVAL: Execute the code
        // Note: Evaluate() is powerful but dangerous with untrusted input
        result = evaluate(inputCode);
        
        // 3. PRINT: Output the result
        writeOutput("Result: " & result);
    } catch (any e) {
        writeOutput("Error: " & e.message);
    }
}
// 4. LOOP: Handled by the user submitting the form again

3. Advanced Implementation Details

To create a more robust "shell-like" experience:

  • Persistent State: To keep variables alive across multiple inputs, store a "context" structure in a persistent scope like Session or Application.
  • Capturing Console Output: If the code uses writeOutput(), you may need to use cfsavecontent to capture that output before it hits the main buffer.
  • Safety: Never expose a REPL to public users. It allows for arbitrary code execution, which can delete files or access sensitive server data.
  • Multi-line Support: For more complex scripts, you may need to detect if a block (like an if statement or function) is complete before evaluating, similar to how [CommandBox's REPLParser](https://community.ortussolutions.com/t/replparser-multiline-support/9559) works. [6, 7, 8] 

Summary of Tools

Feature [2, 3] Function/Tool Platform
Expression Eval Evaluate(string) Adobe & Lucee
Full Code Execution Render(string) Lucee Only
Terminal REPL cf.bat / cf.sh Adobe (2018+)
CLI REPL box repl CommandBox

References

Using workflows written in CFML to write and read REPL

To build a workflow in CFML that programmatically reads from and writes to a REPL, you need to treat the REPL as an external process. This is most effectively done using CommandBox, which provides a robust CLI and REPL environment for CFML. [1, 2] 

1. Using CommandBox via cfexecute

The standard way to interact with a REPL from a running CFML workflow (like a background task or a web request) is to use <cfexecute> or the execute() function to call the [CommandBox binary](https://modern-cfml.ortusbooks.com/intro/instructions-and-interpreters).

  • Writing to REPL: You can pass CFML code directly to the CommandBox repl command using the --code flag or by piping input.
  • Reading from REPL: The output of the command is captured in a variable for your workflow to process. [3, 4, 5] 

Example: Running a Snippet and Capturing the Result

// Define the CFML code you want the REPL to evaluate
replInput = "x = 10; y = 20; writeOutput(x + y);";
// Execute CommandBox REPL with the code
execute(
    name = "box", 
    arguments = "repl --code=""#replInput#""", 
    variable = "replOutput", 
    timeout = 10
);
// Read the result back into your workflow
writeOutput("The REPL returned: " & replOutput);

2. Interactive Workflows with Piping

If your workflow needs to chain multiple operations, you can use the cfml command in CommandBox. This allows you to [pipe data](https://commandbox.ortusbooks.com/usage/execution/cfml-functions) between CFML functions as if they were terminal commands.

  • Workflow logic: #listGetAt www.foo.com 2 . | #ucase | #reverse
  • Result: The REPL processes each step and passes the "Read" result of one to the "Eval" of the next. [6, 7] 

3. Asynchronous "Daemon" REPL

For a long-running workflow that needs to keep a REPL "warm" (to avoid startup overhead), consider using an Event Gateway or a persistent background thread. [8] 

  1. Start a process: Use java.lang.ProcessBuilder via CFML to open a persistent connection to the CommandBox shell.
  2. Write to Stream: Send commands to the process's OutputStream.
  3. Read from Stream: Use a separate CFML thread to constantly poll the InputStream for the REPL's response. [9, 10] 

4. Safety and Best Practices

  • Sanitisation: If the input for your REPL comes from an external source, treat it as unsafe. Programmatic REPLs can execute fileDelete() or access system environment variables.
  • Timeouts: Always set a timeout in your execute calls to prevent a "loop" in the REPL from hanging your entire server.
  • Context: Remember that code executed in a separate REPL process does not share the same variable scope (like Session or Request) as your main workflow unless you explicitly pass those values in. [11] 

References

Pass complex data (like a Struct) between your workflow and a CommandBox REPL

To pass complex data, such as a Struct or Array, between a CFML workflow and a REPL, the most reliable method is to use JSON serialisation. Since the REPL and your main application run in separate memory spaces, JSON acts as a universal bridge for data exchange.

1. Passing a Struct into the REPL (Write)

When calling the REPL, convert your CFML Struct into a JSON string and inject it into the command as a literal. CommandBox’s REPL is smart enough to interpret a JSON string as a native Struct if it's the first input to certain functions or assigned directly. [1, 2] 

// Your complex workflow data
userData = {
    "id": 123,
    "roles": ["admin", "editor"],
    "settings": { "theme": "dark" }
};
// Serialize to JSON (use single quotes for the shell command)
jsonInput = serializeJSON(userData);
// Build the REPL command
// Note: We assign the JSON string directly to a variable inside the REPL
replCommand = "data = #jsonInput#; writeOutput(data.roles[1]);";
execute(
    name = "box",
    arguments = "repl --code=""#replCommand#""",
    variable = "replResponse"
);
writeOutput("REPL processed role: " & replResponse); // "admin"

2. Getting a Struct back from the REPL (Read)

To read complex data back into your workflow, have the REPL print the result as JSON. You then use deserializeJSON() in your main workflow to turn that string back into a live CFML Struct. [3] 

// REPL code that performs logic and returns a new struct
replCode = "result = { 'status': 'success', 'timestamp': now() }; writeOutput(serializeJSON(result));";
execute(
    name = "box",
    arguments = "repl --code=""#replCode#""",
    variable = "rawJsonResponse"
);
// Read the complex data back into your workflow
if (isJSON(rawJsonResponse)) {
    finalData = deserializeJSON(rawJsonResponse);
    writeOutput("Status received: " & finalData.status);
}

Key Considerations for Data Integrity

  • Key Casing: Adobe ColdFusion typically converts struct keys to UPPERCASE during serialisation unless you quote the keys (e.g., {"name": "value"}).
  • Shell Escaping: Be careful with double quotes inside your JSON. When building the arguments string for execute(), ensure you escape quotes correctly so the shell doesn't break the command.
  • Performance: If you are passing very large datasets (multi-MB structs), the overhead of serialisation and shell execution will increase. For high-frequency workflows, consider writing the data to a temporary JSON file and having the REPL read that file instead of passing it as a command-line argument. [4, 5, 6, 7] 

Using temporary files to handle larger datasets between your workflow and the REPL

To handle larger datasets between your CFML workflow and a REPL, using temporary files is the most reliable method. This avoids shell character limits and prevents memory issues. [1] 

1. The Workflow: Writing to a Temp File

First, your main application serialises the data into a JSON file. Use getTempFile() to ensure a unique filename that won't collide with other processes. [2, 3] 

// 1. Prepare your large dataset
complexData = {
    "users": queryToArray( myLargeUserQuery ), // Assume 10k rows
    "metadata": { "source": "workflow_alpha", "processed": now() }
};
// 2. Create a unique temp file
tempFilePath = getTempFile( getTempDirectory(), "repl_data" );
// 3. WRITE: Save the JSON to the file
fileWrite( tempFilePath, serializeJSON( complexData ) );

2. The REPL: Reading the File

When you execute the REPL, pass the file path as a variable. The REPL code will then read the file from disk and deserialise it back into a native CFML object. [4, 5] 

// 4. Build the REPL script to READ the file
replCode = "
    data = deserializeJSON( fileRead('#tempFilePath#') );
    // Perform complex logic on the data
    resultCount = data.users.len();
    writeOutput( resultCount );
";
// 5. EXECUTE: Call CommandBox REPL
execute(
    name = "box",
    arguments = "repl --code=""#replCode#""",
    variable = "replOutput"
);

3. Cleaning Up

Because these files are stored in the system's temporary directory, they will eventually be cleared, but it is best practice to delete them manually once your workflow is finished to save disk space. [1, 6] 

// 6. Cleanup after reading the result
if ( fileExists( tempFilePath ) ) {
    fileDelete( tempFilePath );
}
writeOutput( "REPL processed #replOutput# records." );

Why use files instead of variables?

  • Memory Efficiency: Large strings in shell commands can lead to "Out of Memory" (OOM) errors or exceed operating system command-line length limits.
  • Data Integrity: Files eliminate the need for complex shell quoting and escaping of special characters in your JSON.
  • Persistent Context: If the REPL crashes, the data remains safely on disk for debugging or a retry attempt. [1, 7] 

References

CommandBox Task Runners to make these multi-step REPL workflows even cleaner

While a REPL is great for ad-hoc snippets, CommandBox Task Runners provide a more structured way to handle multi-step workflows. A Task Runner is a CFML component (.cfc) that runs directly from the command line, allowing you to pass complex arguments naturally and use built-in helpers for file and shell interaction. [1, 2, 3, 4]

1. Create the Task Runner (MyTask.cfc) [5]

Instead of cramming logic into a string for the REPL, you write a standard CFML function. You can create one by running task create --open in [CommandBox](https://commandbox.ortusbooks.com/task-runners). [2, 3, 6] 

/**
 * MyTask.cfc
 * Automates a workflow with complex data
 */
component {
    
    function run( string inputPath ) {
        // 1. READ: Load the large dataset from the file
        var data = deserializeJSON( fileRead( arguments.inputPath ) );
        
        print.greenLine( "Processing #data.users.len()# users..." );

        // 2. EVAL: Perform your workflow logic
        var result = {
            "processedCount": data.users.len(),
            "timestamp": now(),
            "status": "complete"
        };

        // 3. PRINT: Return the result as JSON for the calling workflow
        print.text( serializeJSON( result ) );
    }
}

2. Execute the Task from your Workflow [5]

In your main application, you call the task just like you did with the REPL, but it’s much cleaner because the logic is encapsulated in its own file. [7, 8] 


// Path to your Task Runner CFC
taskPath = expandPath( "./MyTask.cfc" );
tempDataFile = getTempFile( getTempDirectory(), "data" );

// Prepare and write data
fileWrite( tempDataFile, serializeJSON( myLargeStruct ) );

// Execute the task via CommandBox
execute(
    name = "box",
    arguments = "task run taskFile=#taskPath# inputPath=#tempDataFile#",
    variable = "rawResult"
);

// Process the structured return
workflowResult = deserializeJSON( rawResult );
writeOutput( "Workflow finished at: #workflowResult.timestamp#" );

Why Task Runners are better for workflows:

  • Portability: Tasks are self-contained in a CFC and can be dropped into any folder without being a full module.
  • Built-in Helpers: You get access to the print helper for formatted console output and filesystemUtil for easy path resolution.
  • Named Parameters: Unlike the REPL, tasks support [named parameters](https://commandbox.ortusbooks.com/task-runners/running-other-tasks), making it easy to pass file paths, IDs, or configuration flags.
  • Readability: Your code is written in a standard IDE with syntax highlighting and error checking rather than as a string inside an execute() call. [1, 3, 9, 10, 11] 

References

Scheduling these tasks to run automatically at specific intervals

To schedule CommandBox Task Runners at specific intervals, you have three primary approaches depending on whether you want to use the operating system, a background process (daemon), or the ColdFusion engine itself. [1] 

1. The Daemon Approach (Self-Scheduling)

For workflows that need to run continuously in the background without external dependencies, you can write your task as a daemon. This involves a while(true) loop and a sleep() command within the CFC. [2, 3] 

/**
 * ScheduledTask.cfc
 * Run: box task run taskFile=ScheduledTask.cfc
 */
component {
    function run() {
        try {
            while( true ) {
                print.blueLine( "Running workflow at #now()#..." );
                
                // INSERT YOUR WORKFLOW LOGIC HERE
                
                // Sleep for 5 minutes (300,000 milliseconds)
                sleep( 300000 );
            }
        } catch( any e ) {
            print.redLine( "Task interrupted: #e.message#" );
        }
    }
}

2. OS-Level Scheduling (Cron / Task Scheduler)

This is the most "production-ready" method for strictly timed intervals (e.g., every day at 2 AM). You simply tell your OS to execute the CommandBox binary and your specific task file. [3, 4, 5, 6] 

  • Linux (Crontab): Add a line to your crontab using crontab -e:
    0 2 * * * /usr/local/bin/box task run /path/to/MyTask.cfc
  • Windows (Task Scheduler): Create a new task that runs the box.exe program with the arguments task run taskFile=C:\path\to\MyTask.cfc. [7, 8, 9] 

3. CFML Engine Scheduling (cfschedule) [10] 

If you want to manage the schedule from within your web application's admin interface or code, you can use the native <cfschedule> tag or cfschedule() function to call the CommandBox CLI. [10, 11] 

cfschedule(
    action    = "update",
    task      = "HourlyWorkflow",
    operation = "HTTPRequest",
    url       = "http://localhost/run_my_task.cfm", // A script that runs the task
    interval  = "3600" // Every hour
);

Note: Your run_my_task.cfm file would then contain the execute() call to trigger the CommandBox task.

4. Advanced: ColdBox Scheduled Tasks

If you are using the [ColdBox Framework](https://coldbox.ortusbooks.com/digging-deeper/scheduled-tasks), you can use the built-in Async Scheduler to define tasks with a fluent, human-readable API. [1, 9, 12] 

// inside your Scheduler.cfc
task( "CleanTempFiles" )
    .call( function(){
        // CommandBox execution logic here
    } )
    .every( 1, "hours" )
    .delay( 5, "minutes" );

References

Using GitHub Actions to CLI JFrog, AWS, GCP

Mike's Notes

What I'm learning today. I'm learning fast as I go. It's all new :)

BoxLang will be the platform on which Pipi 10 runs.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

22/11/2025

Using GitHub Actions to CLI JFrog, AWS, GCP

By: Mike Peters
On a Sandy Beach: 21/11/2025

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

I finally figured out how to implement CI/CD so Pipi can autonomously manage all remote cloud platforms.

  • AWS
  • Azure
  • GCP
  • IBM
  • etc

I was watching a video from the MLOPs community email that led me to JFrog (very useful), which led me to GitHub Actions. I had been looking for a way to enable Pipi 9 to autonomously control any Cloud Platform, but I did not know the correct technical terms, so I was asking the wrong questions. It's one of the disadvantages of being completely self-taught.

Use GitHub Actions

According to Google AI ..."

GitHub Actions can effectively control both Google Cloud Platform (GCP) and Amazon Web Services (AWS) Command Line Interfaces (CLIs) within your CI/CD workflows. This enables automation of cloud resource management, deployments, and other cloud-related tasks directly from your GitHub repositories.

  • Controlling AWS CLI with GitHub Actions:
  • Configure AWS Credentials:
  • Store your AWS Access Key ID and Secret Access Key as GitHub Secrets in your repository settings.

Use the aws-actions/configure-aws-credentials action to configure the AWS CLI with these secrets within your workflow. This action handles the secure setup of credentials for subsequent AWS CLI commands.

Execute AWS CLI Commands:

Once credentials are configured, you can use the run step in your workflow to execute any AWS CLI command.

Example:

Code

        - name: Configure AWS Credentials
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
            aws-region: us-east-1

        - name: List S3 Buckets
          run: aws s3 ls

Controlling GCP CLI (gcloud) with GitHub Actions:

Authenticate to GCP:

Store your GCP Service Account Key (JSON format) as a GitHub Secret.
Use the google-github-actions/auth action to authenticate your workflow to GCP using this service account key.

Setup gcloud CLI:

Use the google-github-actions/setup-gcloud action to install and configure the gcloud CLI within your workflow. You can specify the desired gcloud version and project ID.

Execute gcloud Commands:

After authentication and gcloud setup, you can use the run step to execute gcloud commands.

Example:

Code

        - name: Authenticate to GCP
          uses: google-github-actions/auth@v1
          with:
            credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}

        - name: Setup gcloud CLI
          uses: google-github-actions/setup-gcloud@v1
          with:
            project_id: your-gcp-project-id

        - name: List GCS Buckets
          run: gcloud storage ls

Key Considerations:
  • Security: Always use GitHub Secrets to store sensitive credentials and implement the principle of least privilege for your cloud service accounts/IAM roles. Consider using OpenID Connect (OIDC) for enhanced security with AWS and GCP.
  • Actions Marketplace: Leverage pre-built actions from the GitHub Marketplace for common tasks like credential configuration and CLI setup, as demonstrated above.
  • Error Handling: Include error handling and logging in your workflows for better debugging and reliability.
  • Idempotency: Design your cloud operations to be idempotent, ensuring that running the workflow multiple times produces the same desired state without unintended side effects.

JFrog

JFrog looks great. Not cheap, but no one is better at security than the Israelis. They are the best in the world. So using their kit is a no-brainer.

There is no free tier, so plan for future use.

Next Question

  • Pipi can use CFML to easily output any of the code listed above.
  • How does that generated code then get into GitHub Actions?
  • So Pipi 9 can autonomously control GitHub Actions. (or GitLab, etc)
  • Would BoxLang do the job?
  • Am I using the correct technical terms?

Interesting examples

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Build and Deploy to GKE

on:
  push:
    branches:
      - main

env:
  PROJECT_ID: ${{ secrets.GKE_PROJECT }}
  GKE_CLUSTER: cluster-1    # Add your cluster name here.
  GKE_ZONE: us-central1-c   # Add your cluster zone here.
  DEPLOYMENT_NAME: gke-test # Add your deployment name here.
  IMAGE: static-site

jobs:
  setup-build-publish-deploy:
    name: Setup, Build, Publish, and Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
    - name: Checkout
      uses: actions/checkout@v5

    # Setup gcloud CLI
    - uses: google-github-actions/setup-gcloud@1bee7de035d65ec5da40a31f8589e240eba8fde5
      with:
        service_account_key: ${{ secrets.GKE_SA_KEY }}
        project_id: ${{ secrets.GKE_PROJECT }}

    # Configure Docker to use the gcloud command-line tool as a credential
    # helper for authentication
    - run: |-
        gcloud --quiet auth configure-docker

    # Get the GKE credentials so we can deploy to the cluster
    - uses: google-github-actions/get-gke-credentials@db150f2cc60d1716e61922b832eae71d2a45938f
      with:
        cluster_name: ${{ env.GKE_CLUSTER }}
        location: ${{ env.GKE_ZONE }}
        credentials: ${{ secrets.GKE_SA_KEY }}

    # Build the Docker image
    - name: Build
      run: |-
        docker build \
          --tag "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA" \
          --build-arg GITHUB_SHA="$GITHUB_SHA" \
          --build-arg GITHUB_REF="$GITHUB_REF" \
          .

    # Push the Docker image to Google Container Registry
    - name: Publish
      run: |-
        docker push "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA"

    # Set up kustomize
    - name: Set up Kustomize
      run: |-
        curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v3.1.0/kustomize_3.1.0_linux_amd64
        chmod u+x ./kustomize

    # Deploy the Docker image to the GKE cluster
    - name: Deploy
      run: |-
        ./kustomize edit set image gcr.io/PROJECT_ID/IMAGE:TAG=gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA
        ./kustomize build . | kubectl apply -f -
        kubectl rollout status deployment/$DEPLOYMENT_NAME
        kubectl get services -o wide

BoxLang and GitHub Actions

According to Google AI ..."

BoxLang projects can leverage GitHub Actions for Continuous Integration and Continuous Deployment (CI/CD) workflows. Ortus Solutions, the creators of BoxLang, provide a dedicated GitHub Action to simplify this process.

Key features and steps for CI/CD with BoxLang and GitHub Actions:

Setup BoxLang GitHub Action: This action streamlines the setup of the BoxLang Dynamic JVM Language runtime within your CI/CD workflows. It handles the installation of Java, BoxLang binaries, and necessary modules. You can specify the desired BoxLang version (latest stable, snapshots, or specific versions) and automatically manage module installations.

Code

    - name: Setup BoxLang
      uses: ortus-boxlang/setup-boxlang@v1 # Use the appropriate version
      with:
        boxlang-version: 'latest' # Or a specific version like '1.0.0'
        commandbox-version: 'latest' # Optional: if you use CommandBox
        install-modules: 'my-module,another-module' # Optional: install specific BoxLang modules

Define Workflow in YAML: Create a YAML file in your repository's .github/workflows directory to define your CI/CD workflow. This file specifies the events that trigger the workflow (e.g., push to main, pull request), the jobs to run, and the steps within each job.

Build and Test: Within your workflow, you can define steps to build your BoxLang project, run unit tests, and perform any other automated tests. The setup-boxlang action ensures the BoxLang environment is ready for these tasks.

Deployment (CD): For continuous deployment, you can add steps to deploy your BoxLang application to a target environment (e.g., a server, cloud platform like AWS Lambda). This might involve building a deployable artifact, uploading it, and triggering deployment scripts or services.

Code

    - name: Build BoxLang Project
      run: boxlang build # Or your specific build command
    - name: Run Tests
      run: boxlang test # Or your specific test command
    - name: Deploy to AWS Lambda
      # Example using a custom script or another action for deployment
      run: ./deploy-to-lambda.sh
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Secrets Management: Store sensitive information like API keys or deployment credentials in GitHub Secrets and securely access them within your workflow using expressions like ${{ secrets.MY_SECRET_NAME }}.

By using the setup-boxlang GitHub Action, the process of integrating BoxLang into your CI/CD pipelines becomes significantly simplified, allowing you to focus on developing your application rather than managing environment setup.