This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-actions.git


The following commit(s) were added to refs/heads/main by this push:
     new bbbae99  Add the action to upload to ATR, and documentation
bbbae99 is described below

commit bbbae990619d9296492e3c236a04616569e21761
Author: Sean B. Palmer <[email protected]>
AuthorDate: Fri Aug 22 15:27:15 2025 +0100

    Add the action to upload to ATR, and documentation
---
 upload-to-atr/README.md  | 60 +++++++++++++++++++++++++++++++++++++++++
 upload-to-atr/action.yml | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 130 insertions(+)

diff --git a/upload-to-atr/README.md b/upload-to-atr/README.md
new file mode 100644
index 0000000..d3973bf
--- /dev/null
+++ b/upload-to-atr/README.md
@@ -0,0 +1,60 @@
+### Upload to ATR with GitHub OIDC and rsync
+
+This composite GitHub Action exchanges a GitHub OIDC token for an ATR JWT, 
registers a short lived SSH key, and rsyncs a local directory to ATR at 
`/<project>/<version>/`. Use it to publish build artifacts to ATR without long 
lived credentials.
+
+### Inputs
+
+- **asf-uid (required)**: Your ASF UID used for SSH login.
+- **project (required)**: Project name segment in the remote path.
+- **version (required)**: Version segment in the remote path.
+- **src**: Local directory to upload. Default: `dist`. A trailing slash will 
be added automatically if omitted.
+- **audience**: OIDC audience for the JWT request. Default: `atr-test`.
+- **atr-host**: ATR host to upload to. Default: `release-test.apache.org`.
+- **ssh-port**: SSH port on ATR. Default: `2222`.
+- **rsync-args**: Arguments passed to `rsync`. Default: `-av`.
+
+### Example workflow
+
+The `id-token` write permission is **required** when using this GitHub Action.
+
+```yaml
+name: Upload to ATR
+
+on:
+  workflow_dispatch:
+
+jobs:
+  upload:
+    permissions:
+      id-token: write
+      contents: read
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Build artifacts
+        run: |
+          ./build.sh
+
+      - name: Upload to ATR
+        uses: apache/tooling-actions/upload-to-atr@v1
+        with:
+          asf-uid: ${{ secrets.ASF_UID }}
+          project: my-project
+          version: ${{ github.ref_name }}
+          src: dist
+          audience: atr-test
+          atr-host: release-test.apache.org
+          ssh-port: '2222'
+          rsync-args: -av
+```
+
+### Further details
+
+The job must grant `id-token: write` so that this action can request a GitHub 
OIDC token.
+
+This action generates an ephemeral Ed25519 SSH key, registers its public key 
with ATR using the GitHub JWT, which is checked used JWKS, and discards the key 
after the job. SSH uses `StrictHostKeyChecking=accept-new` so that the host key 
is learned on first connection.
+
+The remote path is `/<project>/<version>/`. The contents of `src` are synced 
to ATR. ATR will create a new revision of the project with the synced files. If 
`rsync` is missing on the runner, this action installs it.
+
+You should not adjust `rsync-args`, as ATR is very strict about which rsync 
arguments it accepts.
diff --git a/upload-to-atr/action.yml b/upload-to-atr/action.yml
new file mode 100644
index 0000000..28e4be2
--- /dev/null
+++ b/upload-to-atr/action.yml
@@ -0,0 +1,70 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: "Upload to ATR using GitHub OIDC and rsync"
+description: "Create a GitHub OIDC JWT, register an SSH key, then rsync a 
directory to ATR."
+branding: {icon: upload-cloud, color: blue}
+
+inputs:
+  asf-uid: {description: "ASF UID", required: true}
+  project: {description: "Project", required: true}
+  version: {description: "Version", required: true}
+  src: {description: "Local directory", default: "dist"}
+  audience: {description: "OIDC audience", default: "atr-test"}
+  atr-host: {description: "ATR host", default: "release-test.apache.org"}
+  ssh-port: {description: "SSH port", default: "2222"}
+  rsync-args: {description: "Arguments for rsync", default: "-av"}
+
+runs:
+  using: "composite"
+  steps:
+    - name: Create a GitHub OIDC JWT
+      shell: bash
+      run: |
+        set -euxo pipefail
+        url="${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${{ inputs.audience }}"
+        jwt="$(curl -sS -H "Authorization: bearer 
${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "$url" \
+             | python3 -c 'import json, sys; 
print(json.load(sys.stdin)["value"])')"
+        echo "::add-mask::$jwt"
+        echo "JWT=$jwt" >> "$GITHUB_ENV"
+
+    - name: Generate an ephemeral SSH key
+      shell: bash
+      run: |
+        set -euxo pipefail
+        ssh-keygen -t ed25519 -N "" -f "$RUNNER_TEMP/ssh_key"
+        echo "SSH_PRIVATE_KEY_PATH=$RUNNER_TEMP/ssh_key" >> "$GITHUB_ENV"
+        echo "SSH_PUBLIC_KEY=$(cat "$RUNNER_TEMP/ssh_key.pub")" >> 
"$GITHUB_ENV"
+
+    - name: Register the ephemeral SSH key with ATR
+      shell: bash
+      run: |
+        set -euxo pipefail
+        curl -sS -X POST -H "Content-Type: application/json" \
+          -d "{\"jwt\":\"$JWT\",\"ssh_key\":\"$SSH_PUBLIC_KEY\"}" \
+          "https://${{ inputs.atr-host }}/api/jwt/github"
+
+    - name: Upload to ATR using rsync
+      shell: bash
+      run: |
+        set -euxo pipefail
+        command -v rsync > /dev/null || { sudo apt-get update -y && sudo 
apt-get install -y rsync; }
+        src="${{ inputs.src }}"
+        case "$src" in */) ;; *) src="$src/";; esac
+        rsync ${{ inputs.rsync-args }} \
+          -e "ssh -p ${{ inputs.ssh-port }} -i $SSH_PRIVATE_KEY_PATH -o 
StrictHostKeyChecking=accept-new" \
+          "$src" "${{ inputs.asf-uid }}@${{ inputs.atr-host }}:/${{ 
inputs.project }}/${{ inputs.version }}/"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to