Skip to content

Commit

Permalink
Fix #49: Replace mail sending with GitHub issue creation (#176)
Browse files Browse the repository at this point in the history
  • Loading branch information
TWiStErRob authored May 5, 2024
1 parent 52f4cb7 commit 4d3fd4c
Show file tree
Hide file tree
Showing 40 changed files with 895 additions and 183 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/automated-alert.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: "Automated alert"

on:
issues:
types:
- labeled

jobs:
comment:
name: "Comment to notify"
if: ${{ github.event.label.name == 'is:automated' }}
timeout-minutes: 2

permissions:
issues: write

runs-on: ubuntu-latest
steps:
- name: "Comment on issue to trigger notification."
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
COMMENT_BODY: |
Automated notification alert.
-- _This comment was created by a [GitHub Actions Workflow][workflow]'s [run][run]._
[workflow]: ${{ github.server_url }}/${{ github.repository }}/actions/workflows/automated-alert.yml
[run]: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
shell: bash
run:
gh issue comment "${ISSUE_NUMBER}" --body "${COMMENT_BODY}"

This file was deleted.

18 changes: 0 additions & 18 deletions android/app/full/src/main/java/net/twisterrob/blt/android/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.widget.Toast;

import androidx.annotation.NonNull;

import net.twisterrob.android.AndroidConstants;
import net.twisterrob.android.app.BaseApp;
import net.twisterrob.android.log.AndroidLoggerFactory;
import net.twisterrob.android.utils.concurrent.BackgroundExecution;
import net.twisterrob.android.utils.concurrent.MailSenderAsyncTask;
import net.twisterrob.android.utils.tostring.stringers.detailed.RangeStringers;
import net.twisterrob.blt.android.app.full.BuildConfig;
import net.twisterrob.blt.android.data.AndroidDBStaticData;
Expand Down Expand Up @@ -80,21 +77,6 @@ public AndroidStaticData getStaticData() {
return m_static;
}

public static void sendMail(String body) {
@SuppressWarnings({"unused", "deprecation"}) // TODO https://github.com/TWiStErRob/net.twisterrob.travel/issues/15
Object task = new MailSenderAsyncTask("Better London Travel",
"[email protected]", "[email protected]") {
@Override protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (Boolean.TRUE.equals(result)) {
Toast.makeText(getInstance(), "Mail sent", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getInstance(), "Mail failed", Toast.LENGTH_SHORT).show();
}
}
}.execute(body);
}

@SuppressWarnings("deprecation")
@Override public Injector injector() {
return new net.twisterrob.blt.android.ui.activity.Injector(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
import org.xml.sax.helpers.DefaultHandler;

import net.twisterrob.java.exceptions.StackTrace;
import net.twisterrob.java.io.MailSender;
import net.twisterrob.java.io.FeedbackSender;

public abstract class BaseFeedHandler<T extends BaseFeed<T>> extends DefaultHandler implements FeedHandler<T> {
public final Logger LOG = LoggerFactory.getLogger(getClass());

protected static void sendMail(String body) {
MailSender sender = new MailSender();
sender.setSubject("Better London Travel");
sender.setFrom("[email protected]");
sender.setTos("[email protected]");
sender.setBody(body);
protected static void sendFeedback(String title, String body) {
String envs = System.getProperty("micronaut.environments");
if (envs == null || !envs.contains("production")) {
throw new IllegalStateException("Immediate feedback: " + title + "\n" + body);
}
FeedbackSender sender = new FeedbackSender();
try {
sender.send();
sender.send(title, body);
} catch (Exception e) {
String callingClass = new StackTrace().getStackTrace()[1].getClassName();
Logger log = LoggerFactory.getLogger(callingClass);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package net.twisterrob.java.io;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class FeedbackSender {

public void send(@Nullable String title, @Nonnull String body) throws IOException {
try {
URL url = buildUrl(title);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.connect();
try {
IOTools.writeAll(conn.getOutputStream(), body);
InputStream response = new BufferedInputStream(conn.getInputStream());
String result = IOTools.readAll(response, "UTF-8");
if (!result.trim().isEmpty()) {
throw new IOException("Server responded with: " + result);
}
} finally {
conn.disconnect();
}
} catch (IOException ex) {
throw new IOException("Cannot send " + title, ex);
}
}

private static @Nonnull URL buildUrl(String title)
throws UnsupportedEncodingException, MalformedURLException {
String titleQuery;
if (title != null) {
String escapedTitle = URLEncoder.encode(title, "UTF-8");
titleQuery = "title=" + escapedTitle;
} else {
titleQuery = "";
}
return new URL(
"https://twisterrob-london.appspot.com/InternalFeedback?"
+ titleQuery
);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,15 @@ public void end(String body) {
}
});
stationServingLine.setEndTextElementListener(new EndTextElementListener() {
@SuppressWarnings("synthetic-access")
@Override public void end(String body) {
Line line = Line.unknown;
if (body != null) {
line = trackerNetData.fromAlias(body);
if (line == Line.unknown) {
sendMail(Line.class + " new alias: " + body);
sendFeedback(
"New line alias: " + body,
Line.class + " new alias: " + body
);
}
}
m_station.getLines().add(line);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ public class LineStatusFeedHandler extends BaseFeedHandler<LineStatusFeed> {
if (attrName != null) {
line = trackerNetData.fromAlias(attrName);
if (line == net.twisterrob.blt.model.Line.unknown) {
sendMail(net.twisterrob.blt.model.Line.class + " new alias: " + attrName);
sendFeedback(
"New line alias: " + attrName,
net.twisterrob.blt.model.Line.class + " new alias: " + attrName
);
}
}
m_lineStatus.setLine(line);
Expand All @@ -85,7 +88,10 @@ public class LineStatusFeedHandler extends BaseFeedHandler<LineStatusFeed> {
statusType = trackerNetData.delayFromTrackerNetCode(attrId);
if (statusType == DelayType.Unknown) {
String attrDescription = attributes.getValue(Status.description);
sendMail(DelayType.class + " new code: " + attrDescription + " as " + attrId);
sendFeedback(
"New delay type:" + attrId,
DelayType.class + " new code: " + attrDescription + " as " + attrId
);
}
}
String attrIsActive = attributes.getValue(Status.id);
Expand Down
1 change: 1 addition & 0 deletions common/test-helpers/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies {
exclude group: "junit", module: "junit"
}
api(libs.test.mockito)
api(libs.test.mockito.kotlin)
api(libs.test.mockito.junit5)
api(libs.test.gwen)
implementation(projects.common.logConsole)
Expand Down
8 changes: 5 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ google-cloud = "26.38.0"
# Run `gcloud components update` to get the new available version.
# (or `gcloud components update --version <version>` to revert)
# https://cloud.google.com/sdk/docs/release-notes
google-cloud-sdk = "455.0.0"
google-cloud-sdk = "474.0.0"
# https://cloud.google.com/appengine/docs/standard/java/release-notes
google-appengine = "2.0.26"
google-appengine-plugin = "2.8.0"
google-maps = "18.2.0"
google-places = "3.4.0"
google-datastore = "2.19.1"

micronaut = "4.4.2"
micronaut-gradle = "4.3.8"
Expand All @@ -42,6 +41,7 @@ junit4 = "4.13.2"
junit5 = "5.10.2"
kotest = "5.8.1"
mockito = "5.11.0"
mockito-kotlin = "5.3.1"
mockative = "2.2.0"
# Use this instead of 1.3
# If `hamcrest-1.3` appears in the dependency list, check if it's excluded from all usages.
Expand Down Expand Up @@ -81,7 +81,8 @@ slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
log4j-slf4j2 = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" }

google-cloud = { module = "com.google.cloud:libraries-bom", version.ref = "google-cloud" }
google-cloud-datastore = { module = "com.google.cloud:google-cloud-datastore", version.ref = "google-datastore" }
google-cloud-datastore = { module = "com.google.cloud:google-cloud-datastore" } # version is BOM managed.
google-cloud-secrets = { module = "com.google.cloud:google-cloud-secretmanager" } # version is BOM managed.
appengine-api = { module = "com.google.appengine:appengine-api-1.0-sdk", version.ref = "google-appengine" }
gms-places = { module = "com.google.android.libraries.places:places", version.ref = "google-places" }
gms-maps = { module = "com.google.android.gms:play-services-maps", version.ref = "google-maps" }
Expand All @@ -94,6 +95,7 @@ test-kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.
test-mockative = { module = "io.mockative:mockative", version.ref = "mockative" }
test-mockative-processor = { module = "io.mockative:mockative-processor", version.ref = "mockative" }
test-mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" }
test-mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockito-kotlin" }
test-mockito-junit5 = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" }
test-hamcrest = { module = "org.hamcrest:hamcrest-junit", version.ref = "hamcrest" }
test-gwen = { module = "com.shazam:gwen", version.ref = "gwen" }
Expand Down
23 changes: 20 additions & 3 deletions web/status-history/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,30 @@
gcloud components install beta
```
3. Run the datastore emulator in the background:
```
```shell
gcloud --project twisterrob-travel beta emulators datastore start --no-store-on-disk
```
4. In a separate window run:
```
```shell
gcloud beta emulators datastore env-init
```
5. Set the output environment variables before running `gradlew :web:status-history:run`.

Note: step 4 and 5 are automated in `build.gradle` and in "Run status-history server" IDEA run configuration.
Note: step 4 and 5 are automated in `build.gradle` and in "Run status-history server" IDEA run configuration.

## Running with secrets access

* Docs: https://cloud.google.com/docs/authentication/provide-credentials-adc#local-dev

1. Install the [Google Cloud SDK](https://cloud.google.com/sdk/).
2. Provide Application Default Credentials (ADC)
```shell
gcloud auth application-default login
```
This stores credentials at %APPDATA%\gcloud\application_default_credentials.json
3. There might be a warning like this:
> Cannot find a quota project to add to ADC.
> You might receive a "quota exceeded" or "API not enabled" error.
> Run $ gcloud auth application-default set-quota-project to add a quota project.
This is safe to ignore for local secrets usage.
Loading

0 comments on commit 4d3fd4c

Please sign in to comment.