diff --git a/.github/do-release.sh b/.github/do-release.sh index 37156abef..b9e2daebc 100755 --- a/.github/do-release.sh +++ b/.github/do-release.sh @@ -2,4 +2,4 @@ ansible-galaxy collection build ansible-galaxy collection publish paloaltonetworks-panos-* --server release_galaxy -ansible-galaxy collection publish paloaltonetworks-panos-* --server automation_hub \ No newline at end of file +ansible-galaxy collection publish paloaltonetworks-panos-* --server automation_hub diff --git a/.github/workflows/_discover_python_ver.yml b/.github/workflows/_discover_python_ver.yml new file mode 100644 index 000000000..e8307eeb6 --- /dev/null +++ b/.github/workflows/_discover_python_ver.yml @@ -0,0 +1,28 @@ +name: (sub) Discover Python version + +defaults: + run: + shell: bash + +permissions: + contents: read + +on: + workflow_call: + outputs: + pyversion: + description: A discovered Python version + value: ${{ jobs.pyversion.outputs.pyversion }} + +jobs: + pyversion: + name: Discover minimum Python version + runs-on: ubuntu-latest + outputs: + pyversion: ${{ steps.pyversion.outputs.pyversion }} + steps: + - name: checkout code + uses: actions/checkout@v4 + - name: discover Python version + id: pyversion + uses: PaloAltoNetworks/pan-os-upgrade-assurance/.github/actions/discover_python_version@v0.3.1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90747566e..97334d6c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,6 @@ on: env: NAMESPACE: paloaltonetworks COLLECTION_NAME: panos - PYTHON_VERSION: 3.8 jobs: @@ -109,9 +108,14 @@ jobs: cd .github/workflows python -m tox -- ../.. + pyversion: + name: Discover minimum Python version + uses: ./.github/workflows/_discover_python_ver.yml + format: name: Code Format Check runs-on: ubuntu-latest + needs: pyversion defaults: run: working-directory: ./ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} @@ -123,7 +127,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ needs.pyversion.outputs.pyversion }} - name: Install Poetry uses: Gr1N/setup-poetry@v8 @@ -139,6 +143,10 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: [sanity, tox, lint, format] runs-on: ubuntu-latest + outputs: + new_release_published: ${{ steps.release.outputs.new_release_published }} + new_release_version: ${{ steps.release.outputs.new_release_version }} + new_release_git_tag: ${{ steps.release.outputs.new_release_git_tag }} steps: - name: Checkout @@ -192,12 +200,12 @@ jobs: docs: name: docs if: github.event_name == 'push' && github.ref == 'refs/heads/main' - needs: [release] + needs: [release, pyversion] runs-on: ubuntu-latest defaults: run: - working-directory: ./ansible_collections/paloaltonetworks/panos + working-directory: ./ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} steps: # Just a note here: The Ansible stuff is apparently doing realpath @@ -207,12 +215,12 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - path: ./ansible_collections/paloaltonetworks/panos + path: ./ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Setup Python uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: ${{ needs.pyversion.outputs.pyversion }} - name: Install Poetry uses: Gr1N/setup-poetry@v8 @@ -247,8 +255,8 @@ jobs: run: | cd ../../../.. mv pan-os-ansible the_repo - mv the_repo/ansible_collections/paloaltonetworks/panos pan-os-ansible - mkdir -p pan-os-ansible/ansible_collections/paloaltonetworks/panos + mv the_repo/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} pan-os-ansible + mkdir -p pan-os-ansible/ansible_collections/${{ env.NAMESPACE }}/${{ env.COLLECTION_NAME }} - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@v4.4.3 @@ -257,3 +265,82 @@ jobs: branch: gh-pages folder: docs/html clean: true + + rc: + name: Check rc EE + runs-on: ubuntu-latest + needs: [sanity, tox, lint, format] + if: (github.event_name == 'push' && github.ref == 'refs/heads/develop') + outputs: + rc: ${{ steps.rc.outputs.new_release_published }} + new_release_version: ${{ steps.rc.outputs.new_release_version }} + + steps: + - name: checkout code + uses: actions/checkout@v4 + + - name: setup node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + + - name: install dependencies + run: | + npm install --save-dev semantic-release + npm install @semantic-release/commit-analyzer -D + npm install conventional-changelog-conventionalcommits -D + npm install @semantic-release/changelog -D + npm install @semantic-release/git -D + npm install @semantic-release/exec -D + # npx semantic-release + # npm ci + + - name: trick semantic check + id: rc + run: | + # Trick semantic-release into thinking we're not in a CI environment + OUTPUT="$(bash -c "unset GITHUB_ACTIONS && unset GITHUB_EVENT_NAME && npx semantic-release --dry-run --no-ci --branches '${GITHUB_REF#refs/heads/}'")" + # print output + echo "$OUTPUT" + # grep with semver regex - \K means to start matching from here in Perl regex + NEW_RELEASE_VERSION=$(echo "$OUTPUT" | grep -oP 'The next release version is \K(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?' || echo -n "") + echo "new_release_version=$NEW_RELEASE_VERSION" >> "$GITHUB_OUTPUT" + + if [ -z "$NEW_RELEASE_VERSION" ]; then + echo "new_release_published=false" >> "$GITHUB_OUTPUT" + else + echo "new_release_published=true" >> "$GITHUB_OUTPUT" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REF: ${{ github.ref }} + + # below does NOT work because semantic-release expects branch name in the config even in dry-run + # but we run rc check in non main branches + # - name: rc check + # id: rc + # uses: cycjimmy/semantic-release-action@v4 + # with: + # dry_run: true + # semantic_version: 17.1.1 + # extra_plugins: | + # conventional-changelog-conventionalcommits@^4.4.0 + # @semantic-release/changelog@^5.0.1 + # @semantic-release/git@^9.0.0 + # @semantic-release/exec@^5.0.00 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build_dev_ee: + name: dev_ee + needs: rc + if: needs.rc.outputs.rc == 'true' + uses: ./.github/workflows/ee.yml + + build_prod_ee: + name: release_ee + needs: release + uses: ./.github/workflows/ee.yml + with: + release: true + release_tag: ${{ needs.release.outputs.new_release_git_tag }} diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml new file mode 100644 index 000000000..753de7689 --- /dev/null +++ b/.github/workflows/ee.yml @@ -0,0 +1,246 @@ +name: Ansible EE Image + +on: + workflow_call: + inputs: + release: + description: Prepare EE for a release + type: boolean + default: false + release_tag: # tag starting with 'v' like v1.2.3 + description: Git tag for release to prepare EE + type: string + required: false + workflow_dispatch: + inputs: + release: + description: EE for a release or development + type: boolean + default: false + +env: + NAMESPACE: paloaltonetworks + COLLECTION_NAME: panos + +jobs: + + build_ee: + name: Ansible EE + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + # if event == push (same event from workflow_call) and inputs.release == true + # release_tag must be given as input + # checkout tag and prepare EE on tag + # elif event == workflow_dispatch and inputs.release == true + # workflow must be run on a tag + # checkout tag and prepare EE on tag + # else - could be workflow_call or workflow_dispatch with release false + # normal checkout - it will checkout whatever the workflow is run on + # prepare EE on branch + - name: check and findout the tag + id: tag + # outputs tag name as v1.2.3 and version as 1.2.3 + run: | + if [[ "${{ github.event_name }}" == "push" && + "${{ inputs.release }}" == "true" ]]; then + if [[ "${{ inputs.release_tag }}" != "v"* ]]; then + echo "release_tag (${{ inputs.release_tag }}) must be provided when workflow_call called with release." + exit 1 + fi + TAG_VERSION=$(echo "${{inputs.release_tag}}" | sed 's#v##') + echo "name=${{inputs.release_tag}}" >> $GITHUB_OUTPUT + echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT + echo "Ansible EE will be prepared for release ${{ inputs.release_tag }}" + elif [[ "${{ github.event_name }}" == "workflow_dispatch" && + "${{ inputs.release }}" == "true" ]]; then + if [[ "${GITHUB_REF}" != "refs/tags/v"* ]]; then + echo "workflow_dispatch must be run on a release tag when release is selected - run on ${GITHUB_REF}" + exit 1 + fi + TAG_NAME=$(echo "${GITHUB_REF}" | sed 's#refs/tags/##') + TAG_VERSION=$(echo "${TAG_NAME}" | sed 's#v##') + echo "name=$TAG_NAME" >> $GITHUB_OUTPUT + echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT + echo "Ansible EE will be prepared for release $TAG_NAME" + else + echo "Ansible EE will be prepared for branch ${GITHUB_REF#refs/heads/}" + fi + env: + GITHUB_REF: ${{ github.ref }} + + # checkout tag for releae otherwise checkout branch + - name: check out code + uses: actions/checkout@v4 + with: + # if tag is empty; github.ref else tag.outputs.name + ref: ${{ steps.tag.outputs.name == '' && github.ref || steps.tag.outputs.name }} + + - name: discover Python version + id: pyversion + uses: PaloAltoNetworks/pan-os-upgrade-assurance/.github/actions/discover_python_version@v0.3.1 + + - name: install Python + uses: actions/setup-python@v4 + with: + python-version: ${{ steps.pyversion.outputs.pyversion }} + cache: pip + + - name: install Poetry + uses: Gr1N/setup-poetry@v8 + + - name: prep Poetry venv + run: | + poetry env use ${{ steps.pyversion.outputs.pyversion }} + poetry lock + poetry install --with ansible-ee --without dev --no-root + + - name: set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # produce docker tags for semver if on a tag, otherwise take ref branch name + # latest tag is only produced for semver operating on a tag + - name: determine docker tags and labels + id: meta + uses: docker/metadata-action@v5 + with: + context: git # git - this ensures to reference the current git context instead of workflow context (context info ref/sha) + images: ghcr.io/paloaltonetworks/pan-os-ansible + tags: | + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} + type=ref,event=branch + type=ref,event=tag + + # take pan-os-ansible from galaxy for a release, but local build for develop + # ref - https://github.com/ansible-collections/community.dns/blob/main/.github/workflows/ee.yml#L96-L98 + - name: Build collection from development branch + run: | + ansible-galaxy collection build + if: ${{ inputs.release == false }} + + - name: create base EE file + run: | + cat > execution-environment.yml <=2.15.0rc2,<2.16 + ansible_runner: + package_pip: ansible-runner + system: | + git-core [platform:rpm] + python3.9-devel [platform:rpm compile] + libcurl-devel [platform:rpm compile] + sshpass [platform:rpm] + rsync [platform:rpm] + epel-release [platform:rpm] + unzip [platform:rpm] + galaxy: requirements.yml + python: requirements-ee.txt + + additional_build_steps: + append_base: + - RUN \$PYCMD -m pip install -U pip + append_final: + # SymLink `python` -> `python3.9` + - RUN alternatives --install /usr/bin/python python /usr/bin/python3.9 39 + + EOF + + - name: append build files to EE for development + run: | + COLLECTION_FILENAME="$(ls "${{ env.NAMESPACE }}-${{ env.COLLECTION_NAME }}"-*.tar.gz)" + + # append to existing EE file + cat >> execution-environment.yml < requirements.yml < requirements.yml < requirements-ee.txt < Posted by [semantic-release](https://github.com/semantic-release/semantic-release) bot" + "successComment": ":tada: This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:\n\nThe release is available on [Ansible Galaxy](https://galaxy.ansible.com/ui/repo/published/paloaltonetworks/panos) and [GitHub release](https://github.com/PaloAltoNetworks/pan-os-ansible/releases)\n\n> Posted by [semantic-release](https://github.com/semantic-release/semantic-release) bot", + "failTitle": false } ] ], "preset": "conventionalcommits" -} \ No newline at end of file +} diff --git a/pyproject.toml b/pyproject.toml index 3d51a63a1..8df7c6fb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,12 @@ chardet = "3.0.4" idna = "2.8" requests = "^2.22.0" +[tool.poetry.group.ansible-ee] +optional = true + +[tool.poetry.group.ansible-ee.dependencies] +ansible-builder = "^3.0.0" + [build-system] requires = ["poetry>=0.12"] build-backend = "poetry.masonry.api" \ No newline at end of file