Enable SwiftLint only for the new files - ios

I have a pretty huge iOS(legacy) project in which I want to add SwiftLint. All the rules I wish to enforce, I would enforce only on new created files. In that way I do not have to go back and fix all the problems that would come up because the rules have not been followed in the past (as there was no SwiftLint in use). I am not sure how to achieve this?

you can run a script like this
# Run SwiftLint
START_DATE=$(date +"%s")
SWIFT_LINT=/usr/local/bin/swiftlint
# Run SwiftLint for given filename
run_swiftlint() {
local filename="${1}"
if [[ "${filename##*.}" == "swift" ]]; then
#${SWIFT_LINT} autocorrect --path "${filename}"
${SWIFT_LINT} lint --path "${filename}"
fi
}
if [[ -e "${SWIFT_LINT}" ]]; then
echo "SwiftLint version: $(${SWIFT_LINT} version)"
# Run for both staged and unstaged files
git diff --name-only | while read filename; do run_swiftlint "${filename}"; done
git diff --cached --name-only | while read filename; do run_swiftlint "${filename}"; done
else
echo "${SWIFT_LINT} is not installed."
exit 0
fi
END_DATE=$(date +"%s")
DIFF=$(($END_DATE - $START_DATE))
echo "SwiftLint took $(($DIFF / 60)) minutes and $(($DIFF % 60)) seconds to complete."
Simply add a build phase run script to Xcode with the following
"${SRCROOT}/Scripts/swiftlint.sh"
It comes from here https://github.com/realm/SwiftLint/issues/413#issuecomment-184077062
It doesn't work on the M1 chip because you need to say something like this
if test -d "/opt/homebrew/bin/"; then
PATH="/opt/homebrew/bin/:${PATH}"
fi
export PATH
if which swiftlint >/dev/null; then
swiftlint
else
echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fine
based on this blog https://www.anotheriosdevblog.com/installing-swiftlint-on-a-m1/

If you are using feature branches you can run it as follows:
swiftlint --config PATH/TO/CONFIG/.swiftlint.yml $(git diff develop --name-only | grep .swift)

Related

Trigger specific job on push to specific directory

We have 12 different projects inside the same repository and have a different job to run for each of these.
I want to know how I can trigger a job only when a change has happened in a specific folder, since running all 12 on every push takes too long to finish.
Well I have hacked a solution that works for us.
First, add an Execute Shell Build Step:
#!/bin/bash
export DIRS="api objects"
DIFF=`git diff --name-only develop`
echo "export RUN_TEST=0" > "$WORKSPACE/RUN_TEST"
for DIR in $DIRS; do
for LINE in $DIFF; do
# Is this file inside an interesting directory?
echo $LINE | grep -e "^$DIR/"
# Checking if it is inside
if [ $? -eq 0 ]; then
echo "export RUN_TEST=1" > "$WORKSPACE/RUN_TEST"
fi
done
done
Here:
api and objects are the 2 directories I want to trigger this Job
develop is the main branch we use, so I want to know how my directories compare to that branch in particular
I create a file $WORKSPACE/RUN_TEST to set a variable if I should or not run it
Then in the time-consuming build steps add:
#!/bin/sh
. "$WORKSPACE/RUN_TEST"
if [ $RUN_TEST -eq 1 ]; then
# Time consuming code here
fi
That way the job is triggered but runs as fast as if it wasn't triggered.
Now I modified it to:
#!/bin/bash
export DIRS="api objects"
DIFF=`git diff --name-only origin/develop`
RUN_TEST=111
for DIR in $DIRS; do
for LINE in $DIFF; do
# Is this file inside an interesting directory?
echo $LINE | grep -e "^$DIR/"
# Checking if it is inside
if [ $? -eq 0 ]; then
RUN_TEST=0
fi
done
done
echo "RUN_TEST=$RUN_TEST"
echo "return $RUN_TEST" > "$WORKSPACE/RUN_TEST"
exit $RUN_TEST
And set Exit code to set build unstable to 111 on all build steps. Then, in all following build steps I did:
#!/bin/bash
# Exit on any error
set -euo pipefail
. "$WORKSPACE/RUN_TEST"
# Rest of build step

Best practice for using Fabric/Crashlytics with open-source app?

I have an iOS app that I'm about to open source. I don't want to include my key and secret in the Run Script code when the the app is live for everyone to look at, fork, download etc. for obvious reasons.
What is the best way to still use Fabric/Crashlytics but also keep those keys secure so that only those who can deploy the app have access to those credentials?
Here's a way:
1 - Store fabric keys in a local file.
<apiKey>
<secretKey>
2 - In your cocoa pods run script phase (under Build Phases in Xcode), have your script grab the api key and secret key from the local file.
apiKey=$(sed -n '1p' < localFile.txt)
secretKey=$(sed -n '2p' < localFile.txt)
3 - Use PlistBuddy in the cocoa pods run script phase to set the API Key into your Info.plist file. Something like this:
/usr/libexec/PlistBuddy -c "Set :Fabric:APIKey string $apiKey" $(PROJECT_DIR)/Info.plist
4 - Call the cocoa pods run command.
"${PODS_ROOT}/Fabric/run" $apiKey $secretKey
Edit: full script
apiKey=$(sed -n '1p' < localFile.txt)
secretKey=$(sed -n '2p' < localFile.txt)
/usr/libexec/PlistBuddy -c "Set :Fabric:APIKey string $apiKey" $(PROJECT_DIR)/Info.plist
"${PODS_ROOT}/Fabric/run" $apiKey $secretKey
NOTE -
$(PROJECT_DIR)/Info.plist may not be the correct path for your particular project.
Jake's answer didn't work for me. Apparently $(PROJECT_DIR)/Info.plist returns an incorrect path.
But here's a working example for a project that uses both Fabric and Google sign in. (This works perfectly in Xcode 9 as of July 2018)
FabricApiKey=$(sed -n '2p' < app_config.txt)
FabricSecretKey=$(sed -n '4p' < app_config.txt)
GoogleReversedClientId=$(sed -n '6p' < app_config.txt)
INFO_PLIST="$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH"
/usr/libexec/PlistBuddy -c "Set :Fabric:APIKey $FabricApiKey" "$INFO_PLIST"
/usr/libexec/PlistBuddy -c "Set :CFBundleURLTypes:0:CFBundleURLSchemes:0 $GoogleReversedClientId" "$INFO_PLIST"
"${PODS_ROOT}/Fabric/run" $FabricApiKey $FabricSecretKey
and here's the structure of app_config.txt file that must be present at the project root:
FabricApiKey:
your_key_here
FabricSecretKey:
your_secret_here
GoogleReversedClientId:
google_reversed_client_id_here
Excellent post by #Jake - thank-you! This is my variation which checks for the existence of the secrets file, and uses some environment variables provided by Xcode 9.4.
#1/usr/bin/env sh
secretsFile=$PROJECT_DIR/scripts/fabric.secrets
if [ ! -f $secretsFile ]; then
echo "warning: '$secretsFile' not found"
exit 0
fi
apiKey=$(sed -n '1p' < $secretsFile)
secretKey=$(sed -n '2p' < $secretsFile)
/usr/libexec/PlistBuddy -c "Set :Fabric:APIKey $apiKey" $PRODUCT_SETTINGS_PATH
$PROJECT_DIR/Fabric.framework/run $apiKey $secretKey
Note: the echo "warning: " part will be detected by Xcode, and put into the build log as a yellow warning.
Finally, here's a pre-commit git hook to check for a 40-character hex string accidentally being added to the Info.plist:
#!/usr/bin/env sh
files=$(ls */Info.plist)
git diff --cached --name-status | while read modificationtype thisfile; do
if [ "$modificationtype" == 'D' ]; then continue; fi
for file in $files
do
if [ ! "$thisfile" == "$file" ]; then continue; fi
if egrep '[0-9a-fA-F]{40}' $file ; then
echo "ERROR: API key in file: ${file}"
exit 1
fi
done
done || exit $?

Create symlinks instead of copy with maven-dependency-plugin : copy-dependencies

I work on a Maven project that need to copy mode than 10 GB of artifacts in a target repository from a maven local repository (after downloaded them).
In some cases (e.g. for tests), I'd like to replace this copy by a symlink creation in order to save few minutes.
My question is: Is there a way to ask to plugin maven-dependency-plugin goal copy-dependencies to create a symlink OR is there any maven plugin that can do it.
The copy-dependencies goal cannot, to my knowledge, do this out of the box. However, you can use a shell script:
#!/bin/sh
outputDir=target/dependency
mkdir -p "$outputDir"
mvn dependency:resolve |
grep ':\(compile\|runtime\)' | sed 's/\[INFO\] *//' |
while read gav
do
case "$gav" in
*:*:*:*:*:*) # G:A:P:C:V:S
g="${gav%%:*}"; remain="${gav#*:}"
a="${remain%%:*}"; remain="${remain#*:}"
p="${remain%%:*}"; remain="${remain#*:}"
c="${remain%%:*}"; remain="${remain#*:}"
v="${remain%%:*}"
s="${remain#*:}"
;;
*:*:*:*:*) # G:A:P:V:S
g="${gav%%:*}"; remain="${gav#*:}"
a="${remain%%:*}"; remain="${remain#*:}"
p="${remain%%:*}"; remain="${remain#*:}"
c=""
v="${remain%%:*}"
s="${remain#*:}"
;;
esac
g=$(echo "$g" | sed 's/\./\//g')
test -n "$c" && artName="$a-$v-$c" || artName="$a-$v"
ln -s "$HOME/.m2/repository/$g/$a/$v/$artName.$p" "$outputDir"
done

error with Uncrustify in xcode for an ios app

I have installed the uncrustify through brew (as per the git instructions), and I have added the run script build phase to the xcode and tried to build an ios project, but the build is failing with the following error:
**/bin/sh: /Users/test/Library/Developer/Xcode/DerivedData/testProj- amlbymrfycxuzmemclwtovltjxzl/Build/Intermediates/testProj.build/Debug-iphoneos/testProj.build/Script-AC898878187BE0A00056CAB1.sh: sh: bad interpreter: No such file or directory**
How can I resolve this error? Any help would be appreciated. Thanks in advance.
My sh script:
if [ -n "$1" ]
then
# recover directory to format :
pathToSourcesDirectory=`echo $(pwd)/$1`
# go to current folder :
scriptDirectory=$(dirname $0)
cd $scriptDirectory
# find sources files to format :
echo ""
echo "==> Getting files to format in directory " + $pathToSourcesDirectory
mkdir -p temp
find $pathToSourcesDirectory -name "*.[mh]" > temp/sources_to_uncrustify.txt
# format files :
echo ""
echo "==> Format files"
/usr/local/bin/uncrustify -F temp/sources_to_uncrustify.txt -c "../uncrustify_objective_c.cfg" --no-backup
# remove temp files :
rm -rf temp/
else
echo "Error : You must specify a source folder as first parameter"
fi
It looks like you don't have Shell set to /bin/sh in the Xcode Run Script configuration:
(screenshot taken from here).

Is there a good macvim git diff?

I have been using textmate for many years and I just made the switch to macvim and one thing that I used all the time with textmate was the command git df which in my .gitconfig was just an alias for
[alias]
df = !git diff | mate
and what that did was give me a screen like this
Is there a replacement in mvim that I can add somewhere for me to get similar behavior
I describe what I use here.
Basically, add the following lines to your "~/.gitconfig":
[diff]
tool = default-difftool
[difftool "default-difftool"]
cmd = default-difftool.sh $LOCAL $REMOTE
With the following wrapper script:
#! /bin/bash
if [[ -f /Applications/MacVim.app/Contents/MacOS/Vim ]]
then
# bypass mvim for speed
VIMPATH='/Applications/MacVim.app/Contents/MacOS/Vim -g -dO -f'
elif [[ -f /usr/local/bin/mvim ]]
then
# fall back to mvim
VIMPATH='mvim -d -f'
else
# fall back to original vim
VIMPATH='vimdiff'
fi
$VIMPATH $#
You can get the diff one file at a time by doing:
git difftool -t vimdiff
vimdiff can be replaced with gvimdiff for gvim, so I would assume you can also replace it with mvimdiff for macvim.
I am not sure of a way to pipe the entirety of git diff into vim though.

Resources