-
Notifications
You must be signed in to change notification settings - Fork 0
146 lines (136 loc) · 6.15 KB
/
Copy pathrelease-ecosystems.yml
File metadata and controls
146 lines (136 loc) · 6.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
name: Release (composer + RubyGems CLI)
# Separate release for distributing the `socket-patch` CLI on the composer and
# RubyGems ecosystems. Decoupled from the main `release.yml`: these are thin
# launcher packages that download the prebuilt binary from the GitHub release at
# their own version, so they only need that release (and its `SHA256SUMS`) to
# already exist. Runs automatically once the main release publishes, or manually
# for a given version.
#
# Required secrets (each publish step skips gracefully when its secret is
# absent, so this workflow is safe to land before credentials are wired):
# - RUBYGEMS_API_KEY — a RubyGems API key with push scope for `socket-patch`
# - PACKAGIST_USERNAME / PACKAGIST_TOKEN — Packagist API credentials
# Preferred hardening: RubyGems / Packagist trusted publishing (OIDC) instead of
# long-lived keys, mirroring the crates.io / PyPI jobs in release.yml.
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to publish (no leading v), e.g. 3.3.0'
required: true
type: string
permissions: {}
jobs:
resolve-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.v.outputs.VERSION }}
tag: ${{ steps.v.outputs.TAG }}
steps:
- name: Resolve version + tag
id: v
# Pass event/input data through env (never interpolate `${{ ... }}`
# directly into the shell) to avoid template-injection (zizmor).
env:
EVENT_NAME: ${{ github.event_name }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
INPUT_VERSION: ${{ inputs.version }}
run: |
if [ "$EVENT_NAME" = "release" ]; then
TAG="$RELEASE_TAG"
else
TAG="v${INPUT_VERSION}"
fi
VERSION="${TAG#v}"
echo "TAG=$TAG" >> "$GITHUB_OUTPUT"
echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing CLI launcher packages for $TAG"
rubygems-cli:
needs: resolve-version
runs-on: ubuntu-latest
# Scope the publish secret to a deployment environment (zizmor
# secrets-outside-env); also lets a maintainer gate publishing with required
# reviewers. Auto-created with no protection rules until configured.
environment: rubygems
permissions:
contents: read
steps:
- name: Checkout (at the release tag)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.resolve-version.outputs.tag }}
persist-credentials: false
# Ruby is pre-installed on ubuntu-latest; no setup action needed.
- name: Lint + build the launcher gem
working-directory: gem/socket-patch
env:
EXPECTED_VERSION: ${{ needs.resolve-version.outputs.version }}
run: |
ruby -c lib/socket_patch/launcher.rb
ruby -c exe/socket-patch
# The gemspec version is baked at the tag by scripts/version-sync.sh.
gemver="$(ruby -e 'print Gem::Specification.load("socket-patch.gemspec").version')"
if [ "$gemver" != "$EXPECTED_VERSION" ]; then
echo "::error::gemspec version $gemver != release $EXPECTED_VERSION (run scripts/version-sync.sh before tagging)"
exit 1
fi
gem build socket-patch.gemspec
- name: Publish socket-patch to RubyGems
working-directory: gem/socket-patch
# zizmor: ignore[use-trusted-publishing]
# Uses an API key for now; RubyGems trusted publishing (OIDC) is the
# documented future hardening (see the header), mirroring the crates.io
# / PyPI jobs. Suppressed until that publisher is registered.
env:
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
VERSION: ${{ needs.resolve-version.outputs.version }}
run: |
if [ -z "${GEM_HOST_API_KEY}" ]; then
echo "::notice title=RubyGems publish skipped::RUBYGEMS_API_KEY not set; built the gem but did not push."
exit 0
fi
# `gem list -r -e -a` prints `socket-patch (3.3.0, 3.2.0, ...)`; match
# this version as a precise list element (preceded by `(`/space,
# followed by `,`/`)`).
if gem list --remote --exact --all socket-patch 2>/dev/null | grep -qE "[ (]${VERSION}[,)]"; then
echo "socket-patch ${VERSION} already on RubyGems; skipping."
exit 0
fi
gem push "socket-patch-${VERSION}.gem"
packagist-cli:
needs: resolve-version
runs-on: ubuntu-latest
# Scope the Packagist secrets to a deployment environment (zizmor
# secrets-outside-env); auto-created with no protection until configured.
environment: packagist
permissions:
contents: read
steps:
- name: Checkout (at the release tag)
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.resolve-version.outputs.tag }}
persist-credentials: false
# PHP + composer are pre-installed on ubuntu-latest.
- name: Lint launcher + validate composer.json
working-directory: composer/socket-patch
run: |
php -l bin/socket-patch
composer validate --no-check-publish
# Packagist is git-tag-driven: it ingests the tagged composer.json on its
# own (typically via a repo webhook). This step nudges its update API so
# the new tag is picked up promptly; without credentials it is a no-op.
- name: Notify Packagist of the new tag
env:
PACKAGIST_USERNAME: ${{ secrets.PACKAGIST_USERNAME }}
PACKAGIST_TOKEN: ${{ secrets.PACKAGIST_TOKEN }}
run: |
if [ -z "${PACKAGIST_USERNAME}" ] || [ -z "${PACKAGIST_TOKEN}" ]; then
echo "::notice title=Packagist sync skipped::PACKAGIST_USERNAME/PACKAGIST_TOKEN not set; Packagist will sync via its repo webhook."
exit 0
fi
curl -fsSL -XPOST -H 'content-type:application/json' \
"https://packagist.org/api/update-package?username=${PACKAGIST_USERNAME}&apiToken=${PACKAGIST_TOKEN}" \
-d '{"repository":{"url":"https://github.com/SocketDev/socket-patch"}}'