mirror of
https://github.com/google/nomulus
synced 2026-08-07 15:56:08 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3474cd6e9b | ||
|
|
1fc4a281c0 | ||
|
|
9a420a69b0 | ||
|
|
a3421f2999 | ||
|
|
72c610688a |
@@ -28,6 +28,9 @@ import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.monitoring.metrics.IncrementableMetric;
|
||||
import com.google.monitoring.metrics.LabelDescriptor;
|
||||
import com.google.monitoring.metrics.MetricRegistryImpl;
|
||||
import google.registry.cache.SimplifiedJedisClient;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.common.Cursor;
|
||||
@@ -39,6 +42,7 @@ import google.registry.request.Action;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.request.lock.LockHandler;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
@@ -61,6 +65,25 @@ public class SyncRemoteCacheAction implements Runnable {
|
||||
private static final String LOCK_NAME = "syncRemoteCacheAction";
|
||||
private static final int BATCH_SIZE = 10000;
|
||||
|
||||
public enum SyncStatus {
|
||||
SUCCESS,
|
||||
FAILURE,
|
||||
NOT_CONFIGURED
|
||||
}
|
||||
|
||||
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS =
|
||||
ImmutableSet.of(
|
||||
LabelDescriptor.create("status", "Whether SyncRemoteCacheAction succeeded or failed."));
|
||||
|
||||
@NonFinalForTesting
|
||||
static final IncrementableMetric SYNC_CACHE_RUNS_METRIC =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newIncrementableMetric(
|
||||
"/batch/sync_remote_cache/runs",
|
||||
"Count of SyncRemoteCacheAction executions",
|
||||
"count",
|
||||
LABEL_DESCRIPTORS);
|
||||
|
||||
private final LockHandler lockHandler;
|
||||
private final Response response;
|
||||
private final Optional<SimplifiedJedisClient> jedisClient;
|
||||
@@ -79,14 +102,17 @@ public class SyncRemoteCacheAction implements Runnable {
|
||||
if (jedisClient.isEmpty()) {
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload("No Jedis/Valkey configuration found");
|
||||
SYNC_CACHE_RUNS_METRIC.increment(SyncStatus.NOT_CONFIGURED.name());
|
||||
return;
|
||||
}
|
||||
Callable<Void> runner =
|
||||
() -> {
|
||||
try {
|
||||
runLocked();
|
||||
SYNC_CACHE_RUNS_METRIC.increment(SyncStatus.SUCCESS.name());
|
||||
response.setStatus(SC_OK);
|
||||
} catch (Exception e) {
|
||||
SYNC_CACHE_RUNS_METRIC.increment(SyncStatus.FAILURE.name());
|
||||
logger.atSevere().withCause(e).log("Errored out during execution.");
|
||||
response.setStatus(SC_INTERNAL_SERVER_ERROR);
|
||||
response.setPayload(String.format("Errored out with cause: %s", e));
|
||||
@@ -95,6 +121,7 @@ public class SyncRemoteCacheAction implements Runnable {
|
||||
};
|
||||
|
||||
if (!lockHandler.executeWithLocks(runner, null, Duration.ofHours(1), LOCK_NAME)) {
|
||||
SYNC_CACHE_RUNS_METRIC.increment(SyncStatus.FAILURE.name());
|
||||
// Send a 200-series status code to prevent this conflicting action from retrying.
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload("Could not acquire lock; already running?");
|
||||
|
||||
@@ -14,14 +14,18 @@
|
||||
|
||||
package google.registry.dns;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.dns.DnsUtils.requestDomainDnsRefresh;
|
||||
import static google.registry.dns.RefreshDnsOnHostRenameAction.PATH;
|
||||
import static google.registry.model.EppResourceUtils.getLinkedDomainKeys;
|
||||
import static google.registry.model.EppResourceUtils.isDeleted;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.model.EppResourceUtils;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.VKey;
|
||||
@@ -29,8 +33,11 @@ import google.registry.request.Action;
|
||||
import google.registry.request.Parameter;
|
||||
import google.registry.request.Response;
|
||||
import google.registry.request.auth.Auth;
|
||||
import google.registry.util.Clock;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Action(
|
||||
service = Action.Service.BACKEND,
|
||||
@@ -43,45 +50,52 @@ public class RefreshDnsOnHostRenameAction implements Runnable {
|
||||
public static final String PARAM_HOST_KEY = "hostKey";
|
||||
public static final String PATH = "/_dr/task/refreshDnsOnHostRename";
|
||||
|
||||
private static final int DNS_REFRESH_BATCH_SIZE = 1000;
|
||||
|
||||
private final VKey<Host> hostKey;
|
||||
private final Response response;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
RefreshDnsOnHostRenameAction(@Parameter(PARAM_HOST_KEY) String hostKey, Response response) {
|
||||
RefreshDnsOnHostRenameAction(
|
||||
@Parameter(PARAM_HOST_KEY) String hostKey, Response response, Clock clock) {
|
||||
this.hostKey = VKey.createEppVKeyFromString(hostKey);
|
||||
this.response = response;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
tm().transact(
|
||||
() -> {
|
||||
Instant now = tm().getTxTime();
|
||||
Host host = tm().loadByKeyIfPresent(hostKey).orElse(null);
|
||||
boolean hostValid = true;
|
||||
String failureMessage = null;
|
||||
if (host == null) {
|
||||
hostValid = false;
|
||||
failureMessage = String.format("Host to refresh does not exist: %s", hostKey);
|
||||
} else if (EppResourceUtils.isDeleted(host, now)) {
|
||||
hostValid = false;
|
||||
failureMessage =
|
||||
String.format("Host to refresh is already deleted: %s", host.getHostName());
|
||||
} else {
|
||||
getLinkedDomainKeys(
|
||||
host.createVKey(), host.getUpdateTimestamp().getTimestamp(), null)
|
||||
.stream()
|
||||
.map(domainKey -> tm().loadByKey(domainKey))
|
||||
.filter(Domain::shouldPublishToDns)
|
||||
.forEach(domain -> requestDomainDnsRefresh(domain.getDomainName()));
|
||||
}
|
||||
Optional<Host> optionalHost = tm().transact(() -> tm().loadByKeyIfPresent(hostKey));
|
||||
if (optionalHost.isEmpty()) {
|
||||
setFailedStatus(String.format("Host to refresh does not exist: %s", hostKey));
|
||||
return;
|
||||
}
|
||||
Instant now = clock.now();
|
||||
Host host = optionalHost.get();
|
||||
if (isDeleted(host, now)) {
|
||||
setFailedStatus(String.format("Host to refresh is already deleted: %s", host.getHostName()));
|
||||
return;
|
||||
}
|
||||
ImmutableSet<VKey<Domain>> linkedDomainKeys =
|
||||
getLinkedDomainKeys(hostKey, host.getUpdateTimestamp().getTimestamp(), null);
|
||||
for (List<VKey<Domain>> batch : Iterables.partition(linkedDomainKeys, DNS_REFRESH_BATCH_SIZE)) {
|
||||
tm().transact(
|
||||
() -> {
|
||||
ImmutableSet<String> domainNames =
|
||||
tm().loadByKeysIfPresent(batch).values().stream()
|
||||
.filter(Domain::shouldPublishToDns)
|
||||
.map(Domain::getDomainName)
|
||||
.collect(toImmutableSet());
|
||||
requestDomainDnsRefresh(domainNames);
|
||||
});
|
||||
}
|
||||
response.setStatus(SC_OK);
|
||||
}
|
||||
|
||||
if (!hostValid) {
|
||||
// Set the response status code to be 204 so to not retry.
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload(failureMessage);
|
||||
}
|
||||
});
|
||||
private void setFailedStatus(String message) {
|
||||
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
|
||||
response.setStatus(SC_NO_CONTENT);
|
||||
response.setPayload(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ public interface TransactionManager {
|
||||
* A runnable that allows for checked exceptions to be thrown.
|
||||
*
|
||||
* <p>This makes it easier to write lambdas without having to worry about wrapping and re-throwing
|
||||
* checked excpetions as unchecked ones.
|
||||
* checked exceptions as unchecked ones.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface ThrowingRunnable {
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
package google.registry.batch;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat;
|
||||
import static google.registry.batch.SyncRemoteCacheAction.SyncStatus.FAILURE;
|
||||
import static google.registry.batch.SyncRemoteCacheAction.SyncStatus.NOT_CONFIGURED;
|
||||
import static google.registry.batch.SyncRemoteCacheAction.SyncStatus.SUCCESS;
|
||||
import static google.registry.model.common.Cursor.CursorType.REMOTE_CACHE_DOMAIN_SYNC;
|
||||
import static google.registry.model.common.Cursor.CursorType.REMOTE_CACHE_HOST_SYNC;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
@@ -73,15 +77,24 @@ class SyncRemoteCacheActionTest {
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
createTld("tld");
|
||||
SyncRemoteCacheAction.SYNC_CACHE_RUNS_METRIC.reset();
|
||||
action = new SyncRemoteCacheAction(lockHandler, response, Optional.of(jedisClient));
|
||||
}
|
||||
|
||||
private static void verifyMetrics(SyncRemoteCacheAction.SyncStatus status) {
|
||||
assertThat(SyncRemoteCacheAction.SYNC_CACHE_RUNS_METRIC)
|
||||
.hasValueForLabels(1, status.name())
|
||||
.and()
|
||||
.hasNoOtherValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_noJedisConfig() {
|
||||
action = new SyncRemoteCacheAction(lockHandler, response, Optional.empty());
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
|
||||
assertThat(response.getPayload()).contains("No Jedis/Valkey configuration found");
|
||||
verifyMetrics(NOT_CONFIGURED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -91,6 +104,7 @@ class SyncRemoteCacheActionTest {
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
|
||||
assertThat(response.getPayload()).contains("Could not acquire lock");
|
||||
verifyMetrics(FAILURE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -100,6 +114,7 @@ class SyncRemoteCacheActionTest {
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_INTERNAL_SERVER_ERROR);
|
||||
assertThat(response.getPayload()).contains("Errored out with cause");
|
||||
verifyMetrics(FAILURE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -109,6 +124,7 @@ class SyncRemoteCacheActionTest {
|
||||
verifyNoInteractions(jedisClient);
|
||||
assertThat(DatabaseHelper.loadByKeyIfPresent(Cursor.createGlobalVKey(REMOTE_CACHE_DOMAIN_SYNC)))
|
||||
.isEmpty();
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -131,6 +147,7 @@ class SyncRemoteCacheActionTest {
|
||||
.getCursorTime()
|
||||
.toString())
|
||||
.isEqualTo("2025-01-01T00:00:00.001Z");
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -146,6 +163,7 @@ class SyncRemoteCacheActionTest {
|
||||
ImmutableList.of(
|
||||
new SimplifiedJedisClient.JedisResource<>("active.tld", activeDomain)));
|
||||
verify(jedisClient).deleteAll(Domain.class, ImmutableList.of("deleted.tld"));
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -166,6 +184,7 @@ class SyncRemoteCacheActionTest {
|
||||
verify(jedisClient)
|
||||
.setAll(
|
||||
ImmutableList.of(new SimplifiedJedisClient.JedisResource<>("example2.tld", domain2)));
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -175,6 +194,7 @@ class SyncRemoteCacheActionTest {
|
||||
verifyNoInteractions(jedisClient);
|
||||
assertThat(DatabaseHelper.loadByKeyIfPresent(Cursor.createGlobalVKey(REMOTE_CACHE_HOST_SYNC)))
|
||||
.isEmpty();
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -197,6 +217,7 @@ class SyncRemoteCacheActionTest {
|
||||
.getCursorTime()
|
||||
.toString())
|
||||
.isEqualTo("2025-01-01T00:00:00.001Z");
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -212,5 +233,6 @@ class SyncRemoteCacheActionTest {
|
||||
ImmutableList.of(
|
||||
new SimplifiedJedisClient.JedisResource<>(active.getRepoId(), active)));
|
||||
verify(jedisClient).deleteAll(Host.class, ImmutableList.of(deleted.getRepoId()));
|
||||
verifyMetrics(SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT;
|
||||
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||
@@ -52,7 +53,7 @@ public class RefreshDnsOnHostRenameActionTest {
|
||||
private RefreshDnsOnHostRenameAction action;
|
||||
|
||||
private void createAction(String hostKey) {
|
||||
action = new RefreshDnsOnHostRenameAction(hostKey, response);
|
||||
action = new RefreshDnsOnHostRenameAction(hostKey, response, clock);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@@ -99,4 +100,28 @@ public class RefreshDnsOnHostRenameActionTest {
|
||||
assertThat(response.getPayload())
|
||||
.isEqualTo("Host to refresh is already deleted: ns1.example.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_multipleBatches() {
|
||||
Host host = persistActiveHost("ns1.example.tld");
|
||||
ImmutableSet.Builder<String> domainNamesBuilder = new ImmutableSet.Builder<>();
|
||||
for (int i = 1; i <= 1001; i++) {
|
||||
String domainName = "example" + i + ".tld";
|
||||
domainNamesBuilder.add(domainName);
|
||||
persistResource(newDomain(domainName, host));
|
||||
}
|
||||
createAction(host.createVKey().stringify());
|
||||
action.run();
|
||||
assertDomainDnsRequests(Iterables.toArray(domainNamesBuilder.build(), String.class));
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_noLinkedDomains() {
|
||||
Host host = persistActiveHost("ns1.example.tld");
|
||||
createAction(host.createVKey().stringify());
|
||||
action.run();
|
||||
assertNoDnsRequests();
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ steps:
|
||||
|
||||
sed -i "s|artifactStorage: artifactStorage|artifactStorage: $artifact_storage|" "$target_file"
|
||||
sed -i "s|serviceAccount: serviceAccount|serviceAccount: $service_account|" "$target_file"
|
||||
sed -i "s|serviceAccount: serviceAccount|serviceAccount: $service_account|" release/clouddeploy/delivery-pipeline.yaml
|
||||
sed -i "s|cluster: cluster|cluster: $cluster_val|" "$target_file"
|
||||
sed -i "s|workerPool: workerPool|workerPool: $worker_pool|" "$target_file"
|
||||
fi
|
||||
|
||||
@@ -203,7 +203,7 @@ steps:
|
||||
--images="gcr.io/${PROJECT_ID}/nomulus=gcr.io/${PROJECT_ID}/nomulus@${nomulus_digest}" \
|
||||
--source=. \
|
||||
--skaffold-file=release/clouddeploy/skaffold.yaml \
|
||||
--deploy-parameters="deployed_image=gcr.io/${PROJECT_ID}/nomulus@${nomulus_digest},base_image=us-docker.pkg.dev/${PROJECT_ID}/gcr.io/nomulus"
|
||||
--deploy-parameters="deployed_image=gcr.io/${PROJECT_ID}/nomulus@${nomulus_digest},base_image=us-docker.pkg.dev/${PROJECT_ID}/gcr.io/nomulus,tag_name=${TAG_NAME},project_id=${PROJECT_ID}"
|
||||
# The tarballs and jars to upload to GCS.
|
||||
artifacts:
|
||||
objects:
|
||||
|
||||
@@ -236,11 +236,17 @@ steps:
|
||||
# partial phase manifests
|
||||
for stage in 1 5
|
||||
do
|
||||
if [ ${service} == backend ] || [ ${service} == console ]
|
||||
then
|
||||
replicas=1
|
||||
else
|
||||
replicas=${stage}
|
||||
fi
|
||||
awk 'NR==1,/^---$/ {if ($0 != "---") print}' ./jetty/kubernetes/nomulus-${env}-${service}.yaml | \
|
||||
sed s/name:\ ${service}/name:\ ${service}-partial-phase/g | \
|
||||
sed s/service:\ ${service}/deployment:\ ${service}-partial-phase/g | \
|
||||
sed s/value:\ ${service}/value:\ ${service}-partial-phase/g | \
|
||||
sed "/^spec:$/a\ replicas: ${stage}" \
|
||||
sed "/^spec:$/a\ replicas: ${replicas}" \
|
||||
> ./jetty/kubernetes/nomulus-${env}-${service}-partial-phase-${stage}.yaml
|
||||
done
|
||||
# gateway
|
||||
@@ -254,26 +260,11 @@ steps:
|
||||
> ./jetty/kubernetes/gateway/nomulus-backend-policy-${env}-${service}-canary.yaml
|
||||
done
|
||||
# Generate manifests for epp-server (which doesn't use HTTP gateway routing)
|
||||
for env in alpha crash qa sandbox production
|
||||
do
|
||||
if [ ${env} == production ]
|
||||
then
|
||||
project="domain-registry"
|
||||
else
|
||||
project="domain-registry-${env}"
|
||||
fi
|
||||
# non-canary
|
||||
sed s/GCP_PROJECT/${PROJECT_ID}/g ./jetty/kubernetes/nomulus-epp-server.yaml | \
|
||||
sed s/latest/${TAG_NAME}/g | \
|
||||
sed s/ENVIRONMENT/${env}/g > ./jetty/kubernetes/nomulus-${env}-epp-server.yaml
|
||||
# canary
|
||||
sed s/GCP_PROJECT/${PROJECT_ID}/g ./jetty/kubernetes/nomulus-epp-server.yaml | \
|
||||
sed s/latest/${TAG_NAME}/g | \
|
||||
sed s/ENVIRONMENT/${env}/g | \
|
||||
sed s/epp-server/epp-server-canary/g | \
|
||||
sed s/EPP-v2-ipv4-main/EPP-v2-ipv4-canary/g | \
|
||||
sed s/EPP-v2-ipv6-main/EPP-v2-ipv6-canary/g > ./jetty/kubernetes/nomulus-${env}-epp-server-canary.yaml
|
||||
done
|
||||
# Lowercase EPP-v2 to epp-v2 to match reserved static GCE IP names.
|
||||
sed s/GCP_PROJECT/${PROJECT_ID}/g ./jetty/kubernetes/nomulus-epp-server.yaml | \
|
||||
sed s/latest/${TAG_NAME}/g | \
|
||||
sed s/ENVIRONMENT/${env}/g | \
|
||||
sed s/EPP-v2/epp-v2/g > ./jetty/kubernetes/nomulus-${env}-epp-server.yaml
|
||||
done
|
||||
# Upload the Gradle binary to GCS if it does not exist and point URL in Gradle wrapper to it.
|
||||
- name: 'gcr.io/cloud-builders/gcloud'
|
||||
|
||||
@@ -5,7 +5,7 @@ This directory contains the Google Cloud Deploy configuration files for the Nomu
|
||||
## Files
|
||||
|
||||
### `delivery-pipeline.yaml`
|
||||
Defines the `DeliveryPipeline` resource named `deploy-nomulus`. It sets up the serial pipeline for rolling out changes to different targets.
|
||||
Defines the `DeliveryPipeline` resource named `deploy-nomulus` and its associated `Automation` resource (`deploy-nomulus/auto-advance-canary`). It sets up the serial pipeline for rolling out changes to different targets and automatically advancing canary rollouts.
|
||||
|
||||
### Target Configurations (e.g., `crash-target.yaml`)
|
||||
Files matching this format define the `Target` resources for Cloud Deploy. They specify the GKE cluster and other environment-specific settings for deployment.
|
||||
|
||||
@@ -14,17 +14,6 @@ serialPipeline:
|
||||
- phaseId: "canary-1"
|
||||
profiles: ["crash-partial-phase-1"]
|
||||
percentage: 10
|
||||
predeploy:
|
||||
tasks:
|
||||
- type: container
|
||||
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:stable
|
||||
env:
|
||||
TARGET_ID: ${{ target.id }}
|
||||
command: ["/bin/bash"]
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
gcloud builds submit --config=release/cloudbuild-schema-verify-${TARGET_ID}.yaml
|
||||
analysis:
|
||||
# 10 minutes.
|
||||
duration: 600s
|
||||
@@ -55,17 +44,20 @@ serialPipeline:
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
gcloud artifacts docker tags add $DEPLOYED_IMAGE \
|
||||
${BASE_IMAGE}:live-cd-${TARGET_ID}
|
||||
gcloud container images add-tag $DEPLOYED_IMAGE \
|
||||
${BASE_IMAGE}:live-cd-${TARGET_ID} --quiet
|
||||
- type: container
|
||||
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:stable
|
||||
env:
|
||||
TARGET_ID: ${{ target.id }}
|
||||
TAG_NAME: ${{ deploy_params['tag_name'] }}
|
||||
PROJECT_ID: ${{ deploy_params['project_id'] }}
|
||||
command: ["/bin/bash"]
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
gcloud builds submit --config=release/cloudbuild-schema-deploy-${TARGET_ID}.yaml
|
||||
gcloud storage cp gs://${PROJECT_ID}-deploy/${TAG_NAME}/cloudbuild-schema-deploy-${TARGET_ID}.yaml .
|
||||
gcloud builds submit --no-source --config=cloudbuild-schema-deploy-${TARGET_ID}.yaml
|
||||
analysis:
|
||||
# 10 minutes.
|
||||
duration: 600s
|
||||
@@ -86,11 +78,14 @@ serialPipeline:
|
||||
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:stable
|
||||
env:
|
||||
TARGET_ID: ${{ target.id }}
|
||||
TAG_NAME: ${{ deploy_params['tag_name'] }}
|
||||
PROJECT_ID: ${{ deploy_params['project_id'] }}
|
||||
command: ["/bin/bash"]
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
gcloud builds submit --config=release/cloudbuild-schema-verify-${TARGET_ID}.yaml
|
||||
gcloud storage cp gs://${PROJECT_ID}-deploy/${TAG_NAME}/cloudbuild-schema-verify-${TARGET_ID}.yaml .
|
||||
gcloud builds submit --no-source --config=cloudbuild-schema-verify-${TARGET_ID}.yaml
|
||||
analysis:
|
||||
# 10 minutes.
|
||||
duration: 600s
|
||||
@@ -121,20 +116,42 @@ serialPipeline:
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
gcloud artifacts docker tags add $DEPLOYED_IMAGE \
|
||||
${BASE_IMAGE}:live-cd-${TARGET_ID}
|
||||
gcloud container images add-tag $DEPLOYED_IMAGE \
|
||||
${BASE_IMAGE}:live-cd-${TARGET_ID} --quiet
|
||||
- type: container
|
||||
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:stable
|
||||
env:
|
||||
TARGET_ID: ${{ target.id }}
|
||||
TAG_NAME: ${{ deploy_params['tag_name'] }}
|
||||
PROJECT_ID: ${{ deploy_params['project_id'] }}
|
||||
command: ["/bin/bash"]
|
||||
args:
|
||||
- "-c"
|
||||
- |
|
||||
gcloud builds submit --config=release/cloudbuild-schema-deploy-${TARGET_ID}.yaml
|
||||
gcloud storage cp gs://${PROJECT_ID}-deploy/${TAG_NAME}/cloudbuild-schema-deploy-${TARGET_ID}.yaml .
|
||||
gcloud builds submit --no-source --config=cloudbuild-schema-deploy-${TARGET_ID}.yaml
|
||||
analysis:
|
||||
# 10 minutes.
|
||||
duration: 600s
|
||||
googleCloud:
|
||||
alertPolicyChecks:
|
||||
sandboxStableDeploymentAlertPolicyChecks
|
||||
---
|
||||
apiVersion: deploy.cloud.google.com/v1
|
||||
kind: Automation
|
||||
metadata:
|
||||
name: deploy-nomulus/auto-advance-canary
|
||||
description: Automatically advances rollouts through canary-1 phase after successful deployment and analysis.
|
||||
# Placeholder: Replace with project service account.
|
||||
serviceAccount: serviceAccount
|
||||
selector:
|
||||
targets:
|
||||
- id: crash
|
||||
- id: sandbox
|
||||
rules:
|
||||
- advanceRolloutRule:
|
||||
id: advance-canary-phases
|
||||
sourcePhases:
|
||||
- "canary-1"
|
||||
wait: 0m
|
||||
|
||||
|
||||
Reference in New Issue
Block a user