Skip to content

Commit 8551d98

Browse files
committed
Setup minimal CI
1 parent 30b53ab commit 8551d98

2 files changed

Lines changed: 267 additions & 0 deletions

File tree

.github/workflows/docker.yaml

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
name: Build and push Docker image
2+
3+
on:
4+
push:
5+
branches: ["main", "release"]
6+
7+
jobs:
8+
docker:
9+
name: Build and push Docker image
10+
runs-on: ubuntu-latest
11+
env:
12+
AWS_REGION: us-east-1
13+
ECR_REGISTRY: 336594912921.dkr.ecr.us-east-1.amazonaws.com
14+
APP_NAME: rpc-proxy
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # needed for git describe to find tags
20+
21+
- name: Configure AWS credentials
22+
uses: aws-actions/configure-aws-credentials@v4
23+
with:
24+
aws-access-key-id: ${{ secrets.ECR_AWS_ACCESS_KEY_ID }}
25+
aws-secret-access-key: ${{ secrets.ECR_AWS_SECRET_ACCESS_KEY }}
26+
aws-region: ${{ env.AWS_REGION }}
27+
28+
- name: Login to Amazon ECR
29+
id: login-ecr
30+
uses: aws-actions/amazon-ecr-login@v2
31+
32+
- name: Set image metadata
33+
id: meta
34+
run: |
35+
SHORT_SHA=${GITHUB_SHA:0:7}
36+
# Derive version from the nearest upstream tag (e.g. 0.0.62-2-g2fe6ca3)
37+
BASE_VERSION=$(git describe --tags --always)
38+
VERSION="custom-${BASE_VERSION}"
39+
if [[ "$GITHUB_REF_NAME" == "main" ]]; then
40+
TAGS="dev latest"
41+
DEPLOYMENT_ENV="dev"
42+
elif [[ "$GITHUB_REF_NAME" == "release" ]]; then
43+
TAGS="prod"
44+
DEPLOYMENT_ENV="prod"
45+
else
46+
# Use branch name as tag, sanitized for Docker tag format
47+
TAGS=$(echo "$GITHUB_REF_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g')
48+
DEPLOYMENT_ENV=""
49+
fi
50+
# Build full Docker tags (registry/app:tag) for each tag + short SHA
51+
DOCKER_TAGS=""
52+
for T in $TAGS $SHORT_SHA; do
53+
DOCKER_TAGS="${DOCKER_TAGS}${ECR_REGISTRY}/${APP_NAME}:${T}"$'\n'
54+
done
55+
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
56+
echo "tags=$TAGS" >> "$GITHUB_OUTPUT"
57+
echo "deployment_env=$DEPLOYMENT_ENV" >> "$GITHUB_OUTPUT"
58+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
59+
echo "docker_tags<<EOF" >> "$GITHUB_OUTPUT"
60+
echo "$DOCKER_TAGS" >> "$GITHUB_OUTPUT"
61+
echo "EOF" >> "$GITHUB_OUTPUT"
62+
echo "Image version: $VERSION (tags: $TAGS)"
63+
64+
- name: Set up Docker Buildx
65+
uses: docker/setup-buildx-action@v3
66+
67+
- name: Build and push image
68+
uses: docker/build-push-action@v6
69+
with:
70+
context: .
71+
push: true
72+
tags: ${{ steps.meta.outputs.docker_tags }}
73+
build-args: |
74+
VERSION=${{ steps.meta.outputs.version }}
75+
COMMIT_SHA=${{ steps.meta.outputs.short_sha }}
76+
cache-from: type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.APP_NAME }}:cache
77+
cache-to: type=registry,ref=${{ env.ECR_REGISTRY }}/${{ env.APP_NAME }}:cache,mode=max
78+
79+
- name: Promote image via infra workflow
80+
if: ${{ steps.meta.outputs.deployment_env != '' }}
81+
env:
82+
GH_TOKEN: ${{ secrets.INFRA_WORKFLOW_PAT }}
83+
GH_WORKFLOW_OWNER: rhinestonewtf
84+
GH_WORKFLOW_REPO: infra
85+
WORKFLOW_FILE: aws-promote-app-version.yaml
86+
DEPLOYMENT_ENV: ${{ steps.meta.outputs.deployment_env }}
87+
SHORT_SHA: ${{ steps.meta.outputs.short_sha }}
88+
run: |
89+
set -euo pipefail
90+
91+
if [[ -z "${GH_TOKEN:-}" ]]; then
92+
echo "INFRA_WORKFLOW_PAT secret is not configured" >&2
93+
exit 1
94+
fi
95+
96+
TARGET_REF="main"
97+
WORKFLOW_PATH=".github/workflows/$WORKFLOW_FILE"
98+
99+
WORKFLOW_METADATA=$(gh api repos/$GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO/actions/workflows/$WORKFLOW_FILE)
100+
WORKFLOW_ID=$(echo "$WORKFLOW_METADATA" | jq -r '.id // empty')
101+
102+
if [[ -z "$WORKFLOW_ID" ]]; then
103+
echo "Unable to resolve workflow id for $WORKFLOW_PATH" >&2
104+
exit 1
105+
fi
106+
107+
echo "Dispatching $WORKFLOW_FILE (id: $WORKFLOW_ID) in $GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO for env $DEPLOYMENT_ENV (version $SHORT_SHA)"
108+
109+
API_ROOT="https://api.github.com"
110+
DISPATCH_URL="$API_ROOT/repos/$GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO/actions/workflows/$WORKFLOW_FILE/dispatches"
111+
AUTH_HEADER=(
112+
-H "Authorization: Bearer $GH_TOKEN"
113+
-H "Accept: application/vnd.github+json"
114+
-H "Content-Type: application/json"
115+
)
116+
117+
DISPATCH_BODY=$(jq -n \
118+
--arg ref "$TARGET_REF" \
119+
--arg env "$DEPLOYMENT_ENV" \
120+
--arg app "$APP_NAME" \
121+
--arg sha "$SHORT_SHA" \
122+
'{ref: $ref, inputs: {env: $env, app_name: $app, version_sha: $sha}}')
123+
124+
DISPATCH_STATUS=$(curl -sS -o /tmp/dispatch.json -w "%{http_code}" "${AUTH_HEADER[@]}" \
125+
-X POST "$DISPATCH_URL" \
126+
-d "$DISPATCH_BODY")
127+
128+
if [[ "$DISPATCH_STATUS" -ge 300 ]]; then
129+
echo "Failed to dispatch remote workflow (status $DISPATCH_STATUS)" >&2
130+
cat /tmp/dispatch.json >&2 || true
131+
exit 1
132+
fi
133+
134+
echo "Awaiting workflow run to be created..."
135+
sleep 10
136+
137+
RUN_ID=$(gh api https://api.github.com/repos/$GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO/actions/runs --jq '[.workflow_runs[] | select(.event == "workflow_dispatch")][0].id' | sed 's/\x1b\[[0-9;]*m//g')
138+
echo "Run ID: $RUN_ID"
139+
140+
if [[ -z "$RUN_ID" ]]; then
141+
echo "Failed to find the dispatched workflow run" >&2
142+
exit 1
143+
fi
144+
145+
gh run watch "$RUN_ID" --repo $GH_WORKFLOW_OWNER/$GH_WORKFLOW_REPO --exit-status --compact --interval 15
146+
147+
- name: Notify Slack of deployment
148+
if: ${{ success() && steps.meta.outputs.deployment_env != '' }}
149+
env:
150+
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
151+
run: |
152+
if [[ -z "${SLACK_WEBHOOK:-}" ]]; then
153+
echo "SLACK_WEBHOOK secret is not configured" >&2
154+
exit 1
155+
fi
156+
157+
MESSAGE=$(jq -n \
158+
--arg text ":rocket: App *${{ env.APP_NAME }}* is live on *${{ steps.meta.outputs.deployment_env }}* version: *${{ steps.meta.outputs.short_sha }}*" \
159+
'{text: $text}')
160+
161+
curl -sSf -X POST -H 'Content-type: application/json' --data "$MESSAGE" "$SLACK_WEBHOOK"

sync-with-upstream.sh

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
UPSTREAM_REMOTE="upstream"
5+
UPSTREAM_URL="https://github.com/erpc/erpc"
6+
ORIGIN_REMOTE="origin"
7+
BRANCH="main"
8+
9+
usage() {
10+
echo "Usage: $0 <tag-or-branch>"
11+
echo ""
12+
echo "Syncs the fork with an upstream release tag or branch."
13+
echo " 1. Ensures upstream remote exists"
14+
echo " 2. Fetches the ref from upstream"
15+
echo " 3. Rebases our commits on top of it"
16+
echo " 4. Pushes main branch (and the tag, if applicable) to origin"
17+
echo ""
18+
echo "Examples:"
19+
echo " $0 0.0.63 # sync to a release tag"
20+
echo " $0 main # sync to upstream main branch"
21+
exit 1
22+
}
23+
24+
if [[ $# -ne 1 ]]; then
25+
usage
26+
fi
27+
28+
REF="$1"
29+
30+
# Ensure we're on the right branch
31+
CURRENT_BRANCH=$(git branch --show-current)
32+
if [[ "$CURRENT_BRANCH" != "$BRANCH" ]]; then
33+
echo "Error: must be on '$BRANCH' branch (currently on '$CURRENT_BRANCH')"
34+
exit 1
35+
fi
36+
37+
# Ensure working tree is clean (tracked changes + untracked files)
38+
if ! git diff --quiet || ! git diff --cached --quiet || [[ -n "$(git ls-files --others --exclude-standard)" ]]; then
39+
echo "Error: working tree is not clean. Commit or stash changes first."
40+
git status --short
41+
exit 1
42+
fi
43+
44+
# Ensure upstream remote exists
45+
if ! git remote get-url "$UPSTREAM_REMOTE" &>/dev/null; then
46+
echo "Adding upstream remote: $UPSTREAM_URL"
47+
git remote add "$UPSTREAM_REMOTE" "$UPSTREAM_URL"
48+
fi
49+
50+
# Determine if REF is a tag or a branch
51+
IS_TAG=false
52+
if git ls-remote --tags "$UPSTREAM_REMOTE" "$REF" | grep -q "$REF"; then
53+
IS_TAG=true
54+
fi
55+
56+
# Fetch from upstream
57+
if $IS_TAG; then
58+
echo "Fetching tag '$REF' from upstream..."
59+
git fetch "$UPSTREAM_REMOTE" "refs/tags/$REF:refs/tags/$REF"
60+
REBASE_TARGET="$REF"
61+
else
62+
echo "Fetching branch '$REF' from upstream..."
63+
git fetch "$UPSTREAM_REMOTE" "$REF"
64+
REBASE_TARGET="$UPSTREAM_REMOTE/$REF"
65+
fi
66+
67+
# Verify the target exists
68+
if ! git rev-parse "$REBASE_TARGET" &>/dev/null; then
69+
echo "Error: '$REBASE_TARGET' not found after fetch"
70+
exit 1
71+
fi
72+
73+
# Show what will be rebased
74+
CUSTOM_COMMITS=$(git log --oneline "$REBASE_TARGET"..HEAD 2>/dev/null || true)
75+
if [[ -z "$CUSTOM_COMMITS" ]]; then
76+
echo "No custom commits to rebase — already up to date with '$REF'"
77+
exit 0
78+
fi
79+
80+
echo ""
81+
echo "Custom commits to rebase on top of '$REF' ($(git rev-parse --short "$REBASE_TARGET")):"
82+
echo "$CUSTOM_COMMITS"
83+
echo ""
84+
read -rp "Proceed with rebase? [y/N] " confirm
85+
if [[ "$confirm" != [yY] ]]; then
86+
echo "Aborted."
87+
exit 1
88+
fi
89+
90+
# Rebase our commits on top of the target
91+
echo "Rebasing on top of '$REBASE_TARGET'..."
92+
git rebase "$REBASE_TARGET"
93+
94+
# Push updated branch to origin
95+
echo "Pushing '$BRANCH' branch to origin..."
96+
git push "$ORIGIN_REMOTE" "$BRANCH" --force-with-lease
97+
98+
# Push the tag to origin if applicable
99+
if $IS_TAG; then
100+
echo "Pushing tag '$REF' to origin..."
101+
git push "$ORIGIN_REMOTE" "refs/tags/$REF"
102+
fi
103+
104+
echo ""
105+
echo "Done! Branch '$BRANCH' rebased on '$REF' and pushed to origin."
106+
echo "Version will be: custom-$(git describe --tags --always)"

0 commit comments

Comments
 (0)