Skip to content

Commit ab0bb44

Browse files
authored
Merge pull request #5 from Expensify/cole/paramiko
Fork fab-classic to support packaged saltfab
2 parents 33f8954 + 12eb08f commit ab0bb44

File tree

7 files changed

+1999
-5
lines changed

7 files changed

+1999
-5
lines changed

.github/workflows/linux.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636

3737
container: "python:${{matrix.imgtag}}"
3838
steps:
39-
- uses: actions/checkout@v4
39+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
4040
- name: System dependencies
4141
run: |
4242
apt-get -q -y update
@@ -47,7 +47,7 @@ jobs:
4747
run: |
4848
pip install -r dev-requirements.txt
4949
pip install "$PARAMIKO"
50-
if [ "$(echo $PARAMIKO | cut -d= -f1)" != paramiko-ng ]; then
50+
if [ "$(echo "$PARAMIKO" | cut -d= -f1)" != paramiko-ng ]; then
5151
export PARAMIKO_REPLACE=1
5252
fi
5353
pip install -e .
@@ -67,7 +67,7 @@ jobs:
6767
- name: Test
6868
run: |
6969
export USER=root HOME=/root
70-
eval $(ssh-agent)
70+
eval "$(ssh-agent)"
7171
ssh-add ~/.ssh/testkey
7272
script -e -q -c "fab test" /dev/null
7373
script -e -q -c "fab -H localhost test:integration" /dev/null
@@ -78,7 +78,7 @@ jobs:
7878
container: "python:3.9-bookworm"
7979

8080
steps:
81-
- uses: actions/checkout@v4
81+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
8282

8383
- name: Install dependencies
8484
run: |

.github/workflows/release.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# This workflow is used to release the python-libs package to the expensify index.
2+
# It uses "trusted publishing" which is a python index feature that allows for
3+
# Github and other CI providers to self authenticate and publish packages to the index.
4+
# See https://docs.pyx.dev/trusted-publishing/ for more information.
5+
#
6+
# The name of this file is important, it must be named release.yml as part of the trusted
7+
# publishing setup, if you change the file name you will have to update the trusted publishing
8+
# setup in pyx.dev.
9+
name: Release
10+
11+
# Only allow one release job to run at a time
12+
# this prevents a race condition where two merges occur
13+
# which causes two version bumps and then the releases
14+
# being done out of order.
15+
concurrency: release
16+
17+
# Create a release on any new tag which is a valid version number.
18+
on:
19+
push:
20+
tags:
21+
- '*.*.*'
22+
23+
jobs:
24+
build:
25+
runs-on: ubuntu-latest
26+
permissions:
27+
contents: read # for actions/checkout in private repos
28+
29+
steps:
30+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
31+
with:
32+
persist-credentials: false
33+
34+
- name: Set up uv
35+
uses: astral-sh/setup-uv@2ddd2b9cb38ad8efd50337e8ab201519a34c9f24 # v7.1.1
36+
37+
- name: Build distributions
38+
run: uv build
39+
40+
- name: Upload distributions
41+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
42+
with:
43+
name: dists
44+
path: dist/
45+
if-no-files-found: error
46+
47+
pyx-publish:
48+
needs: [build]
49+
runs-on: ubuntu-latest
50+
permissions:
51+
contents: read # for actions/checkout in private repos
52+
id-token: write # for Trusted Publishing to pyx
53+
54+
# Deploy environment requires that certain conditions are met for this code to run.
55+
# These conditions are configured in the repo settings. This below string is also
56+
# used in the trusted publishing setup in pyx.dev.
57+
environment: pyx.dev
58+
59+
steps:
60+
# This checkout might seem useless but it lets the uv step below use the uv cache.
61+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
62+
with:
63+
persist-credentials: false
64+
65+
- name: Download distributions
66+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
67+
with:
68+
name: dists
69+
path: dist/
70+
71+
- uses: astral-sh/pyx-auth-action@08873fa2b19cf2361327222bea1657faed760ae2 # v0.0.6
72+
id: auth
73+
with:
74+
workspace: expensify
75+
registry: main
76+
77+
- run: uv publish dist/*
78+
env:
79+
UV_PUBLISH_URL: ${{ steps.auth.outputs.url }}
80+
UV_PUBLISH_TOKEN: ${{ steps.auth.outputs.token }}

.github/workflows/version.yml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: Bump version
2+
3+
# Don't let more than one version bump job run at a time
4+
# this prevents a race condition where two merges occur
5+
# at the same time and the version bump of the first one is not
6+
# finished before the second one starts, then they will both
7+
# try to bump to the same version.
8+
concurrency: version
9+
10+
on:
11+
push:
12+
branches: [main]
13+
14+
jobs:
15+
version:
16+
runs-on: ubuntu-latest
17+
if: ${{ github.actor != 'botify-app[bot]' }} # prevent infinite loop
18+
steps:
19+
- name: Generate a GitHub App token
20+
id: generateAppToken
21+
uses: actions/create-github-app-token@3ff1caaa28b64c9cc276ce0a02e2ff584f3900c5 # v2.0.2
22+
with:
23+
app-id: ${{ vars.BOTIFY_APP_CLIENT_ID }}
24+
private-key: ${{ secrets.BOTIFY_APP_PRIVATE_KEY }}
25+
26+
# This step setups up the git config which is then used later to push the tag.
27+
# Auth for the repo is setup at this step, so we need to pass the bot token
28+
# in so that it does not use the GITHUB_TOKEN when the tag is pushed. This
29+
# allows this workflow to trigger another workflow from the tag event.
30+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
31+
with:
32+
ref: main
33+
token: ${{ steps.generateAppToken.outputs.token }}
34+
35+
- name: Install the latest version of uv
36+
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
37+
with:
38+
enable-cache: true
39+
cache-dependency-glob: "uv.lock"
40+
41+
- name: Get merged pull request
42+
id: getMergedPullRequest
43+
run: |
44+
echo "ORIGINAL_PR_URL=$(gh pr list --state merged --json 'mergeCommit,url' --jq '.[] | select(.mergeCommit.oid | contains("${{ github.sha }}")) | .url')" >> "$GITHUB_ENV"
45+
shell: bash
46+
env:
47+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
49+
# Bumps the version and automatically locks and syncs.
50+
- name: Bump version
51+
id: bump-version
52+
run: ./scripts/bump-version.sh
53+
shell: bash
54+
55+
- name: Created signed commit and push tags
56+
run: |
57+
set -euxo pipefail
58+
VERSION="$(uv version --short)"
59+
readonly VERSION
60+
61+
# Push commits for the updated files
62+
for FILE in pyproject.toml uv.lock ; do
63+
MESSAGE="Update $FILE version to $VERSION"
64+
SHA=$(git rev-parse "main:$FILE")
65+
# Create a file with the base64 encoded content
66+
base64 -i "$FILE" > "base64.txt"
67+
NEW_COMMIT_SHA=$(gh api --method PUT "/repos/:owner/:repo/contents/$FILE" \
68+
--field message="$MESSAGE" \
69+
--field content="@base64.txt" \
70+
--field encoding="base64" \
71+
--field branch="main" \
72+
--field sha="$SHA" \
73+
--jq '.commit.sha')
74+
done
75+
76+
# Set up git user info so we can push a tag
77+
# botify-app[bot] GitHub App ID can be found here: https://api.github.com/users/botify-app[bot]
78+
git config --global user.name "botify-app[bot]"
79+
git config --global user.email "208549588+botify-app[bot]@users.noreply.github.com"
80+
81+
# Fetch the commit that was made via the API
82+
git fetch origin main
83+
84+
# Tag new_commit_sha with our new version
85+
git tag -a "$VERSION" "$NEW_COMMIT_SHA" -m "$VERSION"
86+
87+
# Push the new tag
88+
git push origin tag "$VERSION"
89+
shell: bash
90+
env:
91+
GH_TOKEN: ${{ steps.generateAppToken.outputs.token }}
92+
93+
- name: Comment on PR
94+
run: |
95+
gh pr comment ${{ env.ORIGINAL_PR_URL }} --body ":rocket: Released in version $(uv version --short) :rocket:"
96+
env:
97+
GH_TOKEN: ${{ steps.generateAppToken.outputs.token }}
98+
shell: bash

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

pyproject.toml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
[project]
2+
name = "fab-classic"
3+
version = "1.20.2"
4+
description = "fab-classic is a simple, Pythonic tool for remote execution and deployment."
5+
readme = "README.rst"
6+
requires-python = ">=3.5"
7+
authors =[{ name = "Jeff Forcier", email = "jeff@bitprophet.org" }]
8+
maintainers = [{ name = "Pierce Lopez", email = "pierce.lopez@gmail.com" }]
9+
urls = { Homepage = "https://github.com/ploxiln/fab-classic" }
10+
dependencies = [
11+
"paramiko>=2.0"
12+
]
13+
14+
classifiers = [
15+
"Development Status :: 5 - Production/Stable",
16+
"Environment :: Console",
17+
"Intended Audience :: Developers",
18+
"Intended Audience :: System Administrators",
19+
"License :: OSI Approved :: BSD License",
20+
"Operating System :: MacOS :: MacOS X",
21+
"Operating System :: POSIX",
22+
23+
# Only allow publishing to expensify's private index
24+
"Private :: pyx :: expensify",
25+
]
26+
27+
[project.scripts]
28+
fab = "fabric.main:main"
29+
30+
[build-system]
31+
# We don't specify a specific version of uv_build because the below constraints allow
32+
# uv to use the version bundled with uv instead of having to install a standalone
33+
# package to build with. `uv` and all of astral's products use semantic versioning
34+
# so by requiring anything less than the next minor version means we won't get
35+
# any breaking changes automatically but we will get bug fixes and improvements.
36+
# If the bundled version is outside of these constraints, uv will auto download
37+
# a compatible version.
38+
requires = ["uv_build>=0.9.17,<0.10.0"]
39+
build-backend = "uv_build"
40+
41+
[tool.uv.build-backend]
42+
module-name = ["fabric"]
43+
module-root = ""
44+
45+
[[tool.uv.index]]
46+
name = "expensify"
47+
url = "https://api.pyx.dev/simple/expensify/main"
48+
publish-url = "https://api.pyx.dev/v1/upload/expensify/main"
49+
50+
# This makes it so that uv will only use the expensify index for
51+
# any package that is listed in the sources section below. All others
52+
# will be pulled from the default index (pypi)
53+
explicit = true
54+
55+
[tool.uv.sources]
56+
fudge = { git = "https://github.com/ploxiln/fudge", branch = "py3" }
57+
58+
[dependency-groups]
59+
dev = [
60+
"flake8==7.3.0 ; python_full_version >= '3.9'",
61+
"fudge",
62+
"jinja2<4.0",
63+
"nose-py3>=1.9.0",
64+
]
65+
doc = [
66+
"alabaster==0.7.12",
67+
"docutils==0.16",
68+
"markupsafe==1.1.1",
69+
"pygments==2.7.4",
70+
"releases==1.6.3",
71+
"semantic-version==2.6.0",
72+
"sphinx==1.8.5",
73+
]
74+

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
long_description = open("README.rst").read()
99

1010
# set PARAMIKO_REPLACE=1 to require "paramiko" instead of "paramiko-ng"
11-
paramiko = 'paramiko' if os.environ.get('PARAMIKO_REPLACE') else 'paramiko-ng'
11+
# FORKED FROM MAIN: we are hard coding this to paramiko because paramiko-ng
12+
# is broken -- see https://github.com/ploxiln/paramiko-ng/issues/130 and
13+
# https://github.com/ploxiln/paramiko-ng/pull/149
14+
paramiko = 'paramiko' # if os.environ.get('PARAMIKO_REPLACE') else 'paramiko-ng'
1215

1316
setup(
1417
name='fab-classic',

0 commit comments

Comments
 (0)