Skip to content
Merged
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
8 changes: 8 additions & 0 deletions .github/actions/dockerhub-login/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: login to Dockerhub (to prevent image pull trottling)
runs:
using: composite
steps:
- name: docker login
run: |
docker login -u "$DOCKERHUB_USERNAME" --password-stdin <<< "$DOCKERHUB_PASSWORD" || echo "::warning::docker-login failed, ignoring"
shell: bash
17 changes: 17 additions & 0 deletions .github/actions/refetch-artifacts/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Refetch artifacts
runs:
using: "composite"
steps:
- name: download wheel.zip
uses: actions/download-artifact@v4
with:
name: wheel
path: ./dist
- name: download sdist.zip
uses: actions/download-artifact@v4
with:
name: sdist
path: ./dist
- name: inspect
shell: bash
run: ls dist/
19 changes: 19 additions & 0 deletions .github/actions/setup-semantic-release/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: setup semantic-release with plugins
runs:
using: composite
steps:
- uses: actions/setup-node@v5
id: setup-node
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ steps.setup-node.node-version }}
- shell: bash
run: |
npm i -g \
semantic-release \
@semantic-release/exec \
@semantic-release/git \
@semantic-release/github \
@semantic-release/changelog \
@google/semantic-release-replace-plugin
51 changes: 51 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Setup base (python, pip cache, tox)
inputs:
python:
description: "Python version to use"
required: true
type: string
default: 3.12
outputs:
'python-version':
value: ${{ steps.python.outputs.python-version }}
runs:
using: "composite"
steps:
- name: pip cache
uses: actions/cache@v4
with:
path: |
~/.cache/pip
key: ${{ runner.os }}-pip-${{ inputs.python }}

- name: Cargo cache
uses: actions/cache/@v4
with:
path: "~/.cargo"
key: ${{ runner.os }}-cargo

- name: Poetry cache
uses: actions/cache/@v4
with:
path: "~/.cache/pypoetry"
key: ${{ runner.os }}-poetry-${{ inputs.python }}
restore-keys: |
${{ runner.os }}-poetry-

- uses: actions/setup-python@v6
id: python
with:
python-version: ${{ inputs.python }}

- name: upgrade pip and install tox
shell: bash
run: |
python -m pip -q install --upgrade pip "setuptools==65.6.2"
pip -q install "tox<4" tox-gh-actions

- name: install Rust and Poetry
shell: bash
run : |
curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable --profile minimal
source "$HOME/.cargo/env"
pip -q install poetry>=1.2.0
55 changes: 55 additions & 0 deletions .github/workflows/lint-and-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Lint and test
on:
pull_request:
push:
branches:
- master
- 'ci/**' # ci testing, pre-releases
#- 'feature/**'

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup
- name: Lint
id: lint
run: tox -e lint
continue-on-error: true
- name: Emit warning if lint failed
if: ${{ steps.lint.outcome != 'success' }}
run: echo "::warning::Linter failure suppressed (continue-on-error=true)"
test:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
python:
- "3.12"
- "3.11"
- "3.10"
- "3.9.14"
- "3.8"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup
with:
python: ${{ matrix.python }}
- name: Test
run: tox
validation:
name: Validation
runs-on: ubuntu-latest
needs: [test]
if: always()
steps:
- name: Validate matrix test success
run: |
# Check the status of the 'test' job (which includes all matrix variations)
if [ "${{ needs.test.result }}" != "success" ]; then
echo "One or more matrix test jobs failed."
exit 1
fi
echo "All matrix test jobs passed."
31 changes: 0 additions & 31 deletions .github/workflows/main.yml

This file was deleted.

146 changes: 146 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
name: Release

on:
workflow_run: # would only fire after file is merged to master
workflows: ["Lint and test"]
types:
- completed
branches:
- master
- 'ci/**' # ci testing, pre-releases
#- develop # can emit -dev releases but we do not want to
workflow_dispatch:
inputs:
dry_run:
description: "Run in dry-run mode (no publish)"
required: false
default: "true"
push: # only temporary, until this file lands on master (see above)
branches:
- 'ci/**'

# MUSTHAVE: Trusted publisher access for both repos.
# NOTE: according to docs, 'test' repo accounts are ephemeral and can be wiped at any time
# NOTE: 'test' accs are not that ephmeperal -- losing access to sandbox account (2FA issue) effectively locked us out of project; good test for workarounds though
# NOTE: as a part of regaining-control scenario we may use distinct project names in pyroject.toml (e.g. appmap-dev, appmap-ng)
env:
DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }}
pypi_project: appmap
#testpypi_project: appmap-dev # workaround for lost-access scenario
testpypi_project: appmapcitest

jobs:

setup:
runs-on: ubuntu-latest
outputs:
distribution_name: ${{ steps.configure.outputs.distribution_name }}
publish_to: ${{ steps.configure.outputs.publish_to }}
publish_env: ${{ steps.configure.outputs.publish_env }}
steps:
- id: configure
shell: bash
run: |
case "${{ github.ref_name }}" in
ci/*)
echo "publish_env=testpypi" >> $GITHUB_OUTPUT
echo "distribution_name=${{ env.testpypi_project }}" >> $GITHUB_OUTPUT
echo "publish_to=https://test.pypi.org/project/${{ env.testpypi_project }}" >> $GITHUB_OUTPUT
;;
master)
echo "publish_env=pypi" >> $GITHUB_OUTPUT
echo "distribution_name=${{ env.pypi_project }}" >> $GITHUB_OUTPUT
echo "publish_to=https://pypi.org/project/${{ env.pypi_project }}" >> $GITHUB_OUTPUT
;;
*)
echo "publish_env=SKIP" >> $GITHUB_OUTPUT
echo "distribution_name=${{ env.pypi_project }}" >> $GITHUB_OUTPUT
echo "publish_to=https://test.pypi.org/project/${{ env.pypi_project }}" >> $GITHUB_OUTPUT
;;
esac

release:
runs-on: ubuntu-latest
needs: setup
if: github.event_name == 'workflow_dispatch' || (github.event_name=='push' && startsWith(github.ref_name,'ci/') ) || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_branch == 'master' || startsWith(github.event.workflow_run.head_branch, 'ci/') ) )
permissions:
contents: write
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/setup-semantic-release # node+semantic-release
- uses: ./.github/actions/setup # poetry
- id: semantic-release # branch policies defined in .releaserc
env:
GIT_AUTHOR_NAME: appland-release
GIT_AUTHOR_EMAIL: release@app.land
GIT_COMMITTER_NAME: appland-release
GIT_COMMITTER_EMAIL: release@app.land
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DISTRIBUTION_NAME: ${{ needs.setup.outputs.distribution_name }}
run: |
if [ "$DRY_RUN" = "true" ]; then
semantic-release --dry-run
else
semantic-release
fi

- name: Upload wheel
if: env.DRY_RUN != 'true'
uses: actions/upload-artifact@v4
with:
name: wheel
path: dist/*.whl
- name: Upload sdist
if: env.DRY_RUN != 'true'
uses: actions/upload-artifact@v4
with:
name: sdist
path: dist/*.tar.gz
outputs: # not reused in fact
release_tag: ${{ steps.semantic-release.outputs.next_release_tag }}

smoketest:
runs-on: ubuntu-latest
needs: ['setup', 'release']
if: github.event.inputs.dry_run!='true'
continue-on-error: ${{ needs.setup.outputs.distribution_name!='appmap' }} # altered names won't work anyway
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/refetch-artifacts
- name: dockerhub login (for seamless docker pulling)
uses: ./.github/actions/dockerhub-login
env:
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }}
continue-on-error: true
- run: ci/scripts/run_tests.sh
env:
SMOKETEST_DOCKER_IMAGE: python:3.12-slim
DISTRIBUTION_NAME: ${{ needs.setup.outputs.distribution_name }}

# as a workaround to ownership issues (lost access to project)
publish:
name: publish package on PyPI
needs: ['setup', 'release','smoketest']
if: (( github.event.inputs.dry_run != 'true' ) && ( (needs.setup.outputs.publish_env == 'pypi') || (needs.setup.outputs.publish_env == 'testpypi') ) )
runs-on: ubuntu-latest
environment:
name: ${{ needs.setup.outputs.publish_env }}
url: ${{ needs.setup.outputs.publish_to }}
permissions:
id-token: write
steps:
- uses: actions/checkout@v5
- uses: ./.github/actions/refetch-artifacts

- name: Publish to PyPI
if: needs.setup.outputs.publish_env=='pypi'
uses: pypa/gh-action-pypi-publish@release/v1

- name: Publish to TestPyPI
if: needs.setup.outputs.publish_env=='testpypi'
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/ # trailing slash matters!
30 changes: 29 additions & 1 deletion .releaserc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# Allowed number of prerelease rules: 1..3
# While semantic-release allows globs, they must be combined with `prerelease: true` and suffix is derived from name than. It conflicts with PEP440
# PEP440 version rules (not compatible with SemVer): [N!]N(.N)*[{a|b|rc}N][.postN][.devN]
# Consequences:
# - prerelease branches must be explicitly specified, no asterisks
# - prerelease parameter should be one of: a,b,rc,dev,post
# - translation from SemVer prerelease notation to PEP440 is tone in 'replacements' section
branches: # only branches listed here will create releases
- master
- name: ci/trusted_publishing_test
prerelease: dev
#- name: develop
# prerelease: dev
#- name: feature/*
# prerelease: true # will use branch name as suffix
plugins:
- '@semantic-release/commit-analyzer'
- '@semantic-release/release-notes-generator'
Expand All @@ -13,9 +28,22 @@ plugins:
hasChanged: true
numMatches: 1
numReplacements: 1
- - '@google/semantic-release-replace-plugin' # optional SemVer -> PEP440 coercion
- replacements:
- files: [pyproject.toml] # optional: SemVer prerelease -> PEP440 ("1.2.3-dev.1" -> "1.2.3.dev1")
from: '^version = "(\\d+\\.\\d+\\.\\d+)-(dev|post)\\.(\\d+)"'
to: 'version = "\\1.\\2\\3"'
- files: [pyproject.toml] # optional: SemVer prerelease -> PEP440 ("1.2.3-rc.10" -> "1.2.3rc10" )
from: '^version = "(\\d+\\.\\d+\\.\\d+)-(a|b|rc)\\.(\\d+)"'
to: 'version = "\\1\\2\\3"'
- - '@semantic-release/git'
- assets:
- CHANGELOG.md
- pyproject.toml
- - '@semantic-release/exec'
- publishCmd: poetry publish --build
- prepareCmd: |
/bin/bash ./ci/scripts/build_with_poetry.sh
- - '@semantic-release/github':
- assets:
- dist/*.whl
- dist/*.tar.gz
Loading
Loading