-
Notifications
You must be signed in to change notification settings - Fork 56
195 lines (166 loc) · 8.22 KB
/
release-integrations.yml
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
name: Release integrations
on:
push:
branches:
- main
workflow_dispatch:
jobs:
prepare-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.prepare-matrix.outputs.INTEGRATIONS_MATRIX }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Prepare matrix
id: prepare-matrix
run: |
integrations_to_release=()
# Get the list of integrations
files=$(find integrations/*/.port -name "spec.yaml")
for file in $files; do
folder=$(dirname "$file")
type=$(grep -E '^name = ".*"' "$folder/../pyproject.toml" | cut -d'"' -f2)
# Get the version from pyproject.toml
version=$(grep -E '^version = ".*"' "$folder/../pyproject.toml" | cut -d'"' -f2)
# Check if the version exists in the ghcr.io registry
rc=0
docker manifest inspect ghcr.io/port-labs/port-ocean-$type:$version > /dev/null 2>&1 || rc=$?
if [ $rc -eq 0 ]; then
echo "Image already exists in $repository: port-ocean-$type:$version"
else
integrations_to_release+=($file)
fi
done
echo $(echo ${integrations_to_release[@]} | jq -R -c 'split(" ")')
echo "INTEGRATIONS_MATRIX=$(echo ${integrations_to_release[@]} | jq -R -c 'split(" ")')" >> $GITHUB_OUTPUT
release-integration:
runs-on: ubuntu-latest
if: needs.prepare-matrix.outputs.matrix != '[]'
outputs:
is_dev_version: ${{ steps.prepare_tags.outputs.is_dev_version }}
permissions:
packages: write
contents: read
needs: [prepare-matrix]
strategy:
# limit the number of parallel jobs to avoid hitting the ghcr.io rate limit
max-parallel: 5
matrix:
integration: ${{fromJson(needs.prepare-matrix.outputs.matrix)}}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Prepare Docker images tags
id: prepare_tags
run: |
current_integration_spec=${{ matrix.integration }}
folder=$(dirname "$current_integration_spec")
context_dir=$(dirname "$folder")
echo "context_dir=$context_dir" >> $GITHUB_OUTPUT
version=$(grep -E '^version = ".*"' "$folder/../pyproject.toml" | cut -d'"' -f2)
type=$(grep -E '^name = ".*"' "$folder/../pyproject.toml" | cut -d'"' -f2)
echo "version=$version" >> $GITHUB_OUTPUT
dockerfile_path=integrations/_infra/Dockerfile
if test -e $folder/../Dockerfile; then
dockerfile_path=$folder/../Dockerfile
fi
echo "dockerfile_path=$dockerfile_path" >> $GITHUB_OUTPUT
# Check if the 'version' variable contains any character other than digits and "."
if [[ ! "$version" =~ ^[0-9.]+$ ]]; then
# If 'version' contains non-numeric and non-dot characters, skip building 'latest' tag
tags="ghcr.io/port-labs/port-ocean-$type:$version"
echo "tags=$tags" >> $GITHUB_OUTPUT
echo "is_dev_version=true" >> $GITHUB_OUTPUT
echo "Version contains non-numeric characters. Building without 'latest' tag."
else
# If 'version' contains only digits and dots, build with both 'latest' and version tags
tags="ghcr.io/port-labs/port-ocean-$type:$version,ghcr.io/port-labs/port-ocean-$type:latest"
echo "tags=$tags" >> $GITHUB_OUTPUT
echo "is_dev_version=false" >> $GITHUB_OUTPUT
fi
- name: Build Docker Image
uses: ./.github/workflows/actions/build-docker-image
with:
dockerfile: ${{ steps.prepare_tags.outputs.dockerfile_path }}
platforms: linux/amd64,linux/arm64
tags: ${{ steps.prepare_tags.outputs.tags }}
build-args: |
BUILD_CONTEXT=${{ steps.prepare_tags.outputs.context_dir }}
INTEGRATION_VERSION=${{ steps.prepare_tags.outputs.version }}
docker-user: ${{ secrets.DOCKER_MACHINE_USER }}
docker-password: ${{ secrets.DOCKER_MACHINE_TOKEN }}
upload-specs:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
needs: release-integration
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Configure AWS Credentials 🔒
id: aws-credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Upload specifications to s3
run: |
# Temporary file
temp_file="temp.yaml"
# Output file name
index_file="index.json"
# AWS S3 bucket details
aws_s3_bucket="ocean-registry"
# Fetch existing index file or create empty one of not exists
if aws s3 ls "s3://$aws_s3_bucket/$index_file" >/dev/null 2>&1; then
aws s3 cp "s3://$aws_s3_bucket/$index_file" $index_file
echo "Successfully fetched global index file from s3 bucket."
else
echo "Index file does not exist in the S3 bucket, Creating new one..."
echo "[]" >"$index_file"
fi
# Find all ocean-spec.yaml files under the specified directory
find integrations/*/.port -type f -name "spec.yaml" >file_list.txt
while IFS= read -r file; do
integration_dir=$(dirname "$file")
integration_name=$(echo "$integration_dir" | awk -F'/' '{print $2}')
# Extract the type for pyproject.toml
type=$(grep -E '^name = ".*"' "$integration_dir/../pyproject.toml" | cut -d'"' -f2)
# Extract the version from pyproject.toml
version=$(grep -E '^version = ".*"' "$integration_dir/../pyproject.toml" | cut -d'"' -f2)
integration_spec="$integration_name-$version.json"
integration_dest="$integration_name/$integration_spec"
integration_legacy_dest="$integration_name.json" # TODO: legacy support, remove once not in use
# Convert YAML to JSON
yq -o json "$file" >"$temp_file"
# Add version attribute
jq --arg type "$type" --arg version "$version" '. + {type: $type, version: $version}' "$temp_file" >"$integration_spec"
if [[ ! ${version} =~ ^.+-dev$ ]]; then
# Upload integration's version manifest to s3
aws s3 cp "$integration_spec" "s3://$aws_s3_bucket/$integration_dest"
aws s3 cp "$integration_spec" "s3://$aws_s3_bucket/$integration_legacy_dest" # TODO: legacy support, remove once not in use
echo "Successfully uploaded $integration_spec to s3 bucket."
# Get the latest version of the current integration
latest_version=$(jq --arg type "$type" -r '.[] | select(.type == $type) | .version' "$index_file")
# Add integration's spec to global index file
regexp="^[0-9.]+$"
if [[ ! "$latest_version" ]]; then
# Add new integration spec if latest tag doesn't exist
jq --argjson new_spec "[$(cat "$integration_spec")]" '. += $new_spec' "$index_file" >"$temp_file"
mv "$temp_file" "$index_file"
elif [[ ! "$latest_version" =~ $regexp ]] || [[ "$version" =~ $regexp ]]; then
# Override global index file if released non-dev version or integration doesn't have non-dev latest tag
jq --argjson updated_spec "$(cat "$integration_spec")" --arg type "$type" \
'map(if .type == $type then $updated_spec else . end)' "$index_file" >"$temp_file"
mv "$temp_file" "$index_file"
fi
# Upload global index file to s3
aws s3 cp "$index_file" "s3://$aws_s3_bucket/$index_file"
echo "Successfully uploaded $index_file to s3 bucket."
else
echo "Did not upload integration spec since the version was in development ('${version}')"
fi
done <file_list.txt