Skip to content

feat(groq): GitHub Action that prints a post‑apocalyptic survival tip, optionally selected by index or run number.#3864

Open
polsala wants to merge 1 commit intomainfrom
ai/groq-20260320-2234
Open

feat(groq): GitHub Action that prints a post‑apocalyptic survival tip, optionally selected by index or run number.#3864
polsala wants to merge 1 commit intomainfrom
ai/groq-20260320-2234

Conversation

@polsala
Copy link
Copy Markdown
Owner

@polsala polsala commented Mar 20, 2026

Implementation Summary

  • Utility: nightly-apocalypse-tip-action
  • Provider: groq
  • Location: github-actions/nightly-nightly-apocalypse-tip-actio
  • Files Created: 4
  • Description: GitHub Action that prints a post‑apocalyptic survival tip, optionally selected by index or run number.

Rationale

  • Automated proposal from the Groq generator delivering a fresh community utility.
  • This utility was generated using the groq AI provider.

Why safe to merge

  • Utility is isolated to github-actions/nightly-nightly-apocalypse-tip-actio.
  • README + tests ship together (see folder contents).
  • No secrets or credentials touched.
  • All changes are additive and self-contained.

Test Plan

  • Follow the instructions in the generated README at github-actions/nightly-nightly-apocalypse-tip-actio/README.md
  • Run tests located in github-actions/nightly-nightly-apocalypse-tip-actio/tests/

Links

  • Generated docs and examples committed alongside this change.

Mock Justification

  • Not applicable; generator did not introduce new mocks.

…, optionally selected by index or run number.
@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Mar 20, 2026

🤖 Review by GROQ Agent

✅ What's solid

  • Self‑contained utility – The action lives in its own directory and does not touch any external services or secrets.
  • Simple deterministic fallback – Using process.env.GITHUB_RUN_NUMBER modulo the tip list gives a repeatable “random” tip when no index is supplied.
  • Graceful error handling – The run() wrapper catches exceptions and fails the step via core.setFailed.
  • Basic test coverage – The three assertions verify explicit index selection, fallback to run number, and out‑of‑range handling.

🧪 Tests

  • Test runner – The file uses raw assert statements and is executed as a plain Node script. Consider adding a test framework (e.g., Jest, Mocha) and a test script in package.json so CI can run npm test automatically.

  • Isolation of env vars – The test mutates process.env.GITHUB_RUN_NUMBER globally. Reset it after the test to avoid side‑effects if more tests are added:

    const originalRun = process.env.GITHUB_RUN_NUMBER;
    process.env.GITHUB_RUN_NUMBER = '7';
    // …run tests…
    process.env.GITHUB_RUN_NUMBER = originalRun;
  • Edge‑case coverage – Add a case for a non‑numeric tip-index (e.g., "abc"). The current code will parse to NaN and fall back to the run‑number logic, which is fine, but an explicit test documents the intended behaviour.

  • Test output – Instead of just console.log('All tests passed'), let the test runner handle reporting. This makes failures visible in CI logs.

🔒 Security

  • Dependency declaration – The script imports @actions/core but the repository does not show a package.json. Add a minimal package.json that pins the version of @actions/core you rely on to avoid supply‑chain surprises:

    {
      "name": "nightly-apocalypse-tip-action",
      "version": "1.0.0",
      "private": true,
      "type": "module",
      "dependencies": {
        "@actions/core": "^1.10.0"
      },
      "scripts": {
        "test": "node ./tests/test_tip_generator.js"
      }
    }
  • Input validation – The action trusts the tip-index input after parseInt. If a malicious user supplies a huge number, the modulo fallback protects you, but you could add an explicit range check and a clear error message:

    if (Number.isNaN(idx) || idx < 0 || idx >= tips.length) {
      core.warning(`Invalid tip-index "${input}" – falling back to run‑number selection`);
      idx = undefined;
    }
  • Error surfacecore.setFailed(error.message) propagates the raw error message. That’s fine for this simple utility, but keep in mind that future changes that might expose internal paths or stack traces should be sanitized.

🧩 Docs / Developer Experience

  • README formatting – The file is a single line of text with embedded \n characters. Convert it to proper Markdown with headings, code blocks, and a usage example:

    # Nightly Apocalypse Tip Action
    
    A tiny GitHub Action that prints a post‑apocalyptic survival tip.
    
    ## Inputs
    | Name      | Description                         | Required | Default |
    |-----------|-------------------------------------|----------|---------|
    | `tip-index` | Integer index of the tip to use.   | No       | (auto)  |
    
    ## Outputs
    | Name | Description |
    |------|-------------|
    | `tip` | The selected tip string. |
    
    ## Example workflow
    
    ```yaml
    jobs:
      nightly:
        runs-on: ubuntu-latest
        steps:
          - uses: ./github-actions/nightly-nightly-apocalypse-tip-actio
            id: tip
          - run: echo "Today's tip: ${{ steps.tip.outputs.tip }}"
    
    
  • Action metadataaction.yml is currently a single line with escaped newlines, which is not valid YAML. Rewrite it as a proper multi‑line file (see the Mocks/Fakes section for a corrected example).

  • Folder naming – The directory is named nightly-nightly-apocalypse-tip-actio (missing the trailing n). Rename it to nightly-apocalypse-tip-action and update any references in the workflow or README to avoid confusion.

  • Exported symbols – The module exports { getTip, tips }. Document these in the README for developers who might want to reuse the logic in other actions.

🧱 Mocks / Fakes

  • No external services – The action does not call any APIs, so mocks are unnecessary at the moment.

  • Future extensibility – If you later add a remote tip source (e.g., fetch from a JSON file in a repo), consider adding a thin wrapper around the fetch logic that can be stubbed in tests. This will keep the current test style (pure functions) while allowing integration tests later.


Quick fix checklist

  1. Rename folder to nightly-apocalypse-tip-action (or another consistent name).

  2. Rewrite action.yml as proper YAML:

    name: "Apocalypse Tip"
    description: "Prints a random post‑apocalyptic survival tip"
    inputs:
      tip-index:
        description: "Optional index of tip to use"
        required: false
        default: ""
    outputs:
      tip:
        description: "The selected tip string"
    runs:
      using: "node16"
      main: "src/tip_generator.js"
  3. Add a minimal package.json with @actions/core as a dependency and a test script.

  4. Improve README with proper Markdown, usage example, and a table of inputs/outputs.

  5. Enhance tests by using a test runner, resetting environment variables, and adding a non‑numeric index case.

  6. (Optional) Validate tip-index more strictly and emit a warning when it’s out of range or not a number.

Implementing these items will make the action easier to consume, safer to run in CI, and more maintainable for future contributors.

@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Mar 20, 2026

🤖 Review by GEMINI Agent

✅ What's solid

  • The core logic for selecting tips in src/tip_generator.js is robust, handling valid indices, undefined inputs, and out-of-range indices by gracefully falling back to the GITHUB_RUN_NUMBER. This makes the action resilient to various input scenarios.
  • The action is self-contained and additive, with no external dependencies beyond @actions/core, contributing to its stability and ease of integration into workflows.
  • The action.yml is well-defined, clearly outlining the action's name, description, inputs, and execution environment.

🧪 Tests

  • The current test suite uses direct assert calls and relies on a global console.log for success indication. For a GitHub Action, consider adopting a more structured testing framework like Jest or Mocha. These frameworks offer enhanced reporting, setup/teardown capabilities, and more expressive assertion methods, which would improve test maintainability and readability.
  • The tests directly modify process.env.GITHUB_RUN_NUMBER. While effective for this simple case, this can lead to test pollution if not properly reset. Using beforeEach/afterEach hooks (available in frameworks like Jest) to manage environment variables would ensure tests are isolated and more robust.
  • The run() function, which orchestrates the action's interaction with @actions/core for inputs, outputs, and logging, is not directly tested. While getTip is well-covered, testing the run() entry point would ensure the action's integration with the GitHub Actions environment works as expected. This could involve mocking @actions/core functions.
    // Example of testing run() with mocks (using a hypothetical Jest-like syntax)
    // const core = require('@actions/core');
    // jest.mock('@actions/core'); // Mock the @actions/core module
    // const { run } = require('../src/tip_generator');
    
    // describe('run', () => {
    //   beforeEach(() => {
    //     jest.clearAllMocks();
    //     process.env.GITHUB_RUN_NUMBER = '7'; // Reset for each test
    //   });
    
    //   test('should set output and log tip when index is provided', () => {
    //     core.getInput.mockReturnValue('2');
    //     run();
    //     expect(core.setOutput).toHaveBeenCalledWith('tip', 'Never trust a stranger offering free canned beans.');
    //     expect(console.log).toHaveBeenCalledWith('Never trust a stranger offering free canned beans.');
    //   });
    // });

🔒 Security

  • The action's reliance on node16 is noted. Ensure that the Node.js version specified in action.yml is actively maintained and free from known vulnerabilities. Consider upgrading to a more recent LTS version (e.g., node20) if compatible with the @actions/core library and other dependencies, to benefit from ongoing security patches.
  • The tip-index input is parsed using parseInt. While the current getTip logic handles non-numeric inputs by treating them as undefined, it's good practice to explicitly validate inputs to prevent unexpected behavior. Adding a check to ensure the input is a non-negative integer string before parsing could add an extra layer of robustness.
    // In src/tip_generator.js, within run()
    const input = core.getInput('tip-index');
    let idx;
    if (input && /^\d+$/.test(input)) { // Validate it's a non-negative integer string
      idx = parseInt(input, 10);
    } else if (input) {
      core.warning(`Invalid 'tip-index' input: '${input}'. Falling back to run number.`);
    }
    const tip = getTip(idx);

🧩 Docs/DX

  • The README.md provides a good overview. However, the Usage section would significantly benefit from a concrete example of how to integrate the action into a GitHub Workflow YAML file. This would provide a copy-paste ready snippet, improving the developer experience.
    # Example for README.md Usage section
    name: 'Daily Apocalypse Tip'
    on:
      workflow_dispatch:
      schedule:
        - cron: '0 0 * * *' # Run daily at midnight UTC
    
    jobs:
      print_tip:
        runs-on: ubuntu-latest
        steps:
          - name: Get Apocalypse Tip
            id: tip_step
            uses: github-actions/nightly-nightly-apocalypse-tip-actio@main # Or a specific tag/commit
            with:
              tip-index: 2 # Optional: specify an index, or omit for run number based selection
    
          - name: Print Tip to Log
            run: echo "Today's Survival Tip: ${{ steps.tip_step.outputs.tip }}"
  • The action.yml specifies default: "" for tip-index. While parseInt('') results in NaN which getTip correctly interprets as undefined, explicitly removing the default (to rely on undefined when not provided) or setting a more semantically meaningful default (e.g., default: -1 if an invalid index should be treated distinctly) might make the input's behavior clearer.
  • The path github-actions/nightly-nightly-apocalypse-tip-actio contains a double "nightly-". Review the naming convention to ensure consistency and avoid redundancy in the directory structure.

🧱 Mocks/Fakes

  • The PR body states "Not applicable; generator did not introduce new mocks." However, the test file test_tip_generator.js explicitly mocks process.env.GITHUB_RUN_NUMBER. This discrepancy should be addressed in the PR description for clarity.
  • While the current mocking of process.env.GITHUB_RUN_NUMBER is functional for testing getTip, consider centralizing environment variable manipulation within test setup/teardown blocks (e.g., beforeAll, afterAll, beforeEach, afterEach in a testing framework) to ensure a clean state for each test and prevent side effects. This improves test isolation and reliability.
    // Example using a test framework structure for env mocking
    // describe('getTip', () => {
    //   let originalRunNumber;
    
    //   beforeAll(() => {
    //     originalRunNumber = process.env.GITHUB_RUN_NUMBER;
    //   });
    
    //   beforeEach(() => {
    //     process.env.GITHUB_RUN_NUMBER = '7'; // Set for each test
    //   });
    
    //   afterAll(() => {
    //     process.env.GITHUB_RUN_NUMBER = originalRunNumber; // Restore original
    //   });
    
    //   // ... your tests ...
    // });

@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Mar 22, 2026

🤖 Review by OPENROUTER Agent

✅ What's solid

  • The action is well-scoped and self-contained within its own directory, minimizing risk to the broader repository.
  • Good use of GITHUB_RUN_NUMBER as a deterministic fallback mechanism for tip selection, ensuring repeatability in CI environments.
  • Clear separation between core logic (getTip) and execution (run), which improves testability and reusability.
  • Proper error handling via try/catch block around the main function, preventing uncaught exceptions from breaking workflows.

🧪 Tests

  • Basic functionality is covered: explicit index selection, fallback behavior with undefined, and out-of-range index handling.
  • Environment mocking for GITHUB_RUN_NUMBER ensures consistent test outcomes.

Actionable Feedback:

  • Add edge case coverage such as negative indices, non-numeric inputs, or missing environment variables. Example:
// Test negative index
tip = getTip(-1);
assert.strictEqual(tip, tips[7 % tips.length], 'Negative index should fall back to run number');
  • Consider using a testing framework like Mocha or Jest for better structure, assertions, and reporting.

🔒 Security

  • No credentials or secrets are involved, keeping the attack surface minimal.
  • Input validation exists but could be strengthened to prevent unexpected behaviors from malformed inputs.

Actionable Feedback:

  • Validate that parsed integers are safe (i.e., not NaN or excessively large). For example:
const idx = input ? parseInt(input, 10) : undefined;
if (isNaN(idx)) {
  // handle invalid input gracefully
}

🧩 Docs/DX

  • README provides basic usage instructions and explains both inputs and outputs clearly.
  • The action’s purpose is fun yet practical for workflow enrichment.

Actionable Feedback:

  • Expand the README with an example YAML snippet showing how to integrate the action into a workflow:
- name: Print Apocalypse Tip
  uses: ./.github/actions/nightly-apocalypse-tip-action
  with:
    tip-index: 3
  • Clarify what happens when tip-index is provided but not a valid integer (e.g., empty string, float).

🧱 Mocks/Fakes

  • No custom mocks were introduced, and existing tests mock GITHUB_RUN_NUMBER directly, which suffices for current scope.

Actionable Feedback:

  • If future features involve GitHub Actions APIs (e.g., setting output messages or interacting with the runner context), consider abstracting core functions behind injectable interfaces to allow easier unit testing without relying on global state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant