Repository: cisagov/setup-env-github-action
Pull request #81: ⚠️ CONFLICT! Lineage pull request for: skeleton
Author: login: cisagovbot
Labels: name: upstream update
description: This issue or pull request pulls in upstream updates
name: dependencies
description: Pull requests that update a dependency file
name: github-actions
description: Pull requests that update GitHub Actions code
name: security
description: This issue or pull request addresses a security issue
Created: 2025-03-28T02:51:43Z | Merged: 2025-04-03T14:01:54Z

# Lineage Pull Request: CONFLICT #

<img align="left" alt="Achtung!!!" width="100" src="https://raw.githubusercontent.com/cisagov/action-lineage/develop/src/achtung.gif">

[Lineage] has created this pull request to incorporate new changes found in an
upstream repository:

Upstream repository: [`https://github.com/cisagov/skeleton-generic.git`](https://github.com/cisagov/skeleton-generic.git)
Remote branch: `HEAD`

Check the changes in this pull request to ensure they won't cause issues with
your project.

The `lineage/skeleton` branch has **one or more unresolved merge conflicts**
that you must resolve before merging this pull request!

## How to resolve the conflicts ##

1. Take ownership of this pull request by removing any other assignees.

1. Clone the repository locally, and reapply the merge:

    ```console
    git clone git@github.com:cisagov/setup-env-github-action.git setup-env-github-action
    cd setup-env-github-action
    git remote add skeleton https://github.com/cisagov/skeleton-generic.git
    git remote set-url --push skeleton no_push
    git switch develop
    git switch --create lineage/skeleton --track origin/develop
    git pull skeleton HEAD
    git status
    ```

1. Review the changes displayed by the `status` command.  Fix any conflicts and
   possibly incorrect auto-merges.

1. After resolving each of the conflicts, `add` your changes to the
   branch, `commit`, and `push` your changes:

    ```console
    git add .github/dependabot.yml 
    git commit
    git push --force --set-upstream origin lineage/skeleton
    ```

    Note that you may *append* to the default merge commit message
    that git creates for you, but *please do not delete the existing
    content*.  It provides useful information about the merge that is
    being performed.

1. Wait for all the automated tests to pass.

1. Confirm each item in the "Pre-approval checklist" below.

1. Remove any of the checklist items that do not apply.

1. Ensure every remaining checkbox has been checked.

1. Mark this draft pull request "Ready for review".

## ✅ Pre-approval checklist ##

- [x] ✌️ The conflicts in this pull request have been resolved.
- [x] All relevant type-of-change labels have been added.
- [x] All new and existing tests pass.

---

> [!NOTE]
> You are seeing this because one of this repository's maintainers has
> configured [Lineage] to open pull requests.

For more information:

🛠 [Lineage] configurations for this project are stored in `.github/lineage.yml`

📚 [Read more about Lineage][Lineage]

[//]: # (lineage:metadata:{&quot;slayed&quot;:true})
[Lineage]: https://github.com/cisagov/action-lineage/ "Lineage GitHub Action"


Diff:
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index ee65037..726c23b 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -11,17 +11,16 @@ updates:
       # Managed by cisagov/skeleton-generic
       - dependency-name: actions/cache
       - dependency-name: actions/checkout
+      - dependency-name: actions/dependency-review-action
       - dependency-name: actions/setup-go
       - dependency-name: actions/setup-python
+      - dependency-name: cisagov/action-job-preamble
       - dependency-name: cisagov/setup-env-github-action
-      - dependency-name: crazy-max/ghaction-dump-context
       - dependency-name: crazy-max/ghaction-github-labeler
-      - dependency-name: crazy-max/ghaction-github-status
-      - dependency-name: GitHubSecurityLab/actions-permissions
+      - dependency-name: github/codeql-action
       - dependency-name: hashicorp/setup-packer
       - dependency-name: hashicorp/setup-terraform
       - dependency-name: mxschmitt/action-tmate
-      - dependency-name: step-security/harden-runner
     package-ecosystem: github-actions
     schedule:
       interval: weekly
diff --git a/.github/labels.yml b/.github/labels.yml
index 5b16492..fe9a53e 100644
--- a/.github/labels.yml
+++ b/.github/labels.yml
@@ -2,69 +2,69 @@
 # Rather than breaking up descriptions into multiline strings we disable that
 # specific rule in yamllint for this file.
 # yamllint disable rule:line-length
-- color: "eb6420"
+- color: eb6420
   description: This issue or pull request is awaiting the outcome of another issue or pull request
   name: blocked
 - color: "000000"
   description: This issue or pull request involves changes to existing functionality
   name: breaking change
-- color: "d73a4a"
+- color: d73a4a
   description: This issue or pull request addresses broken functionality
   name: bug
-- color: "07648d"
+- color: 07648d
   description: This issue will be advertised on code.gov's Open Tasks page (https://code.gov/open-tasks)
   name: code.gov
-- color: "0366d6"
+- color: 0366d6
   description: Pull requests that update a dependency file
   name: dependencies
-- color: "5319e7"
+- color: 5319e7
   description: This issue or pull request improves or adds to documentation
   name: documentation
-- color: "cfd3d7"
+- color: cfd3d7
   description: This issue or pull request already exists or is covered in another issue or pull request
   name: duplicate
-- color: "b005bc"
+- color: b005bc
   description: A high-level objective issue encompassing multiple issues instead of a specific unit of work
   name: epic
 - color: "000000"
   description: Pull requests that update GitHub Actions code
   name: github-actions
-- color: "0e8a16"
+- color: 0e8a16
   description: This issue or pull request is well-defined and good for newcomers
   name: good first issue
-- color: "ff7518"
+- color: ff7518
   description: Pull request that should count toward Hacktoberfest participation
   name: hacktoberfest-accepted
-- color: "a2eeef"
+- color: a2eeef
   description: This issue or pull request will add or improve functionality, maintainability, or ease of use
   name: improvement
-- color: "fef2c0"
+- color: fef2c0
   description: This issue or pull request is not applicable, incorrect, or obsolete
   name: invalid
-- color: "ce099a"
+- color: ce099a
   description: This pull request is ready to merge during the next Lineage Kraken release
   name: kraken 🐙
-- color: "a4fc5d"
+- color: a4fc5d
   description: This issue or pull request requires further information
   name: need info
-- color: "fcdb45"
+- color: fcdb45
   description: This pull request is awaiting an action or decision to move forward
   name: on hold
-- color: "ef476c"
+- color: ef476c
   description: This issue is a request for information or needs discussion
   name: question
-- color: "d73a4a"
+- color: d73a4a
   description: This issue or pull request addresses a security issue
   name: security
-- color: "00008b"
+- color: 00008b
   description: This issue or pull request adds or otherwise modifies test code
   name: test
-- color: "1d76db"
+- color: 1d76db
   description: This issue or pull request pulls in upstream updates
   name: upstream update
-- color: "d4c5f9"
+- color: d4c5f9
   description: This issue or pull request increments the version number
   name: version bump
-- color: "ffffff"
+- color: ffffff
   description: This issue will not be incorporated
   name: wontfix
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 15a004c..eeebb23 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,7 +1,7 @@
 ---
 name: build
 
-on:
+on:  # yamllint disable-line rule:truthy
   merge_group:
     types:
       - checks_requested
@@ -36,23 +36,30 @@ jobs:
     steps:
       # Note that a duplicate of this step must be added at the top of
       # each job.
-      - uses: GitHubSecurityLab/actions-permissions/monitor@v1
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
         with:
-          # Uses the organization variable unless overridden
-          config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
-      # Note that a duplicate of this step must be added at the top of
-      # each job.
-      - id: harden-runner
-        name: Harden the runner
-        uses: step-security/harden-runner@v2
-        with:
-          egress-policy: audit
-      - id: github-status
-        name: Check GitHub status
-        uses: crazy-max/ghaction-github-status@v4
-      - id: dump-context
-        name: Dump context
-        uses: crazy-max/ghaction-dump-context@v2
+          check_github_status: "true"
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          output_workflow_context: "true"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
   lint:
     needs:
       - diagnostics
@@ -61,15 +68,28 @@ jobs:
       contents: read
     runs-on: ubuntu-latest
     steps:
-      - uses: GitHubSecurityLab/actions-permissions/monitor@v1
-        with:
-          # Uses the organization variable unless overridden
-          config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
-      - id: harden-runner
-        name: Harden the runner
-        uses: step-security/harden-runner@v2
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
         with:
-          egress-policy: audit
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
       - id: setup-env
         uses: cisagov/setup-env-github-action@develop
       - uses: actions/checkout@v4
@@ -92,16 +112,16 @@ jobs:
           echo "dir=$(go env GOCACHE)" >> $GITHUB_OUTPUT
       - uses: actions/cache@v4
         env:
-          BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\
+          BASE_CACHE_KEY: ${{ github.job }}-${{ runner.os }}-\
             py${{ steps.setup-python.outputs.python-version }}-\
             go${{ steps.setup-go.outputs.go-version }}-\
             packer${{ steps.setup-env.outputs.packer-version }}-\
-            tf${{ steps.setup-env.outputs.terraform-version }}-"
+            tf${{ steps.setup-env.outputs.terraform-version }}-
         with:
-          key: "${{ env.BASE_CACHE_KEY }}\
+          key: ${{ env.BASE_CACHE_KEY }}\
             ${{ hashFiles('**/requirements-test.txt') }}-\
             ${{ hashFiles('**/requirements.txt') }}-\
-            ${{ hashFiles('**/.pre-commit-config.yaml') }}"
+            ${{ hashFiles('**/.pre-commit-config.yaml') }}
           # Note that the .terraform directory IS NOT included in the
           # cache because if we were caching, then we would need to use
           # the `-upgrade=true` option. This option blindly pulls down the
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..d1590e9
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,134 @@
+---
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+name: CodeQL
+
+# The use of on here as a key is part of the GitHub actions syntax.
+# yamllint disable-line rule:truthy
+on:
+  merge_group:
+    types:
+      - checks_requested
+  pull_request:
+    # The branches here must be a subset of the ones in the push key
+    branches:
+      - develop
+  push:
+    # Dependabot-triggered push events have read-only access, but uploading code
+    # scanning requires write access.
+    branches-ignore:
+      - dependabot/**
+  schedule:
+    - cron: 0 2 * * 6
+
+jobs:
+  diagnostics:
+    name: Run diagnostics
+    # This job does not need any permissions
+    permissions: {}
+    runs-on: ubuntu-latest
+    steps:
+      # Note that a duplicate of this step must be added at the top of
+      # each job.
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
+        with:
+          check_github_status: "true"
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          output_workflow_context: "true"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
+  analyze:
+    name: Analyze
+    needs:
+      - diagnostics
+    runs-on: ubuntu-latest
+    permissions:
+      # actions/checkout needs this to fetch code
+      contents: read
+      # required for all workflows
+      security-events: write
+    strategy:
+      fail-fast: false
+      matrix:
+        # Override automatic language detection by changing the below
+        # list
+        #
+        # Supported options are actions, c-cpp, csharp, go,
+        # java-kotlin, javascript-typescript, python, ruby, and swift.
+        language:
+          - actions
+        # Learn more...
+        # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
+
+    steps:
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
+        with:
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
+
+      - name: Checkout repository
+        uses: actions/checkout@v4
+
+      # Initializes the CodeQL tools for scanning.
+      - name: Initialize CodeQL
+        uses: github/codeql-action/init@v3
+        with:
+          languages: ${{ matrix.language }}
+
+      # Autobuild attempts to build any compiled languages (C/C++, C#, or
+      # Java). If this step fails, then you should remove it and run the build
+      # manually (see below).
+      - name: Autobuild
+        uses: github/codeql-action/autobuild@v3
+
+      # ℹ️ Command-line programs to run using the OS shell.
+      # 📚 https://git.io/JvXDl
+
+      # ✏️ If the Autobuild fails above, remove it and uncomment the following
+      #    three lines and modify them (or add more) to build your code if your
+      #    project uses a compiled language
+
+      # - run: |
+      #     make bootstrap
+      #     make release
+
+      - name: Perform CodeQL Analysis
+        uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
new file mode 100644
index 0000000..9901352
--- /dev/null
+++ b/.github/workflows/dependency-review.yml
@@ -0,0 +1,87 @@
+---
+name: Dependency review
+
+on:  # yamllint disable-line rule:truthy
+  merge_group:
+    types:
+      - checks_requested
+  pull_request:
+
+# Set a default shell for any run steps. The `-Eueo pipefail` sets errtrace,
+# nounset, errexit, and pipefail. The `-x` will print all commands as they are
+# run. Please see the GitHub Actions documentation for more information:
+# https://docs.github.com/en/actions/using-jobs/setting-default-values-for-jobs
+defaults:
+  run:
+    shell: bash -Eueo pipefail -x {0}
+
+jobs:
+  diagnostics:
+    name: Run diagnostics
+    # This job does not need any permissions
+    permissions: {}
+    runs-on: ubuntu-latest
+    steps:
+      # Note that a duplicate of this step must be added at the top of
+      # each job.
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
+        with:
+          check_github_status: "true"
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          output_workflow_context: "true"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
+  dependency-review:
+    name: Dependency review
+    needs:
+      - diagnostics
+    permissions:
+      # actions/checkout needs this to fetch code
+      contents: read
+    runs-on: ubuntu-latest
+    steps:
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
+        with:
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
+      - id: checkout-repo
+        name: Checkout the repository
+        uses: actions/checkout@v4
+      - id: dependency-review
+        name: Review dependency changes for vulnerabilities and license changes
+        uses: actions/dependency-review-action@v4
diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml
index 0005147..07c0acf 100644
--- a/.github/workflows/sync-labels.yml
+++ b/.github/workflows/sync-labels.yml
@@ -1,7 +1,7 @@
 ---
 name: sync-labels
 
-on:
+on:  # yamllint disable-line rule:truthy
   push:
     paths:
       - .github/labels.yml
@@ -20,23 +20,30 @@ jobs:
     steps:
       # Note that a duplicate of this step must be added at the top of
       # each job.
-      - uses: GitHubSecurityLab/actions-permissions/monitor@v1
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
         with:
-          # Uses the organization variable unless overridden
-          config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
-      # Note that a duplicate of this step must be added at the top of
-      # each job.
-      - id: harden-runner
-        name: Harden the runner
-        uses: step-security/harden-runner@v2
-        with:
-          egress-policy: audit
-      - id: github-status
-        name: Check GitHub status
-        uses: crazy-max/ghaction-github-status@v4
-      - id: dump-context
-        name: Dump context
-        uses: crazy-max/ghaction-dump-context@v2
+          check_github_status: "true"
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          output_workflow_context: "true"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
   labeler:
     needs:
       - diagnostics
@@ -47,15 +54,28 @@ jobs:
       issues: write
     runs-on: ubuntu-latest
     steps:
-      - uses: GitHubSecurityLab/actions-permissions/monitor@v1
-        with:
-          # Uses the organization variable unless overridden
-          config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
-      - id: harden-runner
-        name: Harden the runner
-        uses: step-security/harden-runner@v2
+      - name: Apply standard cisagov job preamble
+        uses: cisagov/action-job-preamble@v1
         with:
-          egress-policy: audit
+          # This functionality is poorly implemented and has been
+          # causing problems due to the MITM implementation hogging or
+          # leaking memory.  If this happens to you just uncomment
+          # this line.
+          # monitor_permissions: "false"
+          # Use a variable to specify the permissions monitoring
+          # configuration. By default this will yield the
+          # configuration stored in the cisagov organization-level
+          # variable, but if you want to use a different configuration
+          # then simply:
+          # 1. Create a repository-level variable with the name
+          # ACTIONS_PERMISSIONS_CONFIG.
+          # 2. Set this new variable's value to the configuration you
+          # want to use for this repository.
+          #
+          # Note in particular that changing the permissions
+          # monitoring configuration *does not* require you to modify
+          # this workflow.
+          permissions_monitoring_config: ${{ vars.ACTIONS_PERMISSIONS_CONFIG }}
       - uses: actions/checkout@v4
       - name: Sync repository labels
         if: success()
diff --git a/.mdl_config.yaml b/.mdl_config.yaml
index 4a650c1..1b48994 100644
--- a/.mdl_config.yaml
+++ b/.mdl_config.yaml
@@ -6,12 +6,12 @@ default: true
 # MD003/heading-style/header-style - Heading style
 MD003:
   # Enforce the ATX-closed style of header
-  style: "atx_closed"
+  style: atx_closed
 
 # MD004/ul-style - Unordered list style
 MD004:
   # Enforce dashes for unordered lists
-  style: "dash"
+  style: dash
 
 # MD013/line-length - Line length
 MD013:
@@ -30,7 +30,7 @@ MD024:
 # MD029/ol-prefix - Ordered list item prefix
 MD029:
   # Enforce the `1.` style for ordered lists
-  style: "one"
+  style: one
 
 # MD033/no-inline-html - Inline HTML
 MD033:
@@ -42,19 +42,19 @@ MD033:
 # MD035/hr-style - Horizontal rule style
 MD035:
   # Enforce dashes for horizontal rules
-  style: "---"
+  style: ---
 
 # MD046/code-block-style - Code block style
 MD046:
   # Enforce the fenced style for code blocks
-  style: "fenced"
+  style: fenced
 
 # MD049/emphasis-style - Emphasis style should be consistent
 MD049:
   # Enforce asterisks as the style to use for emphasis
-  style: "asterisk"
+  style: asterisk
 
 # MD050/strong-style - Strong style should be consistent
 MD050:
   # Enforce asterisks as the style to use for strong
-  style: "asterisk"
+  style: asterisk
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 26113a8..0d8b248 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -42,17 +42,17 @@ repos:
 
   # Text file hooks
   - repo: https://github.com/igorshubovych/markdownlint-cli
-    rev: v0.42.0
+    rev: v0.44.0
     hooks:
       - id: markdownlint
         args:
           - --config=.mdl_config.yaml
   - repo: https://github.com/rbubley/mirrors-prettier
-    rev: v3.3.3
+    rev: v3.5.3
     hooks:
       - id: prettier
   - repo: https://github.com/adrienverge/yamllint
-    rev: v1.35.1
+    rev: v1.37.0
     hooks:
       - id: yamllint
         args:
@@ -60,14 +60,14 @@ repos:
 
   # GitHub Actions hooks
   - repo: https://github.com/python-jsonschema/check-jsonschema
-    rev: 0.29.4
+    rev: 0.32.1
     hooks:
       - id: check-github-actions
       - id: check-github-workflows
 
   # pre-commit hooks
   - repo: https://github.com/pre-commit/pre-commit
-    rev: v4.0.1
+    rev: v4.2.0
     hooks:
       - id: validate_manifest
 
@@ -102,7 +102,7 @@ repos:
 
   # Shell script hooks
   - repo: https://github.com/scop/pre-commit-shfmt
-    rev: v3.10.0-1
+    rev: v3.11.0-1
     hooks:
       - id: shfmt
         args:
@@ -126,31 +126,31 @@ repos:
 
   # Python hooks
   - repo: https://github.com/PyCQA/bandit
-    rev: 1.7.10
+    rev: 1.8.3
     hooks:
       - id: bandit
         args:
           - --config=.bandit.yml
   - repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 24.10.0
+    rev: 25.1.0
     hooks:
       - id: black
   - repo: https://github.com/PyCQA/flake8
-    rev: 7.1.1
+    rev: 7.1.2
     hooks:
       - id: flake8
         additional_dependencies:
           - flake8-docstrings==1.7.0
   - repo: https://github.com/PyCQA/isort
-    rev: 5.13.2
+    rev: 6.0.1
     hooks:
       - id: isort
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v1.13.0
+    rev: v1.15.0
     hooks:
       - id: mypy
   - repo: https://github.com/pypa/pip-audit
-    rev: v2.7.3
+    rev: v2.8.0
     hooks:
       - id: pip-audit
         args:
@@ -162,13 +162,13 @@ repos:
           - --requirement
           - requirements.txt
   - repo: https://github.com/asottile/pyupgrade
-    rev: v3.19.0
+    rev: v3.19.1
     hooks:
       - id: pyupgrade
 
   # Ansible hooks
   - repo: https://github.com/ansible/ansible-lint
-    rev: v24.10.0
+    rev: v25.1.3
     hooks:
       - id: ansible-lint
         additional_dependencies:
@@ -212,7 +212,7 @@ repos:
 
   # Terraform hooks
   - repo: https://github.com/antonbabenko/pre-commit-terraform
-    rev: v1.96.1
+    rev: v1.98.0
     hooks:
       - id: terraform_fmt
       - id: terraform_validate
diff --git a/.yamllint b/.yamllint
index 2a119a6..00e85a6 100644
--- a/.yamllint
+++ b/.yamllint
@@ -2,12 +2,33 @@
 extends: default
 
 rules:
+  braces:
+    # Do not allow non-empty flow mappings
+    forbid: non-empty
+    # Allow up to one space inside braces. This is required for Ansible compatibility.
+    max-spaces-inside: 1
+
+  brackets:
+    # Do not allow non-empty flow sequences
+    forbid: non-empty
+
+  comments:
+    # Ensure that inline comments have at least one space before the preceding content.
+    # This is required for Ansible compatibility.
+    min-spaces-from-content: 1
+
   # yamllint does not like it when you comment out different parts of
   # dictionaries in a list. You can see
   # https://github.com/adrienverge/yamllint/issues/384 for some examples of
   # this behavior.
   comments-indentation: disable
 
+  indentation:
+    # Ensure that block sequences inside of a mapping are indented
+    indent-sequences: true
+    # Enforce a specific number of spaces
+    spaces: 2
+
   # yamllint does not allow inline mappings that exceed the line length by
   # default. There are many scenarios where the inline mapping may be a key,
   # hash, or other long value that would exceed the line length but cannot
@@ -18,6 +39,24 @@ rules:
     # Allows a 10% overage from the default limit of 80
     max: 88
 
-  # yamllint doesn't like when we use yes and no for true and false,
-  # but that's pretty standard in Ansible.
-  truthy: disable
+  # Using anything other than strings to express octal values can lead to unexpected
+  # and potentially unsafe behavior. Ansible strongly recommends against such practices
+  # and these rules are needed for Ansible compatibility. Please see the following for
+  # more information:
+  # https://ansible.readthedocs.io/projects/lint/rules/risky-octal/
+  octal-values:
+    # Do not allow explicit octal values (those beginning with a leading 0o).
+    forbid-explicit-octal: true
+    # Do not allow implicit octal values (those beginning with a leading 0).
+    forbid-implicit-octal: true
+
+  quoted-strings:
+    # Allow disallowed quotes (single quotes) for strings that contain allowed quotes
+    # (double quotes).
+    allow-quoted-quotes: true
+    # Apply these rules to keys in mappings as well
+    check-keys: true
+    # We prefer double quotes for strings when they are needed
+    quote-type: double
+    # Only require quotes when they are necessary for proper processing
+    required: only-when-needed
diff --git a/bump-version b/bump-version
new file mode 100755
index 0000000..2ef7569
--- /dev/null
+++ b/bump-version
@@ -0,0 +1,172 @@
+#!/usr/bin/env bash
+
+# bump-version [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
+# bump-version --list-files
+
+set -o nounset
+set -o errexit
+set -o pipefail
+
+# Stores the canonical version for the project.
+VERSION_FILE=package.json
+# Files that should be updated with the new version.
+VERSION_FILES=("$VERSION_FILE")
+
+USAGE=$(
+  cat << END_OF_LINE
+Update the version of the project.
+
+Usage:
+  ${0##*/} [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
+  ${0##*/} --list-files
+  ${0##*/} (-h | --help)
+
+Options:
+  -h | --help    Show this message.
+  --push         Perform a \`git push\` after updating the version.
+  --label LABEL  Specify the label to use when updating the build or prerelease version.
+  --list-files   List the files that will be updated when the version is bumped.
+END_OF_LINE
+)
+
+old_version=$(sed -n "s/^[[:blank:]]*\"version\": \"\(.*\)\",\{0,1\}$/\1/p" $VERSION_FILE)
+# Comment out periods so they are interpreted as periods and don't
+# just match any character
+old_version_regex="^\([[:blank:]]*\"version\": \)\"${old_version//\./\\\.}\""
+new_version="$old_version"
+
+bump_part=""
+label=""
+commit_prefix="Bump"
+with_push=false
+commands_with_label=("build" "prerelease")
+commands_with_prerelease=("major" "minor" "patch")
+with_prerelease=false
+
+#######################################
+# Display an error message, the help information, and exit with a non-zero status.
+# Arguments:
+#   Error message.
+#######################################
+function invalid_option() {
+  echo "$1"
+  echo "$USAGE"
+  exit 1
+}
+
+#######################################
+# Bump the version using the provided command.
+# Arguments:
+#   The version to bump.
+#   The command to bump the version.
+# Returns:
+#   The new version.
+#######################################
+function bump_version() {
+  local temp_version
+  temp_version=$(python -c "import semver; print(semver.parse_version_info('$1').${2})")
+  echo "$temp_version"
+}
+
+if [ $# -eq 0 ]; then
+  echo "$USAGE"
+  exit 1
+else
+  while [ $# -gt 0 ]; do
+    case $1 in
+      --push)
+        if [ "$with_push" = true ]; then
+          invalid_option "Push has already been set."
+        fi
+
+        with_push=true
+        shift
+        ;;
+      --label)
+        if [ -n "$label" ]; then
+          invalid_option "Label has already been set."
+        fi
+
+        label="$2"
+        shift 2
+        ;;
+      build | finalize | major | minor | patch)
+        if [ -n "$bump_part" ]; then
+          invalid_option "Only one version part should be bumped at a time."
+        fi
+
+        bump_part="$1"
+        shift
+        ;;
+      prerelease)
+        with_prerelease=true
+        shift
+        ;;
+      show)
+        echo "$old_version"
+        exit 0
+        ;;
+      -h | --help)
+        echo "$USAGE"
+        exit 0
+        ;;
+      --list-files)
+        printf '%s\n' "${VERSION_FILES[@]}"
+        exit 0
+        ;;
+      *)
+        invalid_option "Invalid option: $1"
+        ;;
+    esac
+  done
+fi
+
+if [ -n "$label" ] && [ "$with_prerelease" = false ] && [[ ! " ${commands_with_label[*]} " =~ [[:space:]]${bump_part}[[:space:]] ]]; then
+  invalid_option "Setting the label is only allowed for the following commands: ${commands_with_label[*]}"
+fi
+
+if [ "$with_prerelease" = true ] && [ -n "$bump_part" ] && [[ ! " ${commands_with_prerelease[*]} " =~ [[:space:]]${bump_part}[[:space:]] ]]; then
+  invalid_option "Changing the prerelease is only allowed in conjunction with the following commands: ${commands_with_prerelease[*]}"
+fi
+
+label_option=""
+if [ -n "$label" ]; then
+  label_option="token='$label'"
+fi
+
+if [ -n "$bump_part" ]; then
+  if [ "$bump_part" = "finalize" ]; then
+    commit_prefix="Finalize"
+    bump_command="finalize_version()"
+  elif [ "$bump_part" = "build" ]; then
+    bump_command="bump_${bump_part}($label_option)"
+  else
+    bump_command="bump_${bump_part}()"
+  fi
+  new_version=$(bump_version "$old_version" "$bump_command")
+  echo Changing version from "$old_version" to "$new_version"
+fi
+
+if [ "$with_prerelease" = true ]; then
+  bump_command="bump_prerelease($label_option)"
+  temp_version=$(bump_version "$new_version" "$bump_command")
+  echo Changing version from "$new_version" to "$temp_version"
+  new_version="$temp_version"
+fi
+
+tmp_file=/tmp/version.$$
+for version_file in "${VERSION_FILES[@]}"; do
+  if [ ! -f "$version_file" ]; then
+    echo Missing expected file: "$version_file"
+    exit 1
+  fi
+  sed "s/$old_version_regex/\1\"$new_version\"/" "$version_file" > $tmp_file
+  mv $tmp_file "$version_file"
+done
+
+git add "${VERSION_FILES[@]}"
+git commit --message "$commit_prefix version from $old_version to $new_version"
+
+if [ "$with_push" = true ]; then
+  git push
+fi
diff --git a/requirements-dev.txt b/requirements-dev.txt
index d84ee68..23d5741 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,2 +1,4 @@
 --requirement requirements-test.txt
 ipython
+# The bump-version script requires at least version 3 of semver.
+semver>=3
diff --git a/setup-env b/setup-env
index 059ccad..f3304d9 100755
--- a/setup-env
+++ b/setup-env
@@ -74,7 +74,8 @@ check_python_version() {
       "invalid version of Python."
     exit 1
   # Else if the Python version isn't installed then notify the user.
-  # grep -E is used for searching through text lines that match the specific verison.
+  # grep -E is used for searching through text lines that match the
+  # specific version.
   elif ! python_versions | grep -E "^${version}$" > /dev/null; then
     echo "Error: Python version $version is not installed."
     echo "Installed Python versions are:"


Reviews:
user: login: dav3r
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-01T16:40:11Z
user: login: dv4harr10
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T16:40:40Z
user: login: mcdonnnj
body: LGTM ✔️ I do have one small change I would like to see if it's not too much of a lift.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-01T20:41:17Z
user: login: jsf9k
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-02T02:49:40Z
user: login: mcdonnnj
body: I'm having some issues with `bump-version`. I do not see the version when I run `./bump-version show` and the `sed` command in use does not appear to work with the version of `sed` that ships with macOS:

```console
$ ./bump-version show

$ sed -n "s/^[[:space:]]*\"version\": \"\(.*\)\",\?$/\1/p" package.json
1.0.0
$ /usr/bin/sed -n "s/^[[:space:]]*\"version\": \"\(.*\)\",\?$/\1/p" package.json
```

After adding `set -x` to `bump-version` I see the following:

```console
$ ./bump-version show
+ VERSION_FILE=package.json
+ VERSION_FILES=("$VERSION_FILE")
++ cat
+ USAGE='Update the version of the project.

Usage:
  bump-version [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
  bump-version --list-files
  bump-version (-h | --help)

Options:
  -h | --help    Show this message.
  --push         Perform a `git push` after updating the version.
  --label LABEL  Specify the label to use when updating the build or prerelease version.
  --list-files   List the files that will be updated when the version is bumped.'
++ sed -n 's/^[[:space:]]*"version": "\(.*\)",\?$/\1/p' package.json
+ old_version=
+ old_version_regex='^\([[:space:]]*"version": \)""'
+ new_version=
+ bump_part=
+ label=
+ commit_prefix=Bump
+ with_push=false
+ commands_with_label=("build" "prerelease")
+ commands_with_prerelease=("major" "minor" "patch")
+ with_prerelease=false
+ '[' 1 -eq 0 ']'
+ '[' 1 -gt 0 ']'
+ case $1 in
+ echo ''

+ exit 0
```
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-02T23:16:48Z
user: login: mcdonnnj
body: I tested the updates to `bump-version` on my Mac and can confirm the script works as expected.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-03T13:57:40Z

Review comments:
diff_hunk: @@ -0,0 +1,172 @@
+#!/usr/bin/env bash
+
+# bump-version [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
+# bump-version --list-files
+
+set -o nounset
+set -o errexit
+set -o pipefail
+
+# Stores the canonical version for the project.
+VERSION_FILE=package.json
+# Files that should be updated with the new version.
+VERSION_FILES=("$VERSION_FILE")
+
+USAGE=$(
+  cat << END_OF_LINE
+Update the version of the project.
+
+Usage:
+  ${0##*/} [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
+  ${0##*/} --list-files
+  ${0##*/} (-h | --help)
+
+Options:
+  -h | --help    Show this message.
+  --push         Perform a \`git push\` after updating the version.
+  --label LABEL  Specify the label to use when updating the build or prerelease version.
+  --list-files   List the files that will be updated when the version is bumped.
+END_OF_LINE
+)
+
+old_version=$(sed -n "s/^[[:space:]]*\"version\": \"\(.*\)\"$/\1/p" $VERSION_FILE)
path: bump-version
user: login: mcdonnnj
body: I would like it if this considered the possibility of a comma following the value for the `version` key if it's not a big lift.
created_at: 2025-04-01T20:37:25Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,172 @@
+#!/usr/bin/env bash
+
+# bump-version [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
+# bump-version --list-files
+
+set -o nounset
+set -o errexit
+set -o pipefail
+
+# Stores the canonical version for the project.
+VERSION_FILE=package.json
+# Files that should be updated with the new version.
+VERSION_FILES=("$VERSION_FILE")
+
+USAGE=$(
+  cat << END_OF_LINE
+Update the version of the project.
+
+Usage:
+  ${0##*/} [--push] [--label LABEL] (major | minor | patch | prerelease | build | finalize | show)
+  ${0##*/} --list-files
+  ${0##*/} (-h | --help)
+
+Options:
+  -h | --help    Show this message.
+  --push         Perform a \`git push\` after updating the version.
+  --label LABEL  Specify the label to use when updating the build or prerelease version.
+  --list-files   List the files that will be updated when the version is bumped.
+END_OF_LINE
+)
+
+old_version=$(sed -n "s/^[[:space:]]*\"version\": \"\(.*\)\"$/\1/p" $VERSION_FILE)
path: bump-version
user: login: jsf9k
body: Please see commit 6ce1755.  I tested this change by running `bump-version patch` locally, both with and without the extra comma.
created_at: 2025-04-02T02:49:39Z
author_association: MEMBER

PR comments:
user: login: github-advanced-security[bot]
created_at: 2025-03-28T03:17:07Z
body: This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on [this overview](/cisagov/setup-env-github-action/security/code-scanning?query=pr%3A81+is%3Aopen). Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out [the documentation](https://docs.github.com/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning). 
author_association: NONE
user: login: mcdonnnj
created_at: 2025-04-01T15:08:23Z
body: Please note that the version is, in an unfriendly way, tracked here: https://github.com/cisagov/setup-env-github-action/blob/6e901890ff80cdb05aa9308bebca0875d1e64ebf/package.json#L40
author_association: MEMBER
user: login: jsf9k
created_at: 2025-04-01T15:57:29Z
body: > Please note that the version is, in an unfriendly way, tracked here:
> 
> https://github.com/cisagov/setup-env-github-action/blob/6e901890ff80cdb05aa9308bebca0875d1e64ebf/package.json#L40

Please see commit 04294e4.  I tested these changes by bumping the patch version locally, then `git rebase`ing to remove that commit before pushing.
author_association: MEMBER
user: login: jsf9k
created_at: 2025-04-03T03:25:40Z
body: > I'm having some issues with `bump-version`. I do not see the version when I run `./bump-version show` and the `sed` command in use does not appear to work with the version of `sed` that ships with macOS:

`bump-version show` and `bump-version patch` both work with GNU `sed`.  Could the problem be the use of the `[:space:]` character class?  Could you try this command using the macOS/BSD version of `sed`?
```console
$ sed -n "s/^\s*\"version\": \"\(.*\)\",\?$/\1/p" package.json
1.0.0
```
author_association: MEMBER
user: login: mcdonnnj
created_at: 2025-04-03T12:48:42Z
body: > > I'm having some issues with `bump-version`. I do not see the version when I run `./bump-version show` and the `sed` command in use does not appear to work with the version of `sed` that ships with macOS:
> 
> `bump-version show` and `bump-version patch` both work with GNU `sed`. Could the problem be the use of the `[:space:]` character class? Could you try this command using the macOS/BSD version of `sed`?
> 
> ```
> $ sed -n "s/^\s*\"version\": \"\(.*\)\",\?$/\1/p" package.json
> 1.0.0
> ```

I believe you're correct and the `[:space:]` character class is the issue. In my terminal I have `sed` aliased to `gsed` (GNU sed) so it works as expected when I try to run the command in my terminal. However, the script is using the BSD `sed` that macOS ships with which is why I am getting the results I see.
author_association: MEMBER
user: login: jsf9k
created_at: 2025-04-03T13:52:19Z
body: > I'm having some issues with `bump-version`.

Please see commit b035dc2.


author_association: MEMBER