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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,18 @@
"template_dir": "python",
"template_ref": "main",
"cookie_dir": "",
"pull_request_strategy": "create",
"pull_request_strategy": "update-or-create",
"post_actions": [],
"draft": false,
<<<<<<< HEAD
<<<<<<< HEAD
"baked_commit_ref": "a5add2662f26a3b877635bbf1fd787682414d2bf",
=======
"baked_commit_ref": "0bac2e8ca365aea9a730bfc06c5e5029b25dcf50",
>>>>>>> 1cad760 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
=======
"baked_commit_ref": "1c8e2eb54eafb18e541e80793a2e71d1fcb3b067",
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
"drift_managed_branch": "develop"
}
}
Expand Down
60 changes: 54 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
- name: "Linting: ruff format"
Expand All @@ -36,7 +36,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
- name: "Linting: ruff"
Expand All @@ -49,7 +49,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
poetry-install-options: "--only dev,docs"
Expand All @@ -63,7 +63,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
- name: "Checking: poetry lock file"
Expand All @@ -76,7 +76,7 @@ jobs:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
- name: "Linting: yamllint"
Expand All @@ -91,13 +91,18 @@ jobs:
strategy:
fail-fast: true
matrix:
<<<<<<< HEAD
python-version: ["3.10", "3.11"] # TODO: Switch back to latest supported Python when https://github.com/networktocode/pyntc/issues/351 is completed
=======
python-version: ["3.10"]
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
env:
INVOKE_PYNTC_PYTHON_VER: "${{ matrix.python-version }}"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
<<<<<<< HEAD
uses: "networktocode/gh-action-setup-poetry-environment@v6"
with:
poetry-version: "2.1.3"
Expand Down Expand Up @@ -136,6 +141,9 @@ jobs:
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
=======
uses: "networktocode/gh-action-setup-poetry-environment@v7"
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
with:
poetry-version: "2.1.3"
- name: "Get image version"
Expand All @@ -156,6 +164,46 @@ jobs:
cache-to: "type=gha,scope=${{ env.INVOKE_PYNTC_IMAGE_NAME }}-${{ env.INVOKE_PYNTC_IMAGE_VER }}-py${{ matrix.python-version }}"
build-args: |
PYTHON_VER=${{ matrix.python-version }}
<<<<<<< HEAD
=======
- name: "Linting: Pylint"
run: "poetry run invoke pylint"
pytest:
needs:
- "check-in-docker"
strategy:
fail-fast: true
matrix:
python-version: ["3.10", "3.14"]
runs-on: "ubuntu-latest"
env:
INVOKE_PYNTC_PYTHON_VER: "${{ matrix.python-version }}"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
- name: "Get image version"
run: "echo INVOKE_PYNTC_IMAGE_VER=`poetry version -s`-py${{ matrix.python-version }} >> $GITHUB_ENV"
- name: "Set up Docker Buildx"
id: "buildx"
uses: "docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2" # v3.10.0
- name: "Build"
uses: "docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25" # v5.4.0
with:
builder: "${{ steps.buildx.outputs.name }}"
context: "./"
push: false
load: true
tags: "${{ env.INVOKE_PYNTC_IMAGE_NAME }}:${{ env.INVOKE_PYNTC_IMAGE_VER }}"
file: "./Dockerfile"
cache-from: "type=gha,scope=${{ env.INVOKE_PYNTC_IMAGE_NAME }}-${{ env.INVOKE_PYNTC_IMAGE_VER }}-py${{ matrix.python-version }}"
cache-to: "type=gha,scope=${{ env.INVOKE_PYNTC_IMAGE_NAME }}-${{ env.INVOKE_PYNTC_IMAGE_VER }}-py${{ matrix.python-version }}"
build-args: |
PYTHON_VER=${{ matrix.python-version }}
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
- name: "Run Tests"
run: "poetry run invoke pytest"
changelog:
Expand All @@ -169,7 +217,7 @@ jobs:
with:
fetch-depth: "0"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v6"
uses: "networktocode/gh-action-setup-poetry-environment@v7"
with:
poetry-version: "2.1.3"
- name: "Check for changelog entry"
Expand Down
223 changes: 223 additions & 0 deletions .github/workflows/prepare_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
---
name: "Prepare Release"
on: # yamllint disable-line rule:truthy rule:comments
workflow_dispatch:
inputs:
bump_rule:
description: "Select the version bump type"
required: true
default: "patch"
type: "choice"
options:
- "prerelease"
- "patch"
- "minor"
- "major"
target_branch:
description: "Create the release from this branch (default: main)."
required: true
default: "main"
date:
description: "Date of the release YYYY-MM-DD (defaults to today's date in the US Eastern TZ)."
required: false
default: ""
<<<<<<< HEAD
=======
previous_version:
description: "The previous version tag to use for generating release notes (defaults to the latest tag or initial commit if no tags exist)."
required: false
default: ""
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)

jobs:
prepare-release:
permissions:
contents: "write"
pull-requests: "write"
name: "Prepare Release"
runs-on: "ubuntu-latest"
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
with:
# If target_branch is 'main', use 'develop' as the source branch. Otherwise, the source and target branch are the same.
ref: "${{ github.event.inputs['target_branch'] == 'main' && 'develop' || github.event.inputs['target_branch'] }}"
fetch-depth: 0 # Fetch all history for git tags

- name: "Setup environment"
<<<<<<< HEAD
uses: "networktocode/gh-action-setup-poetry-environment@v6"
=======
uses: "networktocode/gh-action-setup-poetry-environment@v7"
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
with:
poetry-version: "2.1.3"
poetry-install-options: "--with dev"

- name: "Validate Branch and Tags"
run: |
# 1. Verify branch exists
if ! git rev-parse --verify origin/${{ github.event.inputs.target_branch }} > /dev/null 2>&1; then
echo "Error: Branch ${{ github.event.inputs.target_branch }} does not exist."
exit 1
fi

# 2. Try to get the previous version tag
# If it fails (no tags), get the hash of the first commit
<<<<<<< HEAD
if PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null); then
=======
if [ -n "${{ github.event.inputs.previous_version }}" ]; then
PREV_TAG="${{ github.event.inputs.previous_version }}"
echo "Using user-specified previous version: $PREV_TAG"
echo "PREVIOUS_TAG=$PREV_TAG" >> $GITHUB_ENV
elif PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null); then
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
echo "PREVIOUS_TAG=$PREV_TAG" >> $GITHUB_ENV
echo "Found previous tag: $PREV_TAG"
else
# Fallback to the first commit in the repository
FIRST_COMMIT=$(git rev-list --max-parents=0 HEAD)
echo "PREVIOUS_TAG=$FIRST_COMMIT" >> $GITHUB_ENV
echo "No tags found. Falling back to initial commit: $FIRST_COMMIT"
fi

- name: "Determine New Version"
id: "versioning"
<<<<<<< HEAD
run: |
# Perform the bump based on the user input
poetry version ${{ github.event.inputs.bump_rule }}
=======
env:
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
# Bump the poetry version based on the user input
CURRENT_POETRY_VER=$(poetry version --short)
set +e # continue running if the next command fails
GITHUB_RELEASE_EXISTS=$(gh release view v$CURRENT_POETRY_VER --json publishedAt --jq '.publishedAt')
set -e
# Unconditionally bump the version if the current version is alpha0 or beta0
if [[ $CURRENT_POETRY_VER == *a0 || $CURRENT_POETRY_VER == *b0 || $CURRENT_POETRY_VER == *rc0 ]]; then
poetry version ${{ github.event.inputs.bump_rule }}
# If the bump rule is prerelease and a release doesn't already exist in github we don't bump the version

# This is because we've already bumped to the prerelease version after the previous release
elif [[ "${{ github.event.inputs.bump_rule }}" == "prerelease" && "$CURRENT_POETRY_VER" =~ (a|b|rc)[0-9]+$ && -z "$GITHUB_RELEASE_EXISTS" ]]; then
echo "Prerelease v$CURRENT_POETRY_VER does not exist in github, using this version"
else
poetry version ${{ github.event.inputs.bump_rule }}
fi
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)

# Capture the New version string for use in other steps
NEW_VER=$(poetry version --short)
echo "NEW_VERSION=$NEW_VER" >> $GITHUB_ENV
echo "RELEASE_BRANCH=release/$NEW_VER" >> $GITHUB_ENV

- name: "Set Date Variable"
run: |
if [ -z "${{ github.event.inputs.date }}" ]; then
RELEASE_DATE=$(TZ=America/New_York date +%Y-%m-%d)
else
RELEASE_DATE="${{ github.event.inputs.date }}"
fi
echo "RELEASE_DATE=$RELEASE_DATE" >> $GITHUB_ENV

- name: "Create Release Branch"
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
git config user.name "${{ github.actor }}"
git config user.email "${{ github.actor }}@users.noreply.github.com"

# Ensure release branch doesn't already exist
if git rev-parse --verify origin/${{ env.RELEASE_BRANCH }} > /dev/null 2>&1; then
echo "Error: Release branch ${{ env.RELEASE_BRANCH }} already exists."
exit 1
fi

# Create a new branch for the release
git checkout -b "${{ env.RELEASE_BRANCH }}"

- name: "Regenerate poetry.lock"
run: "poetry lock --regenerate"

- name: "Generate Github Release Notes"
env:
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
# 1. Get Towncrier Draft
TOWNCRIER_NOTES=$(poetry run towncrier build --version "${{ env.NEW_VERSION }}" --date "${{ env.RELEASE_DATE }}" --draft)

# 2. Call GitHub API to generate raw notes
RAW_GH_NOTES=$(gh api /repos/${{ github.repository }}/releases/generate-notes \
-f tag_name="v${{ env.NEW_VERSION }}" \
-f target_commitish="${{ github.event.inputs['target_branch'] == 'main' && 'develop' || github.event.inputs['target_branch'] }}" \
-f previous_tag_name="${{ env.PREVIOUS_TAG }}" --jq '.body')

# 3. Parse usernames (Regex match)
# We use grep to find "@user" patterns, sort, and uniq them
USERNAMES=$(echo "$RAW_GH_NOTES" | grep -oP 'by @\K[a-zA-Z0-9-]+' | sort -u | grep -vE 'dependabot|nautobot-bot|github-actions' || true)

# 4. Format the Contributors section
CONTRIBUTORS_SECTION="## Contributors"
for user in $USERNAMES; do
CONTRIBUTORS_SECTION="$CONTRIBUTORS_SECTION"$'\n'"* @$user"
done

# 5. Extract the "Full Changelog" or "New Contributors" part
# Using awk to grab everything from '## New Contributors' or '**Full Changelog**' to the end
GH_FOOTER=$(echo "$RAW_GH_NOTES" | awk '/## New Contributors/ || /\*\*Full Changelog\*\*/ {found=1} found {print}')
if [ -z "$GH_FOOTER" ]; then
GH_FOOTER=$(echo "$RAW_GH_NOTES" | sed -n '/**Full Changelog**/,$p')
fi

# 6. Combine everything
FINAL_NOTES="$TOWNCRIER_NOTES"$'\n\n'"$CONTRIBUTORS_SECTION"$'\n\n'"$GH_FOOTER"

# 7. Save to a temporary file to avoid shell argument length limits
echo "$FINAL_NOTES" > ../consolidated_notes.md

<<<<<<< HEAD
- name: "Generate Release Notes"
=======
- name: "Generate App Release Notes and update mkdocs.yml"
>>>>>>> 45de4a7 (Cookie updated targeting develop by NetworkToCode Cookie Drift Manager Tool)
run: "poetry run inv generate-release-notes --version '${{ env.NEW_VERSION }}' --date '${{ env.RELEASE_DATE }}'"

- name: "Commit Changes and Push"
run: |
# Add all changes (pyproject.toml, poetry.lock, etc.)
git add .
git commit -m "prepare release v${{ env.NEW_VERSION }}"
git push origin "${{ env.RELEASE_BRANCH }}"

- name: "Create Pull Request"
env:
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
gh pr create \
--title "Release v${{ env.NEW_VERSION }}" \
--body-file "../consolidated_notes.md" \
--base "${{ github.event.inputs.target_branch }}" \
--head "${{ env.RELEASE_BRANCH }}"

- name: "Create Draft Release"
env:
GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
if [[ "${{ github.event.inputs.bump_rule }}" == "prerelease" ]]; then
RELEASE_FLAGS="--prerelease"
elif [[ "${{ github.event.inputs.target_branch }}" == "main" ]]; then
RELEASE_FLAGS="--latest"
else
RELEASE_FLAGS="--latest=false"
fi

gh release create "v${{ env.NEW_VERSION }}" \
--draft \
$RELEASE_FLAGS \
--title "v${{ env.NEW_VERSION }} - ${{ env.RELEASE_DATE }}" \
--notes-file "../consolidated_notes.md" \
--target "${{ github.event.inputs.target_branch }}"
Loading